@elevasis/ui 2.20.0 → 2.22.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 (100) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/app/index.js +5 -5
  3. package/dist/charts/index.js +3 -3
  4. package/dist/{chunk-TO7QXDBX.js → chunk-3HEUGBOT.js} +3 -3
  5. package/dist/chunk-AXXTN44Z.js +26 -0
  6. package/dist/{chunk-FMFX4K6E.js → chunk-B4FHWKEF.js} +3390 -2929
  7. package/dist/{chunk-AL23U6C3.js → chunk-BIWHHWCJ.js} +1 -2
  8. package/dist/{chunk-MZFJWCPH.js → chunk-BSZRKBAW.js} +277 -92
  9. package/dist/{chunk-GP3AFJYG.js → chunk-COG4ABRI.js} +8 -13
  10. package/dist/chunk-DDZOHLHB.js +48 -0
  11. package/dist/{chunk-ZE2KQSHL.js → chunk-GJ7EIABJ.js} +4 -4
  12. package/dist/{chunk-YP6T426C.js → chunk-IBUYJXA3.js} +1326 -1110
  13. package/dist/{chunk-2CFOFSSG.js → chunk-IOTLB6ND.js} +8 -13
  14. package/dist/{chunk-GBMNCNHX.js → chunk-KVJ3LFH2.js} +3 -1
  15. package/dist/chunk-LJWV4TWV.js +335 -0
  16. package/dist/{chunk-PJVG3ISO.js → chunk-LKVBEE63.js} +7 -9
  17. package/dist/{chunk-JR5WNTLA.js → chunk-LVJGPE6H.js} +11 -24
  18. package/dist/{chunk-OUYH2SBS.js → chunk-LVUCBY7X.js} +2 -2
  19. package/dist/{chunk-TIIPYB2Z.js → chunk-QZJM3RYI.js} +1 -1
  20. package/dist/{chunk-OD7GWIZS.js → chunk-SGXXJE52.js} +1 -121
  21. package/dist/{chunk-7YQKVWSD.js → chunk-SQ5JGELM.js} +25 -5
  22. package/dist/{chunk-R7OJCNL3.js → chunk-T6INEVX6.js} +1 -1
  23. package/dist/{chunk-RX4UWZZR.js → chunk-TKAYX2SP.js} +8 -3
  24. package/dist/{chunk-CTTY6FUT.js → chunk-TSSKOQBX.js} +2 -2
  25. package/dist/{chunk-GTYUP7MB.js → chunk-WWJ6S2HQ.js} +10 -22
  26. package/dist/{chunk-Q5HC6ENG.js → chunk-XOTJNW4Q.js} +1 -1
  27. package/dist/{chunk-BHR7IV72.js → chunk-XUYBOO32.js} +1 -1
  28. package/dist/{chunk-M7W7CGPL.js → chunk-Z6FAH4XV.js} +1 -1
  29. package/dist/{chunk-Q4QJOSVS.js → chunk-ZBCTB5CA.js} +1 -1
  30. package/dist/components/index.css +85 -85
  31. package/dist/components/index.d.ts +970 -746
  32. package/dist/components/index.js +246 -39
  33. package/dist/components/navigation/index.css +589 -0
  34. package/dist/components/navigation/index.d.ts +1 -13
  35. package/dist/components/navigation/index.js +11 -1
  36. package/dist/execution/index.d.ts +27 -0
  37. package/dist/features/auth/index.css +2 -2
  38. package/dist/features/auth/index.d.ts +184 -3
  39. package/dist/features/crm/index.css +2 -2
  40. package/dist/features/crm/index.d.ts +201 -38
  41. package/dist/features/crm/index.js +15 -14
  42. package/dist/features/dashboard/index.css +2 -2
  43. package/dist/features/dashboard/index.d.ts +25 -27
  44. package/dist/features/dashboard/index.js +15 -14
  45. package/dist/features/delivery/index.css +85 -85
  46. package/dist/features/delivery/index.d.ts +201 -38
  47. package/dist/features/delivery/index.js +15 -14
  48. package/dist/features/lead-gen/index.css +2 -2
  49. package/dist/features/lead-gen/index.d.ts +19 -37
  50. package/dist/features/lead-gen/index.js +15 -14
  51. package/dist/features/monitoring/index.css +85 -85
  52. package/dist/features/monitoring/index.d.ts +18 -36
  53. package/dist/features/monitoring/index.js +17 -16
  54. package/dist/features/monitoring/requests/index.css +2 -2
  55. package/dist/features/monitoring/requests/index.d.ts +18 -36
  56. package/dist/features/monitoring/requests/index.js +15 -14
  57. package/dist/features/operations/index.css +2 -2
  58. package/dist/features/operations/index.d.ts +49 -67
  59. package/dist/features/operations/index.js +18 -17
  60. package/dist/features/seo/index.d.ts +17 -35
  61. package/dist/features/seo/index.js +1 -1
  62. package/dist/features/settings/index.css +2 -2
  63. package/dist/features/settings/index.d.ts +222 -44
  64. package/dist/features/settings/index.js +16 -15
  65. package/dist/graph/index.css +2 -2
  66. package/dist/hooks/delivery/index.css +2 -2
  67. package/dist/hooks/delivery/index.d.ts +184 -3
  68. package/dist/hooks/delivery/index.js +2 -2
  69. package/dist/hooks/index.css +85 -85
  70. package/dist/hooks/index.d.ts +1862 -1582
  71. package/dist/hooks/index.js +13 -12
  72. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +92 -121
  73. package/dist/hooks/published.css +85 -85
  74. package/dist/hooks/published.d.ts +1862 -1582
  75. package/dist/hooks/published.js +13 -12
  76. package/dist/index.css +12 -12
  77. package/dist/index.d.ts +689 -470
  78. package/dist/index.js +14 -13
  79. package/dist/initialization/index.d.ts +184 -3
  80. package/dist/layout/index.js +2 -2
  81. package/dist/organization/index.css +589 -0
  82. package/dist/organization/index.js +1 -1
  83. package/dist/profile/index.d.ts +184 -3
  84. package/dist/provider/index.css +384 -0
  85. package/dist/provider/index.d.ts +68 -125
  86. package/dist/provider/index.js +11 -10
  87. package/dist/provider/published.css +463 -0
  88. package/dist/provider/published.d.ts +68 -125
  89. package/dist/provider/published.js +8 -7
  90. package/dist/supabase/index.d.ts +359 -6
  91. package/dist/test-utils/index.d.ts +46 -2
  92. package/dist/test-utils/index.js +104 -3
  93. package/dist/theme/index.js +2 -2
  94. package/dist/types/index.d.ts +303 -141
  95. package/dist/utils/index.d.ts +26 -59
  96. package/dist/utils/index.js +1 -1
  97. package/package.json +4 -4
  98. package/dist/chunk-LR5CRY5A.js +0 -514
  99. package/dist/chunk-MG3NF7QL.js +0 -63
  100. /package/dist/{chunk-6GUW5GGF.js → chunk-6Z3G4U2R.js} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { IconBrain } from '@tabler/icons-react';
