@camunda/camunda-composite-components 0.25.2 → 0.25.3
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 +2 -2
- package/lib/esm/src/components/c3-data-table/c3-data-table.js +2 -1
- package/lib/esm/src/components/c3-data-table/c3-data-table.types.d.ts +9 -0
- package/lib/esm/src/components/c3-navigation-v2/c3-breadcrumb-bar.js +3 -10
- package/lib/esm/src/components/c3-navigation-v2/c3-navigation-v2.js +1 -1
- package/lib/esm/src/components/c3-navigation-v2/c3-navigation-v2.types.d.ts +7 -6
- package/lib/esm/src/components/c3-navigation-v2/c3-sidebar.js +2 -8
- package/lib/esm/src/components/c3-navigation-v2/c3-tools-area.js +1 -1
- package/lib/esm/src/components/c3-navigation-v2/resolve-link-as.d.ts +16 -0
- package/lib/esm/src/components/c3-navigation-v2/resolve-link-as.js +28 -0
- package/lib/esm/src/components/c3-navigation-v2/use-c3-navigation-v2.d.ts +12 -23
- package/lib/esm/src/components/c3-navigation-v2/use-c3-navigation-v2.js +1 -1
- package/lib/esm/src/components/c3-navigation-v2/use-cluster-webapp-breadcrumbs.js +1 -0
- package/package.json +3 -3
package/lib/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camunda/camunda-composite-components",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.3",
|
|
4
4
|
"description": "Camunda Composite Components",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/camunda/camunda-cloud-management-apps/issues"
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@vitest/browser": "4.1.9",
|
|
71
71
|
"@vitest/browser-playwright": "4.1.9",
|
|
72
72
|
"vitest": "4.1.9",
|
|
73
|
-
"conventional-changelog-conventionalcommits": "
|
|
73
|
+
"conventional-changelog-conventionalcommits": "10.2.0",
|
|
74
74
|
"eslint-import-resolver-typescript": "4.4.5",
|
|
75
75
|
"eslint-plugin-react": "7.37.5",
|
|
76
76
|
"eslint-plugin-react-hooks": "7.1.1",
|
|
@@ -327,7 +327,8 @@ export const C3DataTable = ({ data, headers, options, toolbar: singleToolbar, to
|
|
|
327
327
|
multiItemElement.multiOnClick(inputData.filter((row) => selectedItems.includes(row.id)));
|
|
328
328
|
}, renderIcon: multiItemElement.icon, disabled: (multiItemElement.disabled &&
|
|
329
329
|
multiItemElement.disabled(inputData.filter((row) => selectedItems.includes(row.id)))) ||
|
|
330
|
-
selectedItems.length === 0
|
|
330
|
+
(selectedItems.length === 0 &&
|
|
331
|
+
!multiItemElement.allowWithoutSelection), kind: multiItemElement.kind, children: multiItemElement.label }, multiItemElement.id));
|
|
331
332
|
}
|
|
332
333
|
else if (toolbarElement.type === 'multiSelect') {
|
|
333
334
|
const multiSelectElement = toolbarElement;
|
|
@@ -54,6 +54,15 @@ export interface C3DataTableToolbarMultiItemButtonProps<T extends RowBaseProps>
|
|
|
54
54
|
multiOnClick: (selectedItems: T[]) => void;
|
|
55
55
|
disabled?: (selectedItems: T[]) => boolean;
|
|
56
56
|
kind?: any;
|
|
57
|
+
/**
|
|
58
|
+
* By default a `multiItemButton` is disabled whenever no rows are
|
|
59
|
+
* selected. Set this to `true` to keep the button enabled even with an
|
|
60
|
+
* empty selection (e.g. when the action can also be triggered without
|
|
61
|
+
* pre-selecting rows, such as opening a dialog that lets the user type
|
|
62
|
+
* or paste values in directly). The `disabled` callback above still
|
|
63
|
+
* applies on top of this.
|
|
64
|
+
*/
|
|
65
|
+
allowWithoutSelection?: boolean;
|
|
57
66
|
}
|
|
58
67
|
export interface C3DataTableToolbarMenuButtonItemProps extends C3DataTableCommonToolbarProps {
|
|
59
68
|
type: 'menuButton';
|
|
@@ -9,6 +9,7 @@ import { Checkmark, ChevronDown, OverflowMenuVertical, } from '@carbon/react/ico
|
|
|
9
9
|
import { useCallback, useEffect, useRef, useState, } from 'react';
|
|
10
10
|
import { createPortal } from 'react-dom';
|
|
11
11
|
import styled from 'styled-components';
|
|
12
|
+
import { resolveLinkAs } from './resolve-link-as.js';
|
|
12
13
|
// `display: contents` so nested flex doesn't trap min-content; label
|
|
13
14
|
// shrinkage propagates to the breadcrumb row directly.
|
|
14
15
|
const SegmentWrapper = styled.div `
|
|
@@ -172,11 +173,7 @@ const Separator = styled.span `
|
|
|
172
173
|
`;
|
|
173
174
|
const DropdownEntry = ({ item, onSelect, linkComponent, }) => {
|
|
174
175
|
const Icon = item.icon;
|
|
175
|
-
return (_jsxs(DropdownItem, { as: item.linkProps
|
|
176
|
-
? 'a'
|
|
177
|
-
: item.linkProps
|
|
178
|
-
? linkComponent
|
|
179
|
-
: undefined, ...(item.linkProps ?? {}), "$isSelected": !!item.isSelected, onClick: () => onSelect(item), role: 'option', tabIndex: -1, "aria-selected": !!item.isSelected, children: [Icon && (_jsx(Icon, { size: 16, style: { color: 'var(--cds-icon-secondary)', flexShrink: 0 } })), _jsx(DropdownItemLabel, { children: item.label }), item.trailingElement, item.isSelected && (_jsx(Checkmark, { size: 16, style: { color: 'var(--cds-icon-primary)', flexShrink: 0 } }))] }));
|
|
176
|
+
return (_jsxs(DropdownItem, { as: resolveLinkAs(item.linkProps, linkComponent), ...(item.linkProps ?? {}), "$isSelected": !!item.isSelected, onClick: () => onSelect(item), role: 'option', tabIndex: -1, "aria-selected": !!item.isSelected, children: [Icon && (_jsx(Icon, { size: 16, style: { color: 'var(--cds-icon-secondary)', flexShrink: 0 } })), _jsx(DropdownItemLabel, { children: item.label }), item.trailingElement, item.isSelected && (_jsx(Checkmark, { size: 16, style: { color: 'var(--cds-icon-primary)', flexShrink: 0 } }))] }));
|
|
180
177
|
};
|
|
181
178
|
const DropdownTitle = styled.div `
|
|
182
179
|
padding: var(--cds-spacing-04) var(--cds-spacing-05) var(--cds-spacing-03);
|
|
@@ -344,11 +341,7 @@ const BreadcrumbSegmentComponent = ({ segment, isLast, linkComponent, }) => {
|
|
|
344
341
|
close();
|
|
345
342
|
}, [close]);
|
|
346
343
|
const handleDropdownKeyDown = usePanelKeyboard(dropdownPanelRef, close, chevronRef, isOpen, '[role="option"]');
|
|
347
|
-
return (_jsxs(_Fragment, { children: [_jsxs(SegmentWrapper, { ref: wrapperRef, children: [_jsxs(SegmentButton, { ref: segmentButtonRef, as: segment.linkProps
|
|
348
|
-
? 'a'
|
|
349
|
-
: segment.linkProps
|
|
350
|
-
? linkComponent
|
|
351
|
-
: undefined, ...(segment.linkProps ?? {}), "$isInteractive": !!(segment.onClick || segment.linkProps), "$isLast": isLast, onClick: segment.onClick, "aria-label": segment.label, title: segment.label, children: [Icon && _jsx(Icon, { size: 16, style: { flexShrink: 0 } }), _jsx(SegmentLabel, { children: segment.label }), segment.trailingElement] }), segment.menuElement, segment.actions && segment.actions.length > 0 && (_jsx(ActionsMenu, { actions: segment.actions, ariaLabel: `${segment.label} actions` })), hasDropdown && (_jsx(ChevronButton, { ref: chevronRef, "$isOpen": isOpen, onClick: toggle, onKeyDown: (e) => {
|
|
344
|
+
return (_jsxs(_Fragment, { children: [_jsxs(SegmentWrapper, { ref: wrapperRef, children: [_jsxs(SegmentButton, { ref: segmentButtonRef, as: resolveLinkAs(segment.linkProps, linkComponent), ...(segment.linkProps ?? {}), "$isInteractive": !!(segment.onClick || segment.linkProps), "$isLast": isLast, onClick: segment.onClick, "aria-label": segment.label, title: segment.label, children: [Icon && _jsx(Icon, { size: 16, style: { flexShrink: 0 } }), _jsx(SegmentLabel, { children: segment.label }), segment.trailingElement] }), segment.menuElement, segment.actions && segment.actions.length > 0 && (_jsx(ActionsMenu, { actions: segment.actions, ariaLabel: `${segment.label} actions` })), hasDropdown && (_jsx(ChevronButton, { ref: chevronRef, "$isOpen": isOpen, onClick: toggle, onKeyDown: (e) => {
|
|
352
345
|
if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {
|
|
353
346
|
if (!isOpen) {
|
|
354
347
|
e.preventDefault();
|
|
@@ -15,7 +15,7 @@ const StyledHeader = styled(Header) `
|
|
|
15
15
|
background-color: var(--cds-layer-01) !important;
|
|
16
16
|
border-bottom: 1px solid var(--cds-border-subtle) !important;
|
|
17
17
|
box-shadow: none !important;
|
|
18
|
-
z-index:
|
|
18
|
+
z-index: calc(var(--c3-nav-z-index, 8000) + 1) !important;
|
|
19
19
|
|
|
20
20
|
// Carbon defaults the tools area to flex: 1, which splits the row
|
|
21
21
|
// 50/50 with breadcrumbs. Make it intrinsic and pin it to the right
|
|
@@ -23,11 +23,15 @@ export interface LinkProps {
|
|
|
23
23
|
href?: string;
|
|
24
24
|
[key: string]: unknown;
|
|
25
25
|
}
|
|
26
|
-
type
|
|
26
|
+
export type IconProps = {
|
|
27
27
|
size?: number;
|
|
28
28
|
style?: React.CSSProperties;
|
|
29
|
+
};
|
|
30
|
+
export type IconComponent = React.ComponentType<IconProps> | React.ForwardRefExoticComponent<{
|
|
31
|
+
size?: number | string;
|
|
32
|
+
style?: React.CSSProperties;
|
|
29
33
|
}>;
|
|
30
|
-
export type LinkComponent = React.
|
|
34
|
+
export type LinkComponent = React.ElementType;
|
|
31
35
|
export interface BreadcrumbDropdownItem {
|
|
32
36
|
key: string;
|
|
33
37
|
label: string;
|
|
@@ -82,9 +86,7 @@ export interface GlobalActionButton {
|
|
|
82
86
|
* Required when `element` is omitted. Ignored when `element` is supplied
|
|
83
87
|
* (the custom element renders instead of the default icon button).
|
|
84
88
|
*/
|
|
85
|
-
icon?:
|
|
86
|
-
size?: number;
|
|
87
|
-
}>;
|
|
89
|
+
icon?: IconComponent;
|
|
88
90
|
onClick?: () => void;
|
|
89
91
|
element?: ReactNode;
|
|
90
92
|
}
|
|
@@ -199,4 +201,3 @@ export interface C3NavigationV2Props {
|
|
|
199
201
|
/** Called when the active tool panel changes (including close via outside click). */
|
|
200
202
|
onActiveToolChange?: (key: string | null) => void;
|
|
201
203
|
}
|
|
202
|
-
export {};
|
|
@@ -8,6 +8,7 @@ import { Popover, PopoverContent } from '@carbon/react';
|
|
|
8
8
|
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp, } from '@carbon/react/icons/index.esm.js';
|
|
9
9
|
import { createContext, useContext, useEffect, useRef, useState, } from 'react';
|
|
10
10
|
import styled, { css } from 'styled-components';
|
|
11
|
+
import { resolveLinkAs } from './resolve-link-as.js';
|
|
11
12
|
const SidebarLabelsContext = createContext({
|
|
12
13
|
groupToggleAria: ({ label, isExpanded }) => isExpanded ? `Collapse ${label}` : `Expand ${label}`,
|
|
13
14
|
});
|
|
@@ -23,7 +24,7 @@ const SidebarNav = styled.nav `
|
|
|
23
24
|
display: flex;
|
|
24
25
|
flex-direction: column;
|
|
25
26
|
transition: width 0.15s ease-out;
|
|
26
|
-
z-index: 8000;
|
|
27
|
+
z-index: var(--c3-nav-z-index, 8000);
|
|
27
28
|
`;
|
|
28
29
|
const ScrollArea = styled.div `
|
|
29
30
|
flex: 1;
|
|
@@ -263,13 +264,6 @@ const CollapseButton = styled.button `
|
|
|
263
264
|
outline-offset: -2px;
|
|
264
265
|
}
|
|
265
266
|
`;
|
|
266
|
-
const resolveLinkAs = (linkProps, linkComponent) => {
|
|
267
|
-
if (!linkProps)
|
|
268
|
-
return undefined;
|
|
269
|
-
if ('href' in linkProps)
|
|
270
|
-
return 'a';
|
|
271
|
-
return linkComponent;
|
|
272
|
-
};
|
|
273
267
|
const pruneNode = (node) => {
|
|
274
268
|
if (node.type === 'item') {
|
|
275
269
|
if (!node.onClick && !node.linkProps)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LinkComponent } from './c3-navigation-v2.types';
|
|
2
|
+
/**
|
|
3
|
+
* Decide which element a clickable nav surface renders as based on the
|
|
4
|
+
* caller's `linkProps`.
|
|
5
|
+
*
|
|
6
|
+
* Preference, in order:
|
|
7
|
+
* 1. If `to` is set and the consumer has wired a `linkComponent`, render
|
|
8
|
+
* through the consumer wrapper so client-side routing stays in effect.
|
|
9
|
+
* 2. If `href` is set, render a plain `<a>` so cross-origin / no-router
|
|
10
|
+
* callers reload as expected and a router-aware Link does not try to
|
|
11
|
+
* SPA-route to another domain.
|
|
12
|
+
* 3. Otherwise (a `to`-only call with no `linkComponent`, or a bare
|
|
13
|
+
* onClick), defer to the consumer's `linkComponent` or fall back to
|
|
14
|
+
* the underlying element default.
|
|
15
|
+
*/
|
|
16
|
+
export declare const resolveLinkAs: (linkProps: Record<string, unknown> | undefined, linkComponent?: LinkComponent) => LinkComponent | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
|
|
3
|
+
* under one or more contributor license agreements. Licensed under a commercial license.
|
|
4
|
+
* You may not use this file except in compliance with the commercial license.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Decide which element a clickable nav surface renders as based on the
|
|
8
|
+
* caller's `linkProps`.
|
|
9
|
+
*
|
|
10
|
+
* Preference, in order:
|
|
11
|
+
* 1. If `to` is set and the consumer has wired a `linkComponent`, render
|
|
12
|
+
* through the consumer wrapper so client-side routing stays in effect.
|
|
13
|
+
* 2. If `href` is set, render a plain `<a>` so cross-origin / no-router
|
|
14
|
+
* callers reload as expected and a router-aware Link does not try to
|
|
15
|
+
* SPA-route to another domain.
|
|
16
|
+
* 3. Otherwise (a `to`-only call with no `linkComponent`, or a bare
|
|
17
|
+
* onClick), defer to the consumer's `linkComponent` or fall back to
|
|
18
|
+
* the underlying element default.
|
|
19
|
+
*/
|
|
20
|
+
export const resolveLinkAs = (linkProps, linkComponent) => {
|
|
21
|
+
if (!linkProps)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (linkProps.to !== undefined && linkComponent)
|
|
24
|
+
return linkComponent;
|
|
25
|
+
if (linkProps.href !== undefined)
|
|
26
|
+
return 'a';
|
|
27
|
+
return linkComponent;
|
|
28
|
+
};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { BreadcrumbAction, C3NavigationV2Props, GlobalActionButton, LinkComponent, LinkProps, SidebarLabels, ToolDescriptor } from './c3-navigation-v2.types';
|
|
1
|
+
import type { BreadcrumbAction, C3NavigationV2Props, GlobalActionButton, IconComponent, 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';
|
|
5
5
|
key: string;
|
|
6
6
|
label: string;
|
|
7
|
-
icon:
|
|
8
|
-
size?: number;
|
|
9
|
-
style?: React.CSSProperties;
|
|
10
|
-
}>;
|
|
7
|
+
icon: IconComponent;
|
|
11
8
|
linkProps?: LinkProps;
|
|
12
9
|
onClick?: () => void;
|
|
13
10
|
isActive?: ActiveMatcher;
|
|
@@ -17,10 +14,7 @@ export interface GroupItemDescriptor {
|
|
|
17
14
|
type: 'group-item';
|
|
18
15
|
key: string;
|
|
19
16
|
label: string;
|
|
20
|
-
icon:
|
|
21
|
-
size?: number;
|
|
22
|
-
style?: React.CSSProperties;
|
|
23
|
-
}>;
|
|
17
|
+
icon: IconComponent;
|
|
24
18
|
linkProps?: LinkProps;
|
|
25
19
|
onClick?: () => void;
|
|
26
20
|
trailingElement?: React.ReactNode;
|
|
@@ -32,10 +26,7 @@ export interface GroupDescriptor {
|
|
|
32
26
|
type: 'group';
|
|
33
27
|
key: string;
|
|
34
28
|
label: string;
|
|
35
|
-
icon:
|
|
36
|
-
size?: number;
|
|
37
|
-
style?: React.CSSProperties;
|
|
38
|
-
}>;
|
|
29
|
+
icon: IconComponent;
|
|
39
30
|
trailingElement?: React.ReactNode;
|
|
40
31
|
defaultExpanded?: boolean;
|
|
41
32
|
children: SidebarNodeDescriptor[];
|
|
@@ -51,10 +42,7 @@ export type SidebarNodeDescriptor = ItemDescriptor | GroupItemDescriptor | Group
|
|
|
51
42
|
export interface BreadcrumbDropdownItemDescriptor {
|
|
52
43
|
key: string;
|
|
53
44
|
label: string;
|
|
54
|
-
icon?:
|
|
55
|
-
size?: number;
|
|
56
|
-
style?: React.CSSProperties;
|
|
57
|
-
}>;
|
|
45
|
+
icon?: IconComponent;
|
|
58
46
|
isSelected?: ActiveMatcher;
|
|
59
47
|
onClick?: () => void;
|
|
60
48
|
linkProps?: LinkProps;
|
|
@@ -63,10 +51,7 @@ export interface BreadcrumbDropdownItemDescriptor {
|
|
|
63
51
|
export interface BreadcrumbDescriptor {
|
|
64
52
|
key: string;
|
|
65
53
|
label: string | ((activeItemKey: string) => string);
|
|
66
|
-
icon?:
|
|
67
|
-
size?: number;
|
|
68
|
-
style?: React.CSSProperties;
|
|
69
|
-
}>;
|
|
54
|
+
icon?: IconComponent;
|
|
70
55
|
onClick?: () => void;
|
|
71
56
|
linkProps?: LinkProps;
|
|
72
57
|
trailingElement?: React.ReactNode;
|
|
@@ -84,8 +69,12 @@ export interface UseC3NavigationV2Options {
|
|
|
84
69
|
sidebarAriaLabel?: string;
|
|
85
70
|
/** Forwarded to `C3Sidebar` `labels`. */
|
|
86
71
|
sidebarLabels?: SidebarLabels;
|
|
87
|
-
/**
|
|
88
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Resolves `isActive` on sidebar items and `isSelected` on breadcrumb
|
|
74
|
+
* dropdown items by key-match. Optional: items that set their own `isActive`
|
|
75
|
+
* (boolean/function) don't need it. Defaults to `''`.
|
|
76
|
+
*/
|
|
77
|
+
activeItemKey?: string;
|
|
89
78
|
sidebarChildren?: SidebarNodeDescriptor[];
|
|
90
79
|
breadcrumbs?: BreadcrumbDescriptor[];
|
|
91
80
|
tools?: ToolDescriptor[];
|
|
@@ -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', sidebarLabels, 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);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camunda/camunda-composite-components",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.3",
|
|
4
4
|
"description": "Camunda Composite Components",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/camunda/camunda-cloud-management-apps/issues"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@vitest/browser": "4.1.9",
|
|
44
44
|
"@vitest/browser-playwright": "4.1.9",
|
|
45
45
|
"vitest": "4.1.9",
|
|
46
|
-
"conventional-changelog-conventionalcommits": "
|
|
46
|
+
"conventional-changelog-conventionalcommits": "10.2.0",
|
|
47
47
|
"eslint-import-resolver-typescript": "4.4.5",
|
|
48
48
|
"eslint-plugin-react": "7.37.5",
|
|
49
49
|
"eslint-plugin-react-hooks": "7.1.1",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"styled-components": "6.4.2",
|
|
61
61
|
"typescript-eslint": "8.61.1",
|
|
62
62
|
"wait-on": "9.0.10",
|
|
63
|
-
"@camunda/ccma-shared-types": "0.
|
|
63
|
+
"@camunda/ccma-shared-types": "0.4.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"@carbon/react": "1.x",
|