@camunda/camunda-composite-components 0.23.3 → 0.24.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.
- package/lib/esm/package.json +26 -26
- package/lib/esm/src/components/c3-data-table/c3-data-table.js +1 -1
- package/lib/esm/src/components/c3-help-center/c3-help-center-provider.d.ts +2 -1
- package/lib/esm/src/components/c3-help-center/c3-help-center-provider.js +4 -1
- package/lib/esm/src/components/c3-help-center/c3-help-center.d.ts +2 -1
- package/lib/esm/src/components/c3-help-center/c3-help-center.js +4 -3
- package/lib/esm/src/components/c3-license-tag/c3-license-tag.d.ts +4 -5
- package/lib/esm/src/components/c3-license-tag/c3-license-tag.js +54 -47
- package/lib/esm/src/components/c3-navigation/c3-navigation-appbar/c3-navigation-appbar.js +6 -6
- package/lib/esm/src/components/c3-navigation/c3-navigation-sidebar/c3-navigation-sidebar-element.js +3 -0
- package/lib/esm/src/components/c3-navigation/c3-navigation-sidebar/c3-navigation-sidebar.js +10 -1
- package/lib/esm/src/components/c3-navigation/helpers.js +12 -0
- package/lib/esm/src/components/c3-navigation-v2/c3-breadcrumb-bar.js +33 -31
- package/lib/esm/src/components/c3-navigation-v2/c3-navigation-v2.js +7 -1
- package/lib/esm/src/components/c3-navigation-v2/c3-navigation-v2.types.d.ts +18 -0
- package/lib/esm/src/components/c3-navigation-v2/c3-sidebar.d.ts +1 -1
- package/lib/esm/src/components/c3-navigation-v2/c3-sidebar.js +82 -84
- package/lib/esm/src/components/c3-navigation-v2/c3-tools-area.js +18 -5
- package/lib/esm/src/components/c3-navigation-v2/index.d.ts +5 -3
- package/lib/esm/src/components/c3-navigation-v2/index.js +1 -0
- package/lib/esm/src/components/c3-navigation-v2/stories/story-templates.d.ts +1 -0
- package/lib/esm/src/components/c3-navigation-v2/stories/story-templates.js +112 -0
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-info-panel.d.ts +2 -1
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-info-panel.js +1 -1
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-notifications-panel.d.ts +11 -0
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-notifications-panel.js +9 -5
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-theme-selector.d.ts +25 -0
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-theme-selector.js +15 -0
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-user-panel.d.ts +15 -0
- package/lib/esm/src/components/c3-navigation-v2/tools/c3-user-panel.js +10 -17
- package/lib/esm/src/components/c3-navigation-v2/use-c3-navigation-v2.d.ts +3 -1
- package/lib/esm/src/components/c3-navigation-v2/use-c3-navigation-v2.js +2 -1
- package/lib/esm/src/components/c3-navigation-v2/use-camunda-tools.d.ts +28 -5
- package/lib/esm/src/components/c3-navigation-v2/use-camunda-tools.js +42 -23
- package/lib/esm/src/components/c3-navigation-v2/use-cluster-sidebar-entries.js +10 -8
- package/lib/esm/src/components/c3-navigation-v2/use-cluster-webapp-breadcrumbs.d.ts +16 -18
- package/lib/esm/src/components/c3-navigation-v2/use-cluster-webapp-breadcrumbs.js +146 -36
- package/lib/esm/src/index.d.ts +2 -2
- package/lib/esm/src/index.js +1 -1
- package/package.json +27 -27
|
@@ -4,11 +4,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
* under one or more contributor license agreements. Licensed under a commercial license.
|
|
5
5
|
* You may not use this file except in compliance with the commercial license.
|
|
6
6
|
*/
|
|
7
|
-
import { Button,
|
|
7
|
+
import { Button, Toggle } from '@carbon/react';
|
|
8
8
|
import { ArrowRight } from '@carbon/react/icons/index.esm.js';
|
|
9
9
|
import styled from 'styled-components';
|
|
10
|
-
import { useC3Profile, } from '../../c3-user-configuration/c3-profile-provider/c3-profile-provider.js';
|
|
11
|
-
import { useC3UserConfiguration } from '../../c3-user-configuration/c3-user-configuration-provider.js';
|
|
12
10
|
import { PanelHeader, PanelTitle } from './panel-primitives.js';
|
|
13
11
|
const ProfileSection = styled.div `
|
|
14
12
|
padding: var(--cds-spacing-05);
|
|
@@ -26,10 +24,6 @@ const ProfileEmail = styled.span `
|
|
|
26
24
|
font-size: var(--cds-label-01-font-size);
|
|
27
25
|
color: var(--cds-text-secondary);
|
|
28
26
|
`;
|
|
29
|
-
const ThemeSection = styled.div `
|
|
30
|
-
padding: var(--cds-spacing-05);
|
|
31
|
-
border-bottom: 1px solid var(--cds-border-subtle-01);
|
|
32
|
-
`;
|
|
33
27
|
const CustomSection = styled.div `
|
|
34
28
|
border-bottom: 1px solid var(--cds-border-subtle-01);
|
|
35
29
|
`;
|
|
@@ -95,31 +89,30 @@ const Copyright = styled.p `
|
|
|
95
89
|
line-height: var(--cds-label-01-line-height);
|
|
96
90
|
letter-spacing: var(--cds-label-01-letter-spacing);
|
|
97
91
|
`;
|
|
98
|
-
const
|
|
92
|
+
const buildLegalLinks = (labels) => [
|
|
99
93
|
{
|
|
100
94
|
key: 'terms',
|
|
101
|
-
label: 'Terms of use',
|
|
95
|
+
label: labels?.termsOfUse ?? 'Terms of use',
|
|
102
96
|
onClick: () => window.open('https://camunda.com/legal/terms/camunda-platform/camunda-platform-8-saas-trial/', '_blank'),
|
|
103
97
|
},
|
|
104
98
|
{
|
|
105
99
|
key: 'privacy',
|
|
106
|
-
label: 'Privacy policy',
|
|
100
|
+
label: labels?.privacyPolicy ?? 'Privacy policy',
|
|
107
101
|
onClick: () => window.open('https://camunda.com/legal/privacy/', '_blank'),
|
|
108
102
|
},
|
|
109
103
|
{
|
|
110
104
|
key: 'imprint',
|
|
111
|
-
label: 'Imprint',
|
|
105
|
+
label: labels?.imprint ?? 'Imprint',
|
|
112
106
|
onClick: () => window.open('https://camunda.com/legal/imprint/', '_blank'),
|
|
113
107
|
},
|
|
114
108
|
];
|
|
115
|
-
export const C3UserPanel = ({ name, email, version, onLogout, stageToggle, customSection, elements, }) => {
|
|
116
|
-
const { handleTheme } = useC3UserConfiguration();
|
|
117
|
-
const { theme, onThemeChange } = useC3Profile();
|
|
109
|
+
export const C3UserPanel = ({ name, email, version, onLogout, stageToggle, customSection, elements, title = 'Account', labels, }) => {
|
|
118
110
|
const consumerKeys = new Set((elements ?? []).map((e) => e.key));
|
|
119
|
-
const defaults =
|
|
111
|
+
const defaults = buildLegalLinks(labels).filter((l) => !consumerKeys.has(l.key));
|
|
120
112
|
const allElements = [...(elements ?? []), ...defaults];
|
|
121
|
-
return (_jsxs(_Fragment, { children: [_jsx(PanelHeader, { children: _jsx(PanelTitle, { children:
|
|
113
|
+
return (_jsxs(_Fragment, { children: [title && (_jsx(PanelHeader, { children: _jsx(PanelTitle, { children: title }) })), (name || email) && (_jsxs(ProfileSection, { children: [name && _jsx(ProfileName, { children: name }), email && _jsx(ProfileEmail, { children: email })] })), customSection && _jsx(CustomSection, { children: customSection }), stageToggle && (_jsx("div", { style: {
|
|
122
114
|
padding: 'var(--cds-spacing-05)',
|
|
123
115
|
borderBottom: '1px solid var(--cds-border-subtle-01)',
|
|
124
|
-
}, children: _jsx(Toggle, { id: 'stage-toggle', labelText: 'Production features', toggled: stageToggle.prodFeaturesEnabled, onToggle: stageToggle.toggle, size: 'sm' }) })), allElements.length > 0 && (_jsx(ElementList, { children: allElements.map((element) => (_jsx(ElementItem, { children: _jsx(ElementButton, { type: 'button', onClick: element.onClick, children: element.label }) }, element.key))) })), _jsxs(BottomPinned, { children: [version && (_jsxs(VersionWrapper, { children: [_jsx(VersionText, { children: version }),
|
|
116
|
+
}, children: _jsx(Toggle, { id: 'stage-toggle', labelText: 'Production features', toggled: stageToggle.prodFeaturesEnabled, onToggle: stageToggle.toggle, size: 'sm' }) })), allElements.length > 0 && (_jsx(ElementList, { children: allElements.map((element) => (_jsx(ElementItem, { children: _jsx(ElementButton, { type: 'button', onClick: element.onClick, children: element.label }) }, element.key))) })), _jsxs(BottomPinned, { children: [version && (_jsxs(VersionWrapper, { children: [_jsx(VersionText, { children: version }), _jsx(Copyright, { children: labels?.copyright?.(new Date().getFullYear()) ??
|
|
117
|
+
`© Camunda Services GmbH ${new Date().getFullYear()}` })] })), onLogout && (_jsx(BottomActions, { children: _jsx(Button, { kind: 'ghost', size: 'lg', onClick: onLogout, renderIcon: ArrowRight, children: labels?.logOut ?? 'Log out' }) }))] })] }));
|
|
125
118
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BreadcrumbAction, C3NavigationV2Props, GlobalActionButton, LinkComponent, LinkProps, ToolDescriptor } from './c3-navigation-v2.types';
|
|
1
|
+
import type { BreadcrumbAction, C3NavigationV2Props, GlobalActionButton, LinkComponent, LinkProps, SidebarLabels, ToolDescriptor } from './c3-navigation-v2.types';
|
|
2
2
|
type ActiveMatcher = boolean | string | ((activeItemKey: string) => boolean);
|
|
3
3
|
export interface ItemDescriptor {
|
|
4
4
|
type: 'item';
|
|
@@ -82,6 +82,8 @@ export interface UseC3NavigationV2Options {
|
|
|
82
82
|
skipToContentLabel?: string;
|
|
83
83
|
headerAriaLabel?: string;
|
|
84
84
|
sidebarAriaLabel?: string;
|
|
85
|
+
/** Forwarded to `C3Sidebar` `labels`. */
|
|
86
|
+
sidebarLabels?: SidebarLabels;
|
|
85
87
|
/** Used to resolve `isActive` on sidebar items and `isSelected` on breadcrumb dropdown items. */
|
|
86
88
|
activeItemKey: string;
|
|
87
89
|
sidebarChildren?: SidebarNodeDescriptor[];
|
|
@@ -30,7 +30,7 @@ function collectDefaultExpanded(nodes, out) {
|
|
|
30
30
|
* descriptors (isActive, label functions) into concrete props.
|
|
31
31
|
*/
|
|
32
32
|
export function useC3NavigationV2(options) {
|
|
33
|
-
const { app, skipToContentTargetId, skipToContentLabel, headerAriaLabel, sidebarAriaLabel = 'Main navigation', activeItemKey, sidebarChildren = [], breadcrumbs = [], tools, globalActions, sidebarExpandedWidth, sidebarCollapsedWidth, defaultSidebarExpanded = true, onSidebarToggle, linkComponent, headerTrailingContent, } = options;
|
|
33
|
+
const { app, skipToContentTargetId, skipToContentLabel, headerAriaLabel, sidebarAriaLabel = 'Main navigation', sidebarLabels, activeItemKey, sidebarChildren = [], breadcrumbs = [], tools, globalActions, sidebarExpandedWidth, sidebarCollapsedWidth, defaultSidebarExpanded = true, onSidebarToggle, linkComponent, headerTrailingContent, } = options;
|
|
34
34
|
const [isSidebarExpanded, setIsSidebarExpanded] = useState(defaultSidebarExpanded);
|
|
35
35
|
const setSidebarExpanded = useCallback((expanded) => {
|
|
36
36
|
setIsSidebarExpanded(expanded);
|
|
@@ -173,6 +173,7 @@ export function useC3NavigationV2(options) {
|
|
|
173
173
|
expandedWidth: sidebarExpandedWidth,
|
|
174
174
|
collapsedWidth: sidebarCollapsedWidth,
|
|
175
175
|
linkComponent,
|
|
176
|
+
labels: sidebarLabels,
|
|
176
177
|
}
|
|
177
178
|
: undefined;
|
|
178
179
|
const navProps = useMemo(() => ({
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { type FC, type ReactNode } from 'react';
|
|
1
2
|
import type { Notification } from '../../api/notifications';
|
|
2
3
|
import type { ToolDescriptor } from './c3-navigation-v2.types';
|
|
3
4
|
import { type InfoPanelElement } from './tools/c3-info-panel';
|
|
5
|
+
import { type C3NotificationsPanelLabels } from './tools/c3-notifications-panel';
|
|
4
6
|
import { type C3UserPanelProps } from './tools/c3-user-panel';
|
|
5
7
|
export interface NotificationsToolOptions {
|
|
6
8
|
onLinkClick?: (meta: Notification['meta']) => void;
|
|
7
9
|
ariaLabel?: string;
|
|
10
|
+
/** Forwarded to `C3NotificationsPanel`. */
|
|
11
|
+
title?: string | null;
|
|
12
|
+
/** Forwarded to `C3NotificationsPanel`. */
|
|
13
|
+
labels?: C3NotificationsPanelLabels;
|
|
8
14
|
}
|
|
9
15
|
export type UserToolOptions = C3UserPanelProps & {
|
|
10
16
|
ariaLabel?: string;
|
|
@@ -15,7 +21,8 @@ export interface HelpToolOptions {
|
|
|
15
21
|
}
|
|
16
22
|
export interface InfoToolOptions {
|
|
17
23
|
elements: InfoPanelElement[];
|
|
18
|
-
|
|
24
|
+
/** Forwarded to `C3InfoPanel`. */
|
|
25
|
+
title?: string | null;
|
|
19
26
|
ariaLabel?: string;
|
|
20
27
|
}
|
|
21
28
|
export interface UseCamundaToolsOptions {
|
|
@@ -39,11 +46,27 @@ export interface UseCamundaToolsOptions {
|
|
|
39
46
|
*/
|
|
40
47
|
help?: HelpToolOptions;
|
|
41
48
|
}
|
|
49
|
+
export interface UseCamundaToolsReturn {
|
|
50
|
+
tools: ToolDescriptor[];
|
|
51
|
+
/**
|
|
52
|
+
* Wraps the consumer's nav subtree with the providers the requested tools
|
|
53
|
+
* depend on. Currently only notifications needs a provider; when omitted,
|
|
54
|
+
* `ToolsProvider` passes children through unchanged. Wrap the
|
|
55
|
+
* `<C3NavigationV2>` render with this so the tool components can read their
|
|
56
|
+
* context inside the JSX they're rendered into.
|
|
57
|
+
*/
|
|
58
|
+
ToolsProvider: FC<{
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
42
62
|
/**
|
|
43
63
|
* Single helper entry point for the standard Camunda tool set.
|
|
44
|
-
* Returns a ToolDescriptor[]
|
|
45
|
-
*
|
|
64
|
+
* Returns a `ToolDescriptor[]` for `C3NavigationV2`'s `tools` prop plus a
|
|
65
|
+
* `ToolsProvider` that conditionally mounts the providers each requested tool
|
|
66
|
+
* depends on. Custom tools can be appended to the returned array; if they
|
|
67
|
+
* have their own provider needs, layer a separate wrapper outside
|
|
68
|
+
* `ToolsProvider`.
|
|
46
69
|
*
|
|
47
|
-
* Must be called within a C3UserConfigurationProvider tree (SaaS).
|
|
70
|
+
* Must be called within a `C3UserConfigurationProvider` tree (SaaS).
|
|
48
71
|
*/
|
|
49
|
-
export declare const useCamundaTools: (options: UseCamundaToolsOptions) =>
|
|
72
|
+
export declare const useCamundaTools: (options: UseCamundaToolsOptions) => UseCamundaToolsReturn;
|
|
@@ -1,75 +1,94 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
|
|
4
4
|
* under one or more contributor license agreements. Licensed under a commercial license.
|
|
5
5
|
* You may not use this file except in compliance with the commercial license.
|
|
6
6
|
*/
|
|
7
|
-
import { HeaderGlobalAction } from '@carbon/react';
|
|
8
|
-
import { Help as HelpIcon,
|
|
7
|
+
import { HeaderGlobalAction as HeaderGlobalActionBase } from '@carbon/react';
|
|
8
|
+
import { Help as HelpIcon, Notification as NotificationIcon, UserAvatar, } from '@carbon/react/icons/index.esm.js';
|
|
9
9
|
import { useContext, useMemo } from 'react';
|
|
10
10
|
import { C3NotificationsUnreadIcon } from '../../assets/c3-icons.js';
|
|
11
|
-
import {
|
|
11
|
+
import { useC3HelpCenter } from '../c3-help-center/c3-help-center-provider.js';
|
|
12
|
+
import C3NotificationProvider, { C3NotificationContext, } from '../c3-navigation/c3-notification-provider/c3-notification-provider.js';
|
|
12
13
|
import { C3InfoPanel } from './tools/c3-info-panel.js';
|
|
13
|
-
import { C3NotificationsPanel } from './tools/c3-notifications-panel.js';
|
|
14
|
+
import { C3NotificationsPanel, } from './tools/c3-notifications-panel.js';
|
|
14
15
|
import { C3UserPanel } from './tools/c3-user-panel.js';
|
|
16
|
+
/**
|
|
17
|
+
* Carbon's `HeaderGlobalAction` is typed as `React.FC` and omits both `ref`
|
|
18
|
+
* (the component uses `forwardRef` internally) and `leaveDelayMs`. Both work
|
|
19
|
+
* at runtime, so we widen the type at the import site — same pattern as
|
|
20
|
+
* `c3-navigation-appbar` / `-sidebar`.
|
|
21
|
+
*/
|
|
22
|
+
const HeaderGlobalAction = HeaderGlobalActionBase;
|
|
15
23
|
/**
|
|
16
24
|
* Single helper entry point for the standard Camunda tool set.
|
|
17
|
-
* Returns a ToolDescriptor[]
|
|
18
|
-
*
|
|
25
|
+
* Returns a `ToolDescriptor[]` for `C3NavigationV2`'s `tools` prop plus a
|
|
26
|
+
* `ToolsProvider` that conditionally mounts the providers each requested tool
|
|
27
|
+
* depends on. Custom tools can be appended to the returned array; if they
|
|
28
|
+
* have their own provider needs, layer a separate wrapper outside
|
|
29
|
+
* `ToolsProvider`.
|
|
19
30
|
*
|
|
20
|
-
* Must be called within a C3UserConfigurationProvider tree (SaaS).
|
|
31
|
+
* Must be called within a `C3UserConfigurationProvider` tree (SaaS).
|
|
21
32
|
*/
|
|
22
33
|
export const useCamundaTools = (options) => {
|
|
23
|
-
const {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const tools = [];
|
|
34
|
+
const { launcherButtonRef: helpButtonRef } = useC3HelpCenter();
|
|
35
|
+
const tools = useMemo(() => {
|
|
36
|
+
const result = [];
|
|
27
37
|
if (options.notifications !== undefined) {
|
|
28
38
|
const notifOptions = options.notifications;
|
|
29
39
|
const label = notifOptions.ariaLabel ?? 'Notifications';
|
|
30
|
-
|
|
40
|
+
result.push({
|
|
31
41
|
key: 'notifications',
|
|
32
42
|
label,
|
|
33
|
-
renderButton: ({ onClick, isActive }) =>
|
|
34
|
-
|
|
43
|
+
renderButton: ({ onClick, isActive }) => {
|
|
44
|
+
const { notifications, isFetching } = useContext(C3NotificationContext);
|
|
45
|
+
const hasUnread = !isFetching && notifications.some((n) => n.state === 'new');
|
|
46
|
+
return (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, isActive: isActive, tooltipAlignment: 'center', leaveDelayMs: 100, children: hasUnread ? (_jsx(C3NotificationsUnreadIcon, { size: 20 })) : (_jsx(NotificationIcon, { size: 20 })) }));
|
|
47
|
+
},
|
|
48
|
+
panel: (_jsx(C3NotificationsPanel, { onLinkClick: notifOptions.onLinkClick, title: notifOptions.title, labels: notifOptions.labels })),
|
|
35
49
|
});
|
|
36
50
|
}
|
|
37
51
|
if (options.info !== undefined) {
|
|
38
52
|
const { elements, title, ariaLabel } = options.info;
|
|
39
53
|
const label = ariaLabel ?? 'Info';
|
|
40
|
-
|
|
54
|
+
result.push({
|
|
41
55
|
key: 'info',
|
|
42
56
|
label,
|
|
43
|
-
renderButton: ({ onClick, isActive }) => (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, isActive: isActive, tooltipAlignment: 'center',
|
|
57
|
+
renderButton: ({ onClick, isActive }) => (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, isActive: isActive, tooltipAlignment: 'center', leaveDelayMs: 100, children: _jsx(HelpIcon, { size: 20 }) })),
|
|
44
58
|
panel: (_jsx(C3InfoPanel, { elements: elements, title: title })),
|
|
45
59
|
});
|
|
46
60
|
}
|
|
47
61
|
if (options.help !== undefined) {
|
|
48
62
|
const { onClick, ariaLabel } = options.help;
|
|
49
63
|
const label = ariaLabel ?? 'Help';
|
|
50
|
-
|
|
64
|
+
result.push({
|
|
51
65
|
key: 'help',
|
|
52
66
|
label,
|
|
53
|
-
renderButton: ({ isActive: _isActive }) => (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, tooltipAlignment: 'center',
|
|
67
|
+
renderButton: ({ isActive: _isActive }) => (_jsx(HeaderGlobalAction, { ref: helpButtonRef, "aria-label": label, onClick: onClick, tooltipAlignment: 'center', leaveDelayMs: 100, children: _jsx(HelpIcon, { size: 20 }) })),
|
|
54
68
|
// no panel, help is a plain button
|
|
55
69
|
});
|
|
56
70
|
}
|
|
57
71
|
if (options.user !== undefined) {
|
|
58
72
|
const { ariaLabel, ...panelProps } = options.user;
|
|
59
73
|
const label = ariaLabel ?? 'Account';
|
|
60
|
-
|
|
74
|
+
result.push({
|
|
61
75
|
key: 'user',
|
|
62
76
|
label,
|
|
63
|
-
renderButton: ({ onClick, isActive }) => (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, isActive: isActive, tooltipAlignment: 'end',
|
|
77
|
+
renderButton: ({ onClick, isActive }) => (_jsx(HeaderGlobalAction, { "aria-label": label, onClick: onClick, isActive: isActive, tooltipAlignment: 'end', leaveDelayMs: 100, children: _jsx(UserAvatar, { size: 20 }) })),
|
|
64
78
|
panel: (_jsx(C3UserPanel, { ...panelProps })),
|
|
65
79
|
});
|
|
66
80
|
}
|
|
67
|
-
return
|
|
81
|
+
return result;
|
|
68
82
|
}, [
|
|
69
|
-
hasUnread,
|
|
70
83
|
options.notifications,
|
|
71
84
|
options.info,
|
|
72
85
|
options.help,
|
|
73
86
|
options.user,
|
|
87
|
+
helpButtonRef,
|
|
74
88
|
]);
|
|
89
|
+
const ToolsProvider = useMemo(() => {
|
|
90
|
+
const needsNotifications = options.notifications !== undefined;
|
|
91
|
+
return ({ children }) => needsNotifications ? (_jsx(C3NotificationProvider, { children: children })) : (_jsx(_Fragment, { children: children }));
|
|
92
|
+
}, [options.notifications !== undefined]);
|
|
93
|
+
return { tools, ToolsProvider };
|
|
75
94
|
};
|
|
@@ -24,15 +24,17 @@ function buildClusterSidebarEntries(clusters, { isAppVisible, resolveClusterLink
|
|
|
24
24
|
if (!endpoint)
|
|
25
25
|
return [];
|
|
26
26
|
const teaser = appTeaserRoutes?.[resolvedApp] ?? appTeaserRoutes?.[app];
|
|
27
|
-
// Admin has no dedicated status on the cluster DTO
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
// `appTeaserRoutes.admin` / `.identity`
|
|
31
|
-
|
|
27
|
+
// Admin/identity has no dedicated status on the cluster DTO; it rides
|
|
28
|
+
// the same ingress as zeebe, so we gate its link on zeebe's health —
|
|
29
|
+
// matching V1's "zeebe as admin health proxy" contract. Consumers can
|
|
30
|
+
// still surface a teaser via `appTeaserRoutes.admin` / `.identity`
|
|
31
|
+
// when the link is unavailable.
|
|
32
|
+
const healthKey = isAdminApp(app)
|
|
33
|
+
? 'zeebe'
|
|
34
|
+
: resolvedApp;
|
|
35
|
+
const linkProps = cluster.status?.[healthKey] === 'Healthy'
|
|
32
36
|
? (teaser ?? { href: endpoint })
|
|
33
|
-
:
|
|
34
|
-
? { href: endpoint }
|
|
35
|
-
: teaser;
|
|
37
|
+
: teaser;
|
|
36
38
|
if (!linkProps)
|
|
37
39
|
return [];
|
|
38
40
|
return [
|
|
@@ -3,30 +3,28 @@ import type { BreadcrumbDescriptor } from './use-c3-navigation-v2';
|
|
|
3
3
|
export interface UseClusterWebappBreadcrumbsOptions {
|
|
4
4
|
/** The app currently being viewed. */
|
|
5
5
|
currentApp: CamundaApp;
|
|
6
|
-
/**
|
|
7
|
-
* Optional resolver to convert an endpoint URL into linkProps.
|
|
8
|
-
* Defaults to `(url) => ({ href: url })`. Override to support
|
|
9
|
-
* client-side routing (e.g. returning `{ to: path }` for internal links).
|
|
10
|
-
*/
|
|
11
|
-
resolveLinkProps?: (url: string, app: string) => {
|
|
12
|
-
href?: string;
|
|
13
|
-
to?: string;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
};
|
|
16
6
|
}
|
|
17
7
|
/**
|
|
18
8
|
* Builds the standard breadcrumb chain for a cluster-scoped Camunda webapp:
|
|
19
9
|
*
|
|
20
|
-
* [Org] > [Cluster] > [App ▾]
|
|
10
|
+
* [Org ▾] > [Cluster ▾] > [App ▾]
|
|
21
11
|
*
|
|
22
|
-
* - **Org crumb**: shown when org data is available (SaaS).
|
|
23
|
-
* web modeler
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
12
|
+
* - **Org crumb**: shown when org data is available (SaaS). Label links back
|
|
13
|
+
* to web modeler for the current org. Dropdown switches orgs and lands on
|
|
14
|
+
* web modeler scoped to the selected org. Dropdown only renders when there
|
|
15
|
+
* is at least one sibling org and the current cluster exposes a modeler
|
|
16
|
+
* endpoint to derive sibling URLs from.
|
|
17
|
+
* - **Cluster crumb**: shown when cluster data is available. Label links back
|
|
18
|
+
* to web modeler / console at the cluster level. Dropdown switches clusters
|
|
19
|
+
* while staying on `currentApp`, filtered to clusters that expose an
|
|
20
|
+
* endpoint for that app (alias-aware via `getEndpointForApp`).
|
|
21
|
+
* - **App crumb**: always shown. Dropdown switches between sibling apps on
|
|
22
|
+
* the same cluster (filtered to apps with endpoints).
|
|
28
23
|
*
|
|
29
|
-
*
|
|
24
|
+
* Each dropdown follows the breadcrumb convention: clicking the label
|
|
25
|
+
* navigates, clicking the chevron opens the dropdown. Items are listed in
|
|
26
|
+
* source order with the current entry marked `isSelected`. Crumbs and
|
|
27
|
+
* dropdowns are omitted when the underlying data is unavailable, so the same
|
|
30
28
|
* hook works for both SaaS (full chain) and Self-Managed (partial or single
|
|
31
29
|
* crumb) without any environment flag.
|
|
32
30
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
/*
|
|
2
3
|
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
|
|
3
4
|
* under one or more contributor license agreements. Licensed under a commercial license.
|
|
@@ -5,7 +6,8 @@
|
|
|
5
6
|
*/
|
|
6
7
|
import { Building, CloudApp } from '@carbon/react/icons/index.esm.js';
|
|
7
8
|
import { useMemo } from 'react';
|
|
8
|
-
import { APP_ICONS, getReadableAppName } from '../../utils/camunda.js';
|
|
9
|
+
import { APP_ICONS, getEndpointForApp, getReadableAppName, isAdminApp, resolveAdminAppName, } from '../../utils/camunda.js';
|
|
10
|
+
import { C3ClusterTag } from '../c3-cluster-tag/c3-cluster-tag.js';
|
|
9
11
|
import { useC3Profile } from '../c3-user-configuration/c3-profile-provider/c3-profile-provider.js';
|
|
10
12
|
import { useC3UserConfiguration } from '../c3-user-configuration/c3-user-configuration-provider.js';
|
|
11
13
|
/**
|
|
@@ -20,77 +22,185 @@ const SWITCHABLE_APPS = [
|
|
|
20
22
|
'optimize',
|
|
21
23
|
'admin',
|
|
22
24
|
];
|
|
25
|
+
/**
|
|
26
|
+
* Replaces the path of `modelerEndpoint` with `/org/{orgId}`. Used to derive
|
|
27
|
+
* the modeler URL for sibling orgs from the current cluster's modeler
|
|
28
|
+
* endpoint. Assumes all modeler URLs share the same host across orgs (SaaS
|
|
29
|
+
* pattern).
|
|
30
|
+
*/
|
|
31
|
+
function buildModelerOrgUrl(modelerEndpoint, orgId) {
|
|
32
|
+
try {
|
|
33
|
+
const url = new URL(modelerEndpoint);
|
|
34
|
+
url.pathname = `/org/${orgId}`;
|
|
35
|
+
url.search = '';
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
23
42
|
/**
|
|
24
43
|
* Builds the standard breadcrumb chain for a cluster-scoped Camunda webapp:
|
|
25
44
|
*
|
|
26
|
-
* [Org] > [Cluster] > [App ▾]
|
|
45
|
+
* [Org ▾] > [Cluster ▾] > [App ▾]
|
|
27
46
|
*
|
|
28
|
-
* - **Org crumb**: shown when org data is available (SaaS).
|
|
29
|
-
* web modeler
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
47
|
+
* - **Org crumb**: shown when org data is available (SaaS). Label links back
|
|
48
|
+
* to web modeler for the current org. Dropdown switches orgs and lands on
|
|
49
|
+
* web modeler scoped to the selected org. Dropdown only renders when there
|
|
50
|
+
* is at least one sibling org and the current cluster exposes a modeler
|
|
51
|
+
* endpoint to derive sibling URLs from.
|
|
52
|
+
* - **Cluster crumb**: shown when cluster data is available. Label links back
|
|
53
|
+
* to web modeler / console at the cluster level. Dropdown switches clusters
|
|
54
|
+
* while staying on `currentApp`, filtered to clusters that expose an
|
|
55
|
+
* endpoint for that app (alias-aware via `getEndpointForApp`).
|
|
56
|
+
* - **App crumb**: always shown. Dropdown switches between sibling apps on
|
|
57
|
+
* the same cluster (filtered to apps with endpoints).
|
|
34
58
|
*
|
|
35
|
-
*
|
|
59
|
+
* Each dropdown follows the breadcrumb convention: clicking the label
|
|
60
|
+
* navigates, clicking the chevron opens the dropdown. Items are listed in
|
|
61
|
+
* source order with the current entry marked `isSelected`. Crumbs and
|
|
62
|
+
* dropdowns are omitted when the underlying data is unavailable, so the same
|
|
36
63
|
* hook works for both SaaS (full chain) and Self-Managed (partial or single
|
|
37
64
|
* crumb) without any environment flag.
|
|
38
65
|
*/
|
|
39
66
|
export function useClusterWebappBreadcrumbs(options) {
|
|
40
|
-
const { currentApp
|
|
41
|
-
const { clusters, activeOrg } = useC3Profile();
|
|
67
|
+
const { currentApp } = options;
|
|
68
|
+
const { clusters, activeOrg, orgs } = useC3Profile();
|
|
42
69
|
const config = useC3UserConfiguration();
|
|
43
70
|
const currentClusterUuid = config.currentClusterUuid;
|
|
44
71
|
const currentCluster = useMemo(() => clusters?.find((c) => c.uuid === currentClusterUuid) ?? null, [clusters, currentClusterUuid]);
|
|
45
72
|
return useMemo(() => {
|
|
46
73
|
const crumbs = [];
|
|
74
|
+
const modelerUrl = currentCluster?.endpoints?.modeler;
|
|
47
75
|
// ── Org crumb ──────────────────────────────────────────────────────────
|
|
48
76
|
if (activeOrg) {
|
|
49
|
-
const
|
|
77
|
+
const allOrgs = orgs ?? [];
|
|
78
|
+
const hasSiblings = allOrgs.filter((o) => o.uuid !== activeOrg.uuid).length > 0;
|
|
79
|
+
const orgDropdownItems = hasSiblings && modelerUrl
|
|
80
|
+
? allOrgs.flatMap((o) => {
|
|
81
|
+
const isCurrent = o.uuid === activeOrg.uuid;
|
|
82
|
+
if (isCurrent) {
|
|
83
|
+
return [
|
|
84
|
+
{
|
|
85
|
+
key: o.uuid,
|
|
86
|
+
label: o.name,
|
|
87
|
+
icon: Building,
|
|
88
|
+
isSelected: true,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
const href = buildModelerOrgUrl(modelerUrl, o.uuid);
|
|
93
|
+
if (!href)
|
|
94
|
+
return [];
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
key: o.uuid,
|
|
98
|
+
label: o.name,
|
|
99
|
+
icon: Building,
|
|
100
|
+
isSelected: false,
|
|
101
|
+
linkProps: { href },
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
})
|
|
105
|
+
: undefined;
|
|
50
106
|
crumbs.push({
|
|
51
107
|
key: 'org',
|
|
52
108
|
label: activeOrg.name,
|
|
53
109
|
icon: Building,
|
|
54
|
-
...(modelerUrl
|
|
55
|
-
|
|
110
|
+
...(modelerUrl ? { linkProps: { href: modelerUrl } } : {}),
|
|
111
|
+
...(orgDropdownItems
|
|
112
|
+
? {
|
|
113
|
+
dropdownTitle: 'Switch organization',
|
|
114
|
+
dropdownAriaLabel: 'Switch organization',
|
|
115
|
+
dropdownItems: orgDropdownItems,
|
|
116
|
+
}
|
|
56
117
|
: {}),
|
|
57
118
|
});
|
|
58
119
|
}
|
|
59
120
|
// ── Cluster crumb ──────────────────────────────────────────────────────
|
|
60
121
|
if (currentCluster) {
|
|
61
|
-
const modelerUrl = currentCluster.endpoints?.modeler;
|
|
62
122
|
const clusterUrl = modelerUrl
|
|
63
123
|
? `${modelerUrl}?fromCluster=${currentCluster.uuid}`
|
|
64
124
|
: undefined;
|
|
125
|
+
const reachableClusters = (clusters ?? []).filter((c) => c.uuid === currentCluster.uuid ||
|
|
126
|
+
getEndpointForApp(currentApp, c.endpoints));
|
|
127
|
+
const hasSiblings = reachableClusters.filter((c) => c.uuid !== currentCluster.uuid).length >
|
|
128
|
+
0;
|
|
129
|
+
const clusterDropdownItems = hasSiblings
|
|
130
|
+
? reachableClusters.map((c) => {
|
|
131
|
+
const isCurrent = c.uuid === currentCluster.uuid;
|
|
132
|
+
const stage = c.labels?.camunda?.[0];
|
|
133
|
+
return {
|
|
134
|
+
key: c.uuid,
|
|
135
|
+
label: c.name,
|
|
136
|
+
icon: CloudApp,
|
|
137
|
+
isSelected: isCurrent,
|
|
138
|
+
...(isCurrent
|
|
139
|
+
? {}
|
|
140
|
+
: {
|
|
141
|
+
linkProps: {
|
|
142
|
+
href: getEndpointForApp(currentApp, c.endpoints) ?? '',
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
...(stage
|
|
146
|
+
? { trailingElement: _jsx(C3ClusterTag, { stage: stage, subtle: true }) }
|
|
147
|
+
: {}),
|
|
148
|
+
};
|
|
149
|
+
})
|
|
150
|
+
: undefined;
|
|
65
151
|
crumbs.push({
|
|
66
152
|
key: 'cluster',
|
|
67
153
|
label: currentCluster.name,
|
|
68
154
|
icon: CloudApp,
|
|
69
|
-
...(clusterUrl
|
|
70
|
-
|
|
155
|
+
...(clusterUrl ? { linkProps: { href: clusterUrl } } : {}),
|
|
156
|
+
...(clusterDropdownItems
|
|
157
|
+
? {
|
|
158
|
+
dropdownTitle: 'Switch cluster',
|
|
159
|
+
dropdownAriaLabel: 'Switch cluster',
|
|
160
|
+
dropdownItems: clusterDropdownItems,
|
|
161
|
+
}
|
|
71
162
|
: {}),
|
|
72
163
|
});
|
|
73
164
|
}
|
|
74
165
|
// ── App crumb ──────────────────────────────────────────────────────────
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
166
|
+
// Resolve label/icon via the same admin↔identity aliasing the sidebar
|
|
167
|
+
// entries use (`useClusterSidebarEntries`), so older clusters that expose
|
|
168
|
+
// only `identity` render as "Identity" instead of disappearing.
|
|
169
|
+
// `SWITCHABLE_APPS` carries only the canonical `admin` key; consumers
|
|
170
|
+
// that pass `currentApp: 'identity'` (legacy code path) still match the
|
|
171
|
+
// switcher row via this normalisation, otherwise the current entry
|
|
172
|
+
// would be missing from the dropdown and nothing would be selected.
|
|
173
|
+
const switcherKey = isAdminApp(currentApp) ? 'admin' : currentApp;
|
|
174
|
+
const resolvedCurrentApp = isAdminApp(currentApp) && currentCluster
|
|
175
|
+
? resolveAdminAppName(currentCluster)
|
|
176
|
+
: currentApp;
|
|
177
|
+
const appLabel = getReadableAppName(resolvedCurrentApp);
|
|
178
|
+
const appIcon = APP_ICONS[resolvedCurrentApp];
|
|
179
|
+
const reachableApps = currentCluster
|
|
180
|
+
? SWITCHABLE_APPS.filter((app) => app === switcherKey ||
|
|
181
|
+
getEndpointForApp(app, currentCluster.endpoints))
|
|
182
|
+
: [switcherKey];
|
|
183
|
+
const hasSiblingApps = reachableApps.filter((app) => app !== switcherKey).length > 0;
|
|
184
|
+
const dropdownItems = hasSiblingApps && currentCluster
|
|
185
|
+
? reachableApps.map((app) => {
|
|
186
|
+
const isCurrent = app === switcherKey;
|
|
187
|
+
const resolvedApp = isAdminApp(app)
|
|
188
|
+
? resolveAdminAppName(currentCluster)
|
|
189
|
+
: app;
|
|
190
|
+
return {
|
|
87
191
|
key: app,
|
|
88
|
-
label: getReadableAppName(
|
|
89
|
-
icon: APP_ICONS[
|
|
90
|
-
isSelected:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
192
|
+
label: getReadableAppName(resolvedApp),
|
|
193
|
+
icon: APP_ICONS[resolvedApp],
|
|
194
|
+
isSelected: isCurrent,
|
|
195
|
+
...(isCurrent
|
|
196
|
+
? {}
|
|
197
|
+
: {
|
|
198
|
+
linkProps: {
|
|
199
|
+
href: getEndpointForApp(app, currentCluster.endpoints) ?? '',
|
|
200
|
+
},
|
|
201
|
+
}),
|
|
202
|
+
};
|
|
203
|
+
})
|
|
94
204
|
: undefined;
|
|
95
205
|
crumbs.push({
|
|
96
206
|
key: 'app',
|
|
@@ -105,5 +215,5 @@ export function useClusterWebappBreadcrumbs(options) {
|
|
|
105
215
|
: {}),
|
|
106
216
|
});
|
|
107
217
|
return crumbs;
|
|
108
|
-
}, [activeOrg, currentCluster, currentApp
|
|
218
|
+
}, [activeOrg, orgs, clusters, currentCluster, currentApp]);
|
|
109
219
|
}
|
package/lib/esm/src/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export { C3LicenseTag, type C3LicenseTagProps, } from './components/c3-license-t
|
|
|
15
15
|
export { default as C3Navigation } from './components/c3-navigation';
|
|
16
16
|
export { C3NavigationAppProps, C3NavigationElementProps, C3NavigationNavBarElement, C3NavigationNavBarProps, C3NavigationNavBarSubElement, C3NavigationProps, } from './components/c3-navigation/c3-navigation.types';
|
|
17
17
|
export { C3NavigationSideBarBaseProps } from './components/c3-navigation/c3-navigation-sidebar/c3-navigation-sidebar.types';
|
|
18
|
-
export type { AppProps as C3NavV2AppProps, BreadcrumbDescriptor, BreadcrumbDropdownItem, BreadcrumbSegment, C3NavigationV2Props, C3NotificationsPanelProps, C3UserPanelProps, GlobalActionButton, GroupDescriptor, GroupItemDescriptor, HelpToolOptions, ItemDescriptor, LinkComponent, LinkProps, NotificationsToolOptions, SectionDescriptor, SidebarGroup, SidebarGroupItem, SidebarItem, SidebarNode, SidebarNodeDescriptor, SidebarProps, SidebarSection, ToolDescriptor, UseC3NavigationV2Options, UseC3NavigationV2Return, UseCamundaToolsOptions, UseClusterSidebarEntriesOptions, UserToolOptions, } from './components/c3-navigation-v2';
|
|
19
|
-
export { C3BreadcrumbBar as preview_C3BreadcrumbBar, C3NavigationV2 as preview_C3NavigationV2, C3NotificationsPanel as preview_C3NotificationsPanel, C3Sidebar as preview_C3Sidebar, C3ToolsArea as preview_C3ToolsArea, C3UserPanel as preview_C3UserPanel, useC3NavigationV2 as preview_useC3NavigationV2, useCamundaTools as preview_useCamundaTools, useClusterSidebarEntries as preview_useClusterSidebarEntries, useClusterWebappBreadcrumbs as preview_useClusterWebappBreadcrumbs, } from './components/c3-navigation-v2';
|
|
18
|
+
export type { AppProps as C3NavV2AppProps, BreadcrumbDescriptor, BreadcrumbDropdownItem, BreadcrumbSegment, C3NavigationV2Props, C3NotificationsPanelLabels, C3NotificationsPanelProps, C3ThemeSelectorLabels, C3ThemeSelectorProps, C3UserPanelLabels, C3UserPanelProps, GlobalActionButton, GroupDescriptor, GroupItemDescriptor, HelpToolOptions, ItemDescriptor, LinkComponent, LinkProps, NotificationsToolOptions, SectionDescriptor, SidebarGroup, SidebarGroupItem, SidebarItem, SidebarLabels, SidebarNode, SidebarNodeDescriptor, SidebarProps, SidebarSection, ToolDescriptor, UseC3NavigationV2Options, UseC3NavigationV2Return, UseCamundaToolsOptions, UseClusterSidebarEntriesOptions, UserToolOptions, } from './components/c3-navigation-v2';
|
|
19
|
+
export { C3BreadcrumbBar as preview_C3BreadcrumbBar, C3NavigationV2 as preview_C3NavigationV2, C3NotificationsPanel as preview_C3NotificationsPanel, C3Sidebar as preview_C3Sidebar, C3ThemeSelector, C3ToolsArea as preview_C3ToolsArea, C3UserPanel as preview_C3UserPanel, useC3NavigationV2 as preview_useC3NavigationV2, useCamundaTools as preview_useCamundaTools, useClusterSidebarEntries as preview_useClusterSidebarEntries, useClusterWebappBreadcrumbs as preview_useClusterWebappBreadcrumbs, } from './components/c3-navigation-v2';
|
|
20
20
|
export { C3BreadcrumbProps } from './components/c3-page/c3-breadcrumb/c3-breadcrumb.types';
|
|
21
21
|
export { C3Page } from './components/c3-page/c3-page';
|
|
22
22
|
export { C3PageProps } from './components/c3-page/c3-page.types';
|
package/lib/esm/src/index.js
CHANGED
|
@@ -13,7 +13,7 @@ export { C3HelpCenter } from './components/c3-help-center/c3-help-center.js';
|
|
|
13
13
|
export { useC3HelpCenter } from './components/c3-help-center/c3-help-center-provider.js';
|
|
14
14
|
export { C3LicenseTag, } from './components/c3-license-tag/index.js';
|
|
15
15
|
export { default as C3Navigation } from './components/c3-navigation/index.js';
|
|
16
|
-
export { C3BreadcrumbBar as preview_C3BreadcrumbBar, C3NavigationV2 as preview_C3NavigationV2, C3NotificationsPanel as preview_C3NotificationsPanel, C3Sidebar as preview_C3Sidebar, C3ToolsArea as preview_C3ToolsArea, C3UserPanel as preview_C3UserPanel, useC3NavigationV2 as preview_useC3NavigationV2, useCamundaTools as preview_useCamundaTools, useClusterSidebarEntries as preview_useClusterSidebarEntries, useClusterWebappBreadcrumbs as preview_useClusterWebappBreadcrumbs, } from './components/c3-navigation-v2/index.js';
|
|
16
|
+
export { C3BreadcrumbBar as preview_C3BreadcrumbBar, C3NavigationV2 as preview_C3NavigationV2, C3NotificationsPanel as preview_C3NotificationsPanel, C3Sidebar as preview_C3Sidebar, C3ThemeSelector, C3ToolsArea as preview_C3ToolsArea, C3UserPanel as preview_C3UserPanel, useC3NavigationV2 as preview_useC3NavigationV2, useCamundaTools as preview_useCamundaTools, useClusterSidebarEntries as preview_useClusterSidebarEntries, useClusterWebappBreadcrumbs as preview_useClusterWebappBreadcrumbs, } from './components/c3-navigation-v2/index.js';
|
|
17
17
|
export { C3Page } from './components/c3-page/c3-page.js';
|
|
18
18
|
export { C3ResponsiveStack } from './components/c3-responsive-stack/c3-responsive-stack.js';
|
|
19
19
|
export { useC3Profile } from './components/c3-user-configuration/c3-profile-provider/c3-profile-provider.js';
|