2
+ import { z } from 'zod';
2
3
 
3
4
  /**
4
5
  * Date formatting utilities for consistent date display across the application
@@ -130,8 +131,10 @@ interface ResourceDefinition {
130
131
  type: ResourceType;
131
132
  /** Environment/deployment status */
132
133
  status: ResourceStatus;
133
- /** Domain tags for filtering and organization */
134
- domains?: ResourceDomain[];
134
+ /** Graph links to Organization Model nodes */
135
+ links?: ResourceLink[];
136
+ /** Infrastructure category for filtering */
137
+ category?: ResourceCategory;
135
138
  /** Whether the agent supports multi-turn sessions (agents only) */
136
139
  sessionCapable?: boolean;
137
140
  /** Whether the resource is local (monorepo) or remote (externally deployed) */
@@ -139,64 +142,28 @@ interface ResourceDefinition {
139
142
  /** Whether this resource is archived and should be excluded from registration and deployment */
140
143
  archived?: boolean;
141
144
  }
142
- /**
143
- * Domain definition for Command View filtering
144
- *
145
- * Domains are organizational metadata for UI filtering/grouping.
146
- * No execution impact - purely for visualization.
147
- *
148
- * @example
149
- * {
150
- * id: 'support',
151
- * name: 'Customer Support',
152
- * description: 'Ticket triage, knowledge base, escalations',
153
- * color: 'green',
154
- * icon: 'IconHeadset'
155
- * }
156
- */
157
- interface DomainDefinition {
158
- /** Unique identifier (e.g., 'support') */
159
- id: string;
160
- /** Display name (e.g., 'Customer Support') */
161
- name: string;
162
- /** Purpose description */
163
- description: string;
164
- /** Optional Mantine color for UI (e.g., 'blue', 'green', 'orange') */
165
- color?: string;
166
- /** Optional Tabler icon name (e.g., 'IconHeadset') */
167
- icon?: string;
168
- }
169
145
 
170
- /**
171
- * Standard Domain Definitions
172
- * Centralized domain constants and definitions for all organization resources.
173
- */
146
+ declare const LinkSchema: z.ZodObject<{
147
+ nodeId: z.ZodString;
148
+ kind: z.ZodEnum<{
149
+ contains: "contains";
150
+ references: "references";
151
+ exposes: "exposes";
152
+ maps_to: "maps_to";
153
+ "operates-on": "operates-on";
154
+ uses: "uses";
155
+ }>;
156
+ }, z.core.$strip>;
157
+ type Link = z.infer<typeof LinkSchema>;
174
158
 
175
- declare const DOMAINS: {
176
- readonly INBOUND_PIPELINE: "inbound-pipeline";
177
- readonly LEAD_GEN_PIPELINE: "lead-gen-pipeline";
178
- readonly SUPPORT: "support";
179
- readonly CLIENT_SUPPORT: "client-support";
180
- readonly DELIVERY: "delivery";
181
- readonly OPERATIONS: "operations";
182
- readonly FINANCE: "finance";
183
- readonly EXECUTIVE: "executive";
184
- readonly INSTANTLY: "instantly";
185
- readonly TESTING: "testing";
186
- readonly INTERNAL: "internal";
187
- readonly INTEGRATION: "integration";
188
- readonly UTILITY: "utility";
189
- readonly DIAGNOSTIC: "diagnostic";
190
- };
191
- /**
192
- * ResourceDomain - Strongly typed domain identifier
193
- * Use this type for all domain references to ensure compile-time validation.
194
- */
195
- type ResourceDomain = (typeof DOMAINS)[keyof typeof DOMAINS];
196
- /**
197
- * Domain lookup map for O(1) access during serialization
198
- */
199
- declare const DOMAIN_MAP: Record<ResourceDomain, DomainDefinition>;
159
+ declare const ResourceCategorySchema: z.ZodEnum<{
160
+ production: "production";
161
+ diagnostic: "diagnostic";
162
+ internal: "internal";
163
+ testing: "testing";
164
+ }>;
165
+ type ResourceCategory = z.infer<typeof ResourceCategorySchema>;
166
+ type ResourceLink = Link;
200
167
 
201
168
  /**
202
169
  * Resource Type Metadata
@@ -375,5 +342,5 @@ declare function restoreConsole(): void;
375
342
 
376
343
  declare function setupBrowserMocks(): void;
377
344
 
378
- export { APIClientError, API_URL, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, DOMAIN_MAP, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, ResourceStatusColors, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail };
345
+ export { APIClientError, API_URL, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, ResourceStatusColors, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail };
379
346
  export type { TablerIcon };
@@ -1,3 +1,3 @@
1
- export { APIClientError, API_URL, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, DOMAIN_MAP, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail } from '../chunk-OD7GWIZS.js';
1
+ export { APIClientError, API_URL, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail } from '../chunk-SGXXJE52.js';
2
2
  export { ResourceStatusColors } from '../chunk-KRWALB24.js';
3
3
  import '../chunk-I2KLQ2HA.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/ui",
3
- "version": "2.20.0",
3
+ "version": "2.22.0",
4
4
  "description": "UI components and platform-aware hooks for building custom frontends on the Elevasis platform",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -225,9 +225,9 @@
225
225
  "@testing-library/jest-dom": "^6.9.1",
226
226
  "msw": "^2.11.0",
227
227
  "vitest": "^3.2.4",
228
- "@repo/core": "0.10.0",
229
- "@repo/typescript-config": "0.0.0",
230
- "@repo/eslint-config": "0.0.0"
228
+ "@repo/core": "0.12.0",
229
+ "@repo/eslint-config": "0.0.0",
230
+ "@repo/typescript-config": "0.0.0"
231
231
  },
232
232
  "dependencies": {
233
233
  "@dagrejs/dagre": "^1.1.4",
@@ -1,514 +0,0 @@
1
- import { SubshellContainer, SubshellSidebar, SubshellRightSideContainer } from './chunk-RX4UWZZR.js';
2
- import { FeatureUnavailableState } from './chunk-BHR7IV72.js';
3
- import { useRouterContext } from './chunk-Q7DJKLEN.js';
4
- import { useInitialization } from './chunk-DK2HVHCY.js';
5
- import { useOrganization } from './chunk-DD3CCMCZ.js';
6
- import { createContext, useMemo, useCallback, useContext } from 'react';
7
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
-
9
- function createFeatureAccessHook({
10
- useInitialization: useInitialization2,
11
- useOrganization: useOrganization2
12
- }) {
13
- return function useFeatureAccess2() {
14
- const { profile, organizationReady } = useInitialization2();
15
- const { currentMembership } = useOrganization2();
16
- const { orgConfig, membershipConfig } = useMemo(() => {
17
- const organizationConfig = currentMembership?.organization?.config;
18
- const memberConfig = currentMembership?.config;
19
- return { orgConfig: organizationConfig, membershipConfig: memberConfig };
20
- }, [currentMembership]);
21
- const userConfig = profile?.config;
22
- const checkFeature = useCallback(
23
- (featureKey) => {
24
- if (profile?.is_platform_admin) {
25
- return { allowed: true, restrictedBy: null };
26
- }
27
- const membershipValue = membershipConfig?.features?.[featureKey];
28
- if (membershipValue === false) return { allowed: false, restrictedBy: "membership" };
29
- return { allowed: true, restrictedBy: null };
30
- },
31
- [profile?.is_platform_admin, membershipConfig]
32
- );
33
- const hasFeature = useCallback((featureKey) => checkFeature(featureKey).allowed, [checkFeature]);
34
- return {
35
- orgConfig,
36
- membershipConfig,
37
- userConfig,
38
- hasFeature,
39
- checkFeature,
40
- isReady: organizationReady
41
- };
42
- };
43
- }
44
- var createUseFeatureAccess = createFeatureAccessHook;
45
-
46
- // src/provider/resolvers/RouteResolver.ts
47
- function normalizeRoutePath(path) {
48
- const trimmedPath = path.trim();
49
- if (!trimmedPath || trimmedPath === "/") {
50
- return "/";
51
- }
52
- return trimmedPath.replace(/\/+$/, "") || "/";
53
- }
54
- function isRouteMatch(currentPath, route) {
55
- const normalizedCurrentPath = normalizeRoutePath(currentPath);
56
- const normalizedRoute = normalizeRoutePath(route);
57
- return normalizedCurrentPath === normalizedRoute || normalizedCurrentPath.startsWith(`${normalizedRoute}/`);
58
- }
59
-
60
- // src/provider/resolvers/NavResolver.ts
61
- function uniqueIds(ids) {
62
- return ids ? [...new Set(ids)] : [];
63
- }
64
- function collectNavLinkPaths(links) {
65
- if (!links?.length) {
66
- return [];
67
- }
68
- return links.flatMap((link) => [link.link, ...collectNavLinkPaths(link.links)]);
69
- }
70
-
71
- // src/provider/validateManifests.ts
72
- function validateManifests(manifests, organizationModel) {
73
- if (!organizationModel) {
74
- return;
75
- }
76
- const validFeatureIds = new Set(organizationModel.features.map((f) => f.id));
77
- const validCapabilityIds = /* @__PURE__ */ new Set([
78
- ...organizationModel.features.flatMap((f) => f.capabilityIds),
79
- ...organizationModel.navigation.surfaces.flatMap((s) => s.capabilityIds),
80
- ...organizationModel.resourceMappings.flatMap((r) => r.capabilityIds)
81
- ]);
82
- const errors = [];
83
- for (const manifest of manifests) {
84
- const key = manifest.key;
85
- if (!validFeatureIds.has(manifest.featureId)) {
86
- errors.push(
87
- `Manifest "${key}": featureId "${manifest.featureId}" is not a known feature id. Valid values: ${[...validFeatureIds].sort().join(", ")}`
88
- );
89
- }
90
- if (manifest.capabilityIds) {
91
- for (let i = 0; i < manifest.capabilityIds.length; i++) {
92
- const capabilityId = manifest.capabilityIds[i];
93
- if (!validCapabilityIds.has(capabilityId)) {
94
- errors.push(
95
- `Manifest "${key}": capabilityIds[${i}] references unknown capability "${capabilityId}". Valid capabilities: ${[...validCapabilityIds].sort().join(", ")}`
96
- );
97
- }
98
- }
99
- }
100
- }
101
- if (errors.length > 0) {
102
- throw new Error(
103
- `Feature manifest validation failed with ${errors.length} error(s):
104
- ` + errors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")
105
- );
106
- }
107
- }
108
- var useFeatureAccess = createFeatureAccessHook({
109
- useInitialization,
110
- useOrganization
111
- });
112
- var ElevasisFeaturesContext = createContext(null);
113
- function useElevasisFeatures() {
114
- const context = useContext(ElevasisFeaturesContext);
115
- if (!context) {
116
- throw new Error(
117
- "useElevasisFeatures must be used within an ElevasisFeaturesProvider. Wrap your app (or the relevant subtree) with <ElevasisFeaturesProvider>."
118
- );
119
- }
120
- return context;
121
- }
122
- function useOptionalElevasisFeatures() {
123
- return useContext(ElevasisFeaturesContext);
124
- }
125
- function findOrganizationModelFeature(organizationModel, featureId) {
126
- if (!organizationModel) {
127
- return void 0;
128
- }
129
- return organizationModel.features.find((f) => f.id === featureId);
130
- }
131
- function findSurfaceByPath(organizationModel, path) {
132
- if (!organizationModel) {
133
- return void 0;
134
- }
135
- const normalizedPath = normalizeRoutePath(path);
136
- return organizationModel.navigation.surfaces.find((surface) => normalizeRoutePath(surface.path) === normalizedPath);
137
- }
138
- function findSurfaceById(organizationModel, id) {
139
- if (!organizationModel) {
140
- return void 0;
141
- }
142
- return organizationModel.navigation.surfaces.find((surface) => surface.id === id);
143
- }
144
- function findSurfacesByPaths(organizationModel, paths) {
145
- if (!organizationModel || paths.length === 0) {
146
- return [];
147
- }
148
- const normalizedPaths = new Set(paths.map((path) => normalizeRoutePath(path)));
149
- return organizationModel.navigation.surfaces.filter(
150
- (surface) => normalizedPaths.has(normalizeRoutePath(surface.path))
151
- );
152
- }
153
- function getOrganizationModelFeatureLabel(organizationModel, featureId) {
154
- if (!organizationModel || !featureId) {
155
- return void 0;
156
- }
157
- return findOrganizationModelFeature(organizationModel, featureId)?.label;
158
- }
159
- function isOrganizationModelFeatureEnabled(organizationModel, featureId) {
160
- if (!organizationModel) {
161
- return void 0;
162
- }
163
- const feature = findOrganizationModelFeature(organizationModel, featureId);
164
- if (!feature) {
165
- return void 0;
166
- }
167
- return feature.enabled;
168
- }
169
- function resolveOrganizationGraphSurface(features, organizationModel) {
170
- for (const feature of features) {
171
- const graphBridge = feature.organizationGraph;
172
- if (!graphBridge) {
173
- continue;
174
- }
175
- const surface = findSurfaceById(organizationModel, graphBridge.surfaceId);
176
- return {
177
- available: Boolean(surface),
178
- surfaceId: graphBridge.surfaceId,
179
- surfacePath: surface?.path,
180
- surfaceType: surface?.surfaceType,
181
- featureId: surface?.featureId
182
- };
183
- }
184
- return {
185
- available: false
186
- };
187
- }
188
- function resolveNavLink(link, organizationModel) {
189
- const matchedSurface = findSurfaceByPath(organizationModel, link.link);
190
- const featureLabel = getOrganizationModelFeatureLabel(organizationModel, link.featureKey);
191
- return {
192
- ...link,
193
- label: matchedSurface?.label ?? featureLabel ?? link.label,
194
- link: matchedSurface?.path ?? link.link,
195
- links: link.links?.map((nestedLink) => resolveNavLink(nestedLink, organizationModel))
196
- };
197
- }
198
- function resolveNavEntry(navEntry, organizationModel, ownerFeatureId) {
199
- const matchedSurface = navEntry.link ? findSurfaceByPath(organizationModel, navEntry.link) : void 0;
200
- const featureLabel = getOrganizationModelFeatureLabel(organizationModel, navEntry.featureKey ?? ownerFeatureId);
201
- return {
202
- ...navEntry,
203
- label: featureLabel ?? matchedSurface?.label ?? navEntry.label,
204
- link: matchedSurface?.path ?? navEntry.link,
205
- links: navEntry.links?.map((link) => resolveNavLink(link, organizationModel))
206
- };
207
- }
208
- function resolveFeatureModule(feature, organizationModel) {
209
- if (!feature.navEntry) {
210
- return feature;
211
- }
212
- return {
213
- ...feature,
214
- navEntry: resolveNavEntry(feature.navEntry, organizationModel, feature.featureId)
215
- };
216
- }
217
- function resolveFeatureSemantics(feature, resolvedFeature, organizationModel) {
218
- const linkedPaths = [resolvedFeature.navEntry?.link, ...collectNavLinkPaths(resolvedFeature.navEntry?.links)].filter(
219
- (path) => Boolean(path)
220
- );
221
- const linkedSurfaces = findSurfacesByPaths(organizationModel, linkedPaths);
222
- const organizationGraphSurface = feature.organizationGraph ? findSurfaceById(organizationModel, feature.organizationGraph.surfaceId) : void 0;
223
- const surfaces = [...linkedSurfaces, ...organizationGraphSurface ? [organizationGraphSurface] : []].filter(
224
- (surface, index, items) => Boolean(surface) && items.findIndex((candidate) => candidate.id === surface.id) === index
225
- );
226
- return {
227
- capabilityIds: uniqueIds([
228
- ...feature.capabilityIds ?? [],
229
- ...surfaces.flatMap((surface) => surface.capabilityIds)
230
- ]),
231
- surfaceIds: surfaces.map((surface) => surface.id),
232
- surfaces
233
- };
234
- }
235
- function resolveFeatureModules(features, organizationModel, isFeatureEnabled) {
236
- return features.map((feature) => {
237
- const resolvedFeature = resolveFeatureModule(feature, organizationModel);
238
- const featureId = feature.featureId;
239
- return {
240
- ...resolvedFeature,
241
- access: {
242
- featureId,
243
- enabled: isFeatureEnabled(featureId)
244
- },
245
- semantics: resolveFeatureSemantics(feature, resolvedFeature, organizationModel)
246
- };
247
- });
248
- }
249
- function filterNavLinks(links, disabledSubsectionPaths, isFeatureEnabled) {
250
- return links.flatMap((link) => {
251
- if (link.featureKey && !isFeatureEnabled(link.featureKey)) {
252
- return [];
253
- }
254
- if (disabledSubsectionPaths.some((disabledPath) => isRouteMatch(link.link, disabledPath))) {
255
- return [];
256
- }
257
- const nestedLinks = link.links?.length ? filterNavLinks(link.links, disabledSubsectionPaths, isFeatureEnabled) : void 0;
258
- return [
259
- {
260
- ...link,
261
- links: nestedLinks
262
- }
263
- ];
264
- });
265
- }
266
- function createShellNavItem(navEntry, placement, source, featureId, links = navEntry.links) {
267
- return {
268
- ...navEntry,
269
- links,
270
- placement,
271
- source,
272
- featureId
273
- };
274
- }
275
- function createFeatureShellNavItem(feature, links = feature.navEntry?.links) {
276
- if (!feature.navEntry) {
277
- return void 0;
278
- }
279
- return createShellNavItem(feature.navEntry, "primary", "feature", feature.access.featureId, links);
280
- }
281
- function getFeatureNavItems(features, disabledSubsectionPaths, isFeatureEnabled) {
282
- return features.flatMap((feature) => {
283
- if (!feature.navEntry) {
284
- return [];
285
- }
286
- const links = feature.navEntry.links?.length ? filterNavLinks(feature.navEntry.links, disabledSubsectionPaths, isFeatureEnabled) : void 0;
287
- const navItem = createFeatureShellNavItem(feature, links);
288
- return navItem ? [navItem] : [];
289
- });
290
- }
291
- function resolveAppShellOverrides(appShellOverrides, organizationModel) {
292
- if (!appShellOverrides) {
293
- return {};
294
- }
295
- return {
296
- primaryNavItems: appShellOverrides.primaryNavItems?.map((navItem) => resolveNavEntry(navItem, organizationModel)),
297
- bottomNavItems: appShellOverrides.bottomNavItems?.map((navItem) => resolveNavEntry(navItem, organizationModel))
298
- };
299
- }
300
- function getAppShellNavItems(navItems, placement, disabledSubsectionPaths, isFeatureEnabled) {
301
- if (!navItems?.length) {
302
- return [];
303
- }
304
- return navItems.flatMap((navItem) => {
305
- if (navItem.featureKey && !isFeatureEnabled(navItem.featureKey)) {
306
- return [];
307
- }
308
- const links = navItem.links?.length ? filterNavLinks(navItem.links, disabledSubsectionPaths, isFeatureEnabled) : void 0;
309
- if (navItem.links && !links?.length && !navItem.link) {
310
- return [];
311
- }
312
- return [createShellNavItem(navItem, placement, "app", navItem.featureKey, links)];
313
- });
314
- }
315
- function findMatchingNavLink(links, currentPath) {
316
- for (const link of links) {
317
- if (link.links?.length) {
318
- const nestedLink = findMatchingNavLink(link.links, currentPath);
319
- if (nestedLink) {
320
- return nestedLink;
321
- }
322
- }
323
- if (isRouteMatch(currentPath, link.link)) {
324
- return link;
325
- }
326
- }
327
- return null;
328
- }
329
- function isHiddenNavLink(link, disabledSubsectionPaths, isFeatureEnabled) {
330
- if (link.featureKey && !isFeatureEnabled(link.featureKey)) {
331
- return true;
332
- }
333
- return disabledSubsectionPaths.some((disabledPath) => isRouteMatch(link.link, disabledPath));
334
- }
335
- function resolveRoute(features, currentPath, disabledSubsectionPaths, isFeatureEnabled) {
336
- for (const feature of features) {
337
- const navEntry = feature.navEntry;
338
- const matchesSubshell = feature.subshellRoutes?.some((route) => isRouteMatch(currentPath, route)) ?? false;
339
- const matchesEntryLink = navEntry?.link ? isRouteMatch(currentPath, navEntry.link) : false;
340
- const matchedLink = navEntry?.links?.length ? findMatchingNavLink(navEntry.links, currentPath) : null;
341
- if (!matchesSubshell && !matchesEntryLink && !matchedLink) {
342
- continue;
343
- }
344
- if (matchedLink && isHiddenNavLink(matchedLink, disabledSubsectionPaths, isFeatureEnabled)) {
345
- return {
346
- status: "hidden",
347
- path: currentPath,
348
- feature,
349
- navItem: createFeatureShellNavItem(feature),
350
- navLink: matchedLink
351
- };
352
- }
353
- return {
354
- status: "matched",
355
- path: currentPath,
356
- feature,
357
- navItem: createFeatureShellNavItem(feature),
358
- navLink: matchedLink ?? void 0
359
- };
360
- }
361
- return {
362
- status: "unmatched",
363
- path: currentPath
364
- };
365
- }
366
- function ElevasisFeaturesProvider({
367
- features,
368
- organizationModel,
369
- appShellOverrides,
370
- timeRange,
371
- operationsApiUrl,
372
- operationsSSEManager,
373
- deliveryApiUrl,
374
- deliverySSEManager,
375
- disabledSubsectionPaths = [],
376
- children
377
- }) {
378
- useMemo(() => validateManifests(features, organizationModel), [features, organizationModel]);
379
- const { hasFeature } = useFeatureAccess();
380
- const hasResolvedFeature = useCallback(
381
- (key) => {
382
- if (!hasFeature(key)) {
383
- return false;
384
- }
385
- const organizationModelFeatureEnabled = isOrganizationModelFeatureEnabled(organizationModel, key);
386
- if (organizationModelFeatureEnabled === void 0) {
387
- return true;
388
- }
389
- return organizationModelFeatureEnabled;
390
- },
391
- [hasFeature, organizationModel]
392
- );
393
- const normalizedDisabledSubsectionPaths = useMemo(() => {
394
- const explicit = disabledSubsectionPaths.map((path) => normalizeRoutePath(path));
395
- const fromModel = organizationModel?.navigation.surfaces.filter((s) => s.enabled === false).map((s) => normalizeRoutePath(s.path)) ?? [];
396
- return [.../* @__PURE__ */ new Set([...explicit, ...fromModel])];
397
- }, [disabledSubsectionPaths, organizationModel]);
398
- const resolvedFeatures = useMemo(
399
- () => resolveFeatureModules(features, organizationModel, hasResolvedFeature),
400
- [features, organizationModel, hasResolvedFeature]
401
- );
402
- const resolvedAppShellOverrides = useMemo(
403
- () => resolveAppShellOverrides(appShellOverrides, organizationModel),
404
- [appShellOverrides, organizationModel]
405
- );
406
- const enabledResolvedFeatures = useMemo(
407
- () => resolvedFeatures.filter((feature) => feature.access.enabled),
408
- [resolvedFeatures]
409
- );
410
- const featureNavItems = useMemo(
411
- () => getFeatureNavItems(enabledResolvedFeatures, normalizedDisabledSubsectionPaths, hasResolvedFeature),
412
- [enabledResolvedFeatures, normalizedDisabledSubsectionPaths, hasResolvedFeature]
413
- );
414
- const primaryNavItems = useMemo(
415
- () => [
416
- ...getAppShellNavItems(
417
- resolvedAppShellOverrides.primaryNavItems,
418
- "primary",
419
- normalizedDisabledSubsectionPaths,
420
- hasResolvedFeature
421
- ),
422
- ...featureNavItems
423
- ],
424
- [resolvedAppShellOverrides.primaryNavItems, normalizedDisabledSubsectionPaths, hasResolvedFeature, featureNavItems]
425
- );
426
- const bottomNavItems = useMemo(
427
- () => getAppShellNavItems(
428
- resolvedAppShellOverrides.bottomNavItems,
429
- "bottom",
430
- normalizedDisabledSubsectionPaths,
431
- hasResolvedFeature
432
- ),
433
- [resolvedAppShellOverrides.bottomNavItems, normalizedDisabledSubsectionPaths, hasResolvedFeature]
434
- );
435
- const shellNavItems = useMemo(() => [...primaryNavItems, ...bottomNavItems], [primaryNavItems, bottomNavItems]);
436
- const shellModel = useMemo(
437
- () => ({
438
- navItems: shellNavItems
439
- }),
440
- [shellNavItems]
441
- );
442
- const organizationGraph = useMemo(
443
- () => resolveOrganizationGraphSurface(enabledResolvedFeatures, organizationModel),
444
- [enabledResolvedFeatures, organizationModel]
445
- );
446
- const getResolvedFeature = useCallback(
447
- (key) => resolvedFeatures.find((feature) => feature.key === key),
448
- [resolvedFeatures]
449
- );
450
- const isFeatureEnabled = useCallback((key) => hasResolvedFeature(key), [hasResolvedFeature]);
451
- const resolveRouteByPath = useCallback(
452
- (path) => resolveRoute(enabledResolvedFeatures, path, normalizedDisabledSubsectionPaths, isFeatureEnabled),
453
- [enabledResolvedFeatures, normalizedDisabledSubsectionPaths, isFeatureEnabled]
454
- );
455
- const shellRuntime = useMemo(
456
- () => ({
457
- resolveRoute: resolveRouteByPath
458
- }),
459
- [resolveRouteByPath]
460
- );
461
- const value = useMemo(
462
- () => ({
463
- shellModel,
464
- shellRuntime,
465
- enabledResolvedFeatures,
466
- resolvedFeatures,
467
- organizationGraph,
468
- organizationModel,
469
- timeRange,
470
- operationsApiUrl,
471
- operationsSSEManager,
472
- deliveryApiUrl,
473
- deliverySSEManager,
474
- disabledSubsectionPaths: normalizedDisabledSubsectionPaths,
475
- isFeatureEnabled,
476
- getResolvedFeature
477
- }),
478
- [
479
- shellModel,
480
- shellRuntime,
481
- enabledResolvedFeatures,
482
- resolvedFeatures,
483
- organizationGraph,
484
- organizationModel,
485
- timeRange,
486
- operationsApiUrl,
487
- operationsSSEManager,
488
- deliveryApiUrl,
489
- deliverySSEManager,
490
- normalizedDisabledSubsectionPaths,
491
- isFeatureEnabled,
492
- getResolvedFeature
493
- ]
494
- );
495
- return /* @__PURE__ */ jsx(ElevasisFeaturesContext.Provider, { value, children });
496
- }
497
- function FeatureShell({ children }) {
498
- const { shellRuntime } = useElevasisFeatures();
499
- const { currentPath } = useRouterContext();
500
- const routeMatch = shellRuntime.resolveRoute(currentPath);
501
- if (routeMatch.status === "hidden") {
502
- return /* @__PURE__ */ jsx(FeatureUnavailableState, { path: currentPath });
503
- }
504
- if (routeMatch.status !== "matched" || !routeMatch.feature?.sidebar) {
505
- return /* @__PURE__ */ jsx(Fragment, { children });
506
- }
507
- const SidebarComponent = routeMatch.feature.sidebar;
508
- return /* @__PURE__ */ jsxs(SubshellContainer, { children: [
509
- /* @__PURE__ */ jsx(SubshellSidebar, { width: 250, children: /* @__PURE__ */ jsx(SidebarComponent, {}) }),
510
- /* @__PURE__ */ jsx(SubshellRightSideContainer, { children })
511
- ] });
512
- }
513
-
514
- export { ElevasisFeaturesProvider, FeatureShell, createFeatureAccessHook, createUseFeatureAccess, useElevasisFeatures, useOptionalElevasisFeatures };