@camunda/camunda-composite-components 0.7.2-rc.0 → 0.8.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.
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/camunda-cloud/camunda-composite-components.git"
6
6
  },
7
- "version": "0.7.1",
7
+ "version": "0.7.2-rc.1",
8
8
  "scripts": {
9
9
  "clean": "rimraf lib/",
10
10
  "build": "yarn clean && tsc",
@@ -30,28 +30,28 @@
30
30
  "test": "yarn test:ts && yarn test:storybook && yarn test:visual-regression:docker"
31
31
  },
32
32
  "devDependencies": {
33
- "@babel/core": "7.24.5",
34
- "@babel/preset-env": "7.24.5",
35
- "@babel/preset-react": "7.24.1",
36
- "@babel/preset-typescript": "7.24.1",
33
+ "@babel/core": "7.24.6",
34
+ "@babel/preset-env": "7.24.6",
35
+ "@babel/preset-react": "7.24.6",
36
+ "@babel/preset-typescript": "7.24.6",
37
37
  "@carbon/react": "1.55.0",
38
38
  "@mdx-js/react": "3.0.1",
39
39
  "@playwright/test": "1.42.1",
40
40
  "@semantic-release/changelog": "6.0.3",
41
41
  "@semantic-release/git": "10.0.1",
42
- "@storybook/addon-a11y": "8.1.2",
43
- "@storybook/addon-actions": "8.1.2",
44
- "@storybook/addon-docs": "8.1.2",
45
- "@storybook/addon-essentials": "8.1.2",
46
- "@storybook/addon-interactions": "8.1.2",
47
- "@storybook/addon-links": "8.1.2",
48
- "@storybook/addon-mdx-gfm": "8.1.2",
42
+ "@storybook/addon-a11y": "8.1.4",
43
+ "@storybook/addon-actions": "8.1.4",
44
+ "@storybook/addon-docs": "8.1.4",
45
+ "@storybook/addon-essentials": "8.1.4",
46
+ "@storybook/addon-interactions": "8.1.4",
47
+ "@storybook/addon-links": "8.1.4",
48
+ "@storybook/addon-mdx-gfm": "8.1.4",
49
49
  "@storybook/addon-webpack5-compiler-babel": "3.0.3",
50
- "@storybook/blocks": "8.1.2",
50
+ "@storybook/blocks": "8.1.4",
51
51
  "@storybook/preset-scss": "1.0.3",
52
- "@storybook/react": "8.1.2",
53
- "@storybook/react-webpack5": "8.1.2",
54
- "@storybook/test": "8.1.2",
52
+ "@storybook/react": "8.1.4",
53
+ "@storybook/react-webpack5": "8.1.4",
54
+ "@storybook/test": "8.1.4",
55
55
  "@storybook/test-runner": "0.18.1",
56
56
  "@types/carbon-components-react": "7.55.10",
57
57
  "@types/event-source-polyfill": "1.0.5",
@@ -86,7 +86,7 @@
86
86
  "sass-loader": "14.1.1",
87
87
  "semantic-release": "23.0.7",
88
88
  "serve": "14.2.1",
89
- "storybook": "8.1.2",
89
+ "storybook": "8.1.4",
90
90
  "style-loader": "4.0.0",
91
91
  "styled-components": "6.1.8",
92
92
  "typescript": "5.4.4",
@@ -95,6 +95,7 @@
95
95
  },
96
96
  "dependencies": {
97
97
  "jwt-decode": "4.0.0",
98
+ "react-error-boundary": "4.0.13",
98
99
  "react-markdown": "8.0.7"
99
100
  },
100
101
  "peerDependencies": {
@@ -1,4 +1,4 @@
1
- import { ComposedModal, Layer } from "@carbon/react";
1
+ import { ActionableNotification, ComposedModal, Layer, ModalBody, ModalHeader, } from "@carbon/react";
2
2
  import React, { useEffect, useRef, useState } from "react";
3
3
  import { HelpCenter } from "./help-center";
4
4
  import { defaultHelpCenterConfig } from "./defaultHelpCenterConfig";
@@ -9,6 +9,7 @@ import { defaultTheme, useC3Profile, } from "../c3-user-configuration/c3-profile
9
9
  import { resolveTheme, } from "../c3-user-configuration/c3-profile-provider/carbon-theme-provider";
10
10
  import { useC3HelpCenter } from "./c3-help-center-provider";
11
11
  import styled from "styled-components";
12
+ import { ErrorBoundary } from "react-error-boundary";
12
13
  const StyledComposedModal = styled(ComposedModal) `
13
14
  .cds--modal-scroll-content {
14
15
  mask-image: none;
@@ -206,5 +207,9 @@ export const C3HelpCenter = ({ autoStartSurvey, origin, flags, onRequestClose, m
206
207
  return (React.createElement(Layer, null,
207
208
  React.createElement(StyledComposedModal, { open: isOpen, size: "lg", onClose: closeFn, className: "help-center", "aria-label": "HelpCenter", style: showSurvey || !persona?.wasShown
208
209
  ? { backgroundColor: "rgba(22,22,22, 0.8)" }
209
- : {} }, showSurvey || !persona?.wasShown ? (React.createElement(C3OnboardingSurvey, { personaCallback: personaCallback, persona: persona, mixpanelTrack: mixpanelTrack, onRequestClose: closeFn, onRequestSkip: onRequestSkipSurvey, theme: resolvedTheme, origin: hostApp, modal: true })) : (React.createElement(HelpCenter, { configuration: helpCenterConfig, persona: persona, audience: decodedAudience || "", flags: flags, onRequestResumeSurvey: onRequestResumeSurvey, onRequestRetakeSurvey: onRequestRetakeSurvey, onRequestClose: closeFn, mixpanelTrack: mixpanelTrack, email: email, theme: resolvedTheme, origin: hostApp, initialTab: activeTab })))));
210
+ : {} },
211
+ React.createElement(ErrorBoundary, { fallbackRender: () => (React.createElement(React.Fragment, null,
212
+ React.createElement(ModalHeader, { title: "Help Center", closeModal: closeFn }),
213
+ React.createElement(ModalBody, null,
214
+ React.createElement(ActionableNotification, { inline: true, hideCloseButton: true, lowContrast: true, kind: "error", title: "Something went wrong.", subtitle: "Try reloading the page.", actionButtonLabel: "Reload", onActionButtonClick: () => window.location.reload() })))) }, showSurvey || !persona?.wasShown ? (React.createElement(C3OnboardingSurvey, { personaCallback: personaCallback, persona: persona, mixpanelTrack: mixpanelTrack, onRequestClose: closeFn, onRequestSkip: onRequestSkipSurvey, theme: resolvedTheme, origin: hostApp, modal: true })) : (React.createElement(HelpCenter, { configuration: helpCenterConfig, persona: persona, audience: decodedAudience || "", flags: flags, onRequestResumeSurvey: onRequestResumeSurvey, onRequestRetakeSurvey: onRequestRetakeSurvey, onRequestClose: closeFn, mixpanelTrack: mixpanelTrack, email: email, theme: resolvedTheme, origin: hostApp, initialTab: activeTab }))))));
210
215
  };
@@ -0,0 +1,3 @@
1
+ import { FC } from "react";
2
+ import { C3BreadcrumbProps } from "./c3-breadcrumb.types";
3
+ export declare const C3Breadcrumb: FC<C3BreadcrumbProps>;
@@ -0,0 +1,32 @@
1
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbSkeleton, Link, OverflowMenu, OverflowMenuItem, SkeletonText, Stack, Tag, } from "@carbon/react";
2
+ import React from "react";
3
+ const breadCrumbWrapperStyles = {
4
+ minHeight: "40px",
5
+ display: "grid",
6
+ gridAutoFlow: "column",
7
+ gridAutoColumns: "max-content",
8
+ alignItems: "center",
9
+ };
10
+ export const C3Breadcrumb = ({ loading, noTrailingSlash, elements, title, menu, tag, forwardRef, }) => {
11
+ let breadcrumb = null;
12
+ if (loading) {
13
+ breadcrumb = (React.createElement(Stack, null,
14
+ React.createElement(BreadcrumbSkeleton, null),
15
+ title && React.createElement(SkeletonText, null)));
16
+ }
17
+ else {
18
+ breadcrumb = (React.createElement(Stack, { gap: 1 },
19
+ React.createElement(Breadcrumb, { noTrailingSlash: noTrailingSlash ?? false }, elements.map((element) => {
20
+ return (React.createElement(BreadcrumbItem, { key: element.key },
21
+ React.createElement(Link, { as: forwardRef, style: { cursor: "pointer" }, ...element.routeProps }, element.label)));
22
+ })),
23
+ (menu || title || tag) && (React.createElement("div", { style: breadCrumbWrapperStyles },
24
+ React.createElement(Stack, { orientation: "horizontal", gap: 4 },
25
+ title && React.createElement("h2", null, title),
26
+ tag && React.createElement(Tag, { type: "blue" }, tag)),
27
+ menu && (React.createElement(OverflowMenu, { style: { float: "right" }, "aria-label": "breadcrumb menu" }, menu.map((item) => {
28
+ return (React.createElement(OverflowMenuItem, { key: item.key, id: item.key, onClick: () => item.onClick(), itemText: item.label, isDelete: item.isDelete }));
29
+ })))))));
30
+ }
31
+ return React.createElement("div", { style: breadCrumbWrapperStyles }, breadcrumb);
32
+ };
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ export interface C3BreadcrumbProps {
3
+ elements: Array<{
4
+ key: string;
5
+ label: string;
6
+ routeProps: any;
7
+ }>;
8
+ loading?: boolean;
9
+ noTrailingSlash?: boolean;
10
+ title?: string;
11
+ tag?: string;
12
+ menu?: Array<{
13
+ key: string;
14
+ label: string;
15
+ onClick: () => void;
16
+ isDelete?: boolean;
17
+ }>;
18
+ forwardRef?: React.ForwardRefExoticComponent<any>;
19
+ }
@@ -0,0 +1,4 @@
1
+ import { FC } from "react";
2
+ import { C3PageProps } from "./c3-page.types";
3
+ declare const C3Page: FC<C3PageProps>;
4
+ export { C3Page };
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ import { Grid, Column, Stack } from "@carbon/react";
3
+ import { C3Tabs } from "./c3-tabs/c3-tabs";
4
+ import { C3Breadcrumb } from "./c3-breadcrumb/c3-breadcrumb";
5
+ import { DefaultStyleWrapper } from "../styles";
6
+ const gridStyles = { paddingRight: 0, paddingLeft: 0 };
7
+ const gridColumnStyles = { marginInline: 0 };
8
+ const C3Page = ({ header, tabs, children, isLoading = false, breadcrumbs = { elements: [] }, }) => {
9
+ return (React.createElement(DefaultStyleWrapper, null,
10
+ React.createElement(Grid, { style: gridStyles },
11
+ React.createElement(Column, { span: 16, style: gridColumnStyles },
12
+ React.createElement(Stack, { orientation: "vertical", gap: 7 },
13
+ (breadcrumbs.elements?.length || header) && (React.createElement(C3Breadcrumb, { ...breadcrumbs, title: header?.title, menu: header?.menuItems, tag: header?.tag, loading: isLoading })),
14
+ tabs && (React.createElement(Stack, { orientation: "vertical", gap: 5 },
15
+ React.createElement(C3Tabs, { tabs: tabs.list, desiredTabId: tabs?.activeTabId, onTabChange: tabs?.onChange, loading: isLoading }))),
16
+ children)))));
17
+ };
18
+ export { C3Page };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { expect, test } from "@playwright/test";
2
+ import { getStory } from "../test-utils";
3
+ test.describe("C3Page", () => {
4
+ test("Basic", async ({ page }) => {
5
+ await getStory(page, "components-c3page--basic");
6
+ await expect(page).toHaveScreenshot();
7
+ });
8
+ test("Loading", async ({ page }) => {
9
+ await getStory(page, "components-c3page--loading");
10
+ await expect(page).toHaveScreenshot();
11
+ });
12
+ test("With tag", async ({ page }) => {
13
+ await getStory(page, "components-c3page--with-tag");
14
+ await expect(page).toHaveScreenshot();
15
+ });
16
+ test("Without tabs", async ({ page }) => {
17
+ await getStory(page, "components-c3page--without-tabs");
18
+ await expect(page).toHaveScreenshot();
19
+ });
20
+ });
@@ -0,0 +1,18 @@
1
+ import { C3BreadcrumbProps } from "./c3-breadcrumb/c3-breadcrumb.types";
2
+ import { C3TabsProps } from "./c3-tabs/c3-tabs.types";
3
+ import React from "react";
4
+ export type C3PageProps = {
5
+ breadcrumbs?: Omit<C3BreadcrumbProps, "title" | "menu" | "tag">;
6
+ header?: {
7
+ title: string;
8
+ tag?: string;
9
+ menuItems?: C3BreadcrumbProps["menu"];
10
+ };
11
+ tabs?: {
12
+ list: C3TabsProps["tabs"];
13
+ activeTabId?: C3TabsProps["desiredTabId"];
14
+ onChange?: C3TabsProps["onTabChange"];
15
+ };
16
+ children?: React.ReactNode;
17
+ isLoading?: boolean;
18
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { FC } from "react";
2
+ import { C3TabsProps } from "./c3-tabs.types";
3
+ export declare const C3Tabs: FC<C3TabsProps>;
@@ -0,0 +1,33 @@
1
+ import { Tab, TabList, TabPanel, TabPanels, Tabs, TabsSkeleton, } from "@carbon/react";
2
+ import React from "react";
3
+ const TabPanelStyles = { paddingLeft: 0, paddingRight: 0 };
4
+ export const C3Tabs = ({ tabs, desiredTabId, onTabChange, loading = false, }) => {
5
+ const initializedTabs = React.useRef([]);
6
+ const visibleTabs = tabs.filter((tab) => tab.visible === undefined || tab.visible);
7
+ visibleTabs.forEach((tab) => {
8
+ if (tab.initializeTab && !initializedTabs.current.includes(tab.id)) {
9
+ initializedTabs.current = [...initializedTabs.current, tab.id];
10
+ tab.initializeTab();
11
+ }
12
+ });
13
+ const foundTab = desiredTabId
14
+ ? visibleTabs.findIndex((tab) => tab.id === desiredTabId)
15
+ : -1;
16
+ const selectedTab = foundTab === -1 ? 0 : foundTab;
17
+ const [activeTabIndex, setActiveTabIndex] = React.useState(selectedTab);
18
+ React.useEffect(() => {
19
+ setActiveTabIndex(selectedTab);
20
+ }, [selectedTab]);
21
+ if (loading) {
22
+ return React.createElement(TabsSkeleton, { key: "tabs-skeleton" });
23
+ }
24
+ return (React.createElement(Tabs, { selectedIndex: activeTabIndex, onChange: (event) => {
25
+ setActiveTabIndex(event.selectedIndex);
26
+ const newDesiredTab = visibleTabs[event.selectedIndex].id;
27
+ if (event.selectedIndex !== activeTabIndex && onTabChange) {
28
+ onTabChange(newDesiredTab);
29
+ }
30
+ } },
31
+ React.createElement(TabList, { "aria-label": "tabs" }, visibleTabs.map((tab) => (React.createElement(Tab, { key: `${tab.id}-label` }, tab.label)))),
32
+ React.createElement(TabPanels, null, visibleTabs.map((tab) => (React.createElement(TabPanel, { key: tab.id, style: TabPanelStyles }, tab.content))))));
33
+ };
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ export interface C3TabsProps {
3
+ tabs: C3TabProps[];
4
+ desiredTabId?: string;
5
+ onTabChange?: (tabId: string) => void;
6
+ loading?: boolean;
7
+ }
8
+ export interface C3TabProps {
9
+ id: string;
10
+ label: string;
11
+ content: React.JSX.Element;
12
+ visible?: boolean;
13
+ initializeTab?: () => void;
14
+ }
@@ -20,3 +20,7 @@ export * from "./assets/app-teaser-images/optimize-3-reports";
20
20
  export * from "./assets/app-teaser-images/tasklist-1-task-manager";
21
21
  export * from "./assets/app-teaser-images/tasklist-2-form";
22
22
  export * from "./assets/app-teaser-images/tasklist-3-api";
23
+ export { C3Page } from "./components/c3-page/c3-page";
24
+ export { C3PageProps } from "./components/c3-page/c3-page.types";
25
+ export { C3BreadcrumbProps } from "./components/c3-page/c3-breadcrumb/c3-breadcrumb.types";
26
+ export { C3TabsProps } from "./components/c3-page/c3-tabs/c3-tabs.types";
@@ -16,3 +16,4 @@ export * from "./assets/app-teaser-images/optimize-3-reports";
16
16
  export * from "./assets/app-teaser-images/tasklist-1-task-manager";
17
17
  export * from "./assets/app-teaser-images/tasklist-2-form";
18
18
  export * from "./assets/app-teaser-images/tasklist-3-api";
19
+ export { C3Page } from "./components/c3-page/c3-page";
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/camunda-cloud/camunda-composite-components.git"
6
6
  },
7
- "version": "0.7.2-rc.0",
7
+ "version": "0.8.0",
8
8
  "scripts": {
9
9
  "clean": "rimraf lib/",
10
10
  "build": "yarn clean && tsc",
@@ -30,28 +30,28 @@
30
30
  "test": "yarn test:ts && yarn test:storybook && yarn test:visual-regression:docker"
31
31
  },
32
32
  "devDependencies": {
33
- "@babel/core": "7.24.5",
34
- "@babel/preset-env": "7.24.5",
35
- "@babel/preset-react": "7.24.1",
36
- "@babel/preset-typescript": "7.24.1",
33
+ "@babel/core": "7.24.6",
34
+ "@babel/preset-env": "7.24.6",
35
+ "@babel/preset-react": "7.24.6",
36
+ "@babel/preset-typescript": "7.24.6",
37
37
  "@carbon/react": "1.55.0",
38
38
  "@mdx-js/react": "3.0.1",
39
39
  "@playwright/test": "1.42.1",
40
40
  "@semantic-release/changelog": "6.0.3",
41
41
  "@semantic-release/git": "10.0.1",
42
- "@storybook/addon-a11y": "8.1.2",
43
- "@storybook/addon-actions": "8.1.2",
44
- "@storybook/addon-docs": "8.1.2",
45
- "@storybook/addon-essentials": "8.1.2",
46
- "@storybook/addon-interactions": "8.1.2",
47
- "@storybook/addon-links": "8.1.2",
48
- "@storybook/addon-mdx-gfm": "8.1.2",
42
+ "@storybook/addon-a11y": "8.1.4",
43
+ "@storybook/addon-actions": "8.1.4",
44
+ "@storybook/addon-docs": "8.1.4",
45
+ "@storybook/addon-essentials": "8.1.4",
46
+ "@storybook/addon-interactions": "8.1.4",
47
+ "@storybook/addon-links": "8.1.4",
48
+ "@storybook/addon-mdx-gfm": "8.1.4",
49
49
  "@storybook/addon-webpack5-compiler-babel": "3.0.3",
50
- "@storybook/blocks": "8.1.2",
50
+ "@storybook/blocks": "8.1.4",
51
51
  "@storybook/preset-scss": "1.0.3",
52
- "@storybook/react": "8.1.2",
53
- "@storybook/react-webpack5": "8.1.2",
54
- "@storybook/test": "8.1.2",
52
+ "@storybook/react": "8.1.4",
53
+ "@storybook/react-webpack5": "8.1.4",
54
+ "@storybook/test": "8.1.4",
55
55
  "@storybook/test-runner": "0.18.1",
56
56
  "@types/carbon-components-react": "7.55.10",
57
57
  "@types/event-source-polyfill": "1.0.5",
@@ -86,7 +86,7 @@
86
86
  "sass-loader": "14.1.1",
87
87
  "semantic-release": "23.0.7",
88
88
  "serve": "14.2.1",
89
- "storybook": "8.1.2",
89
+ "storybook": "8.1.4",
90
90
  "style-loader": "4.0.0",
91
91
  "styled-components": "6.1.8",
92
92
  "typescript": "5.4.4",
@@ -95,6 +95,7 @@
95
95
  },
96
96
  "dependencies": {
97
97
  "jwt-decode": "4.0.0",
98
+ "react-error-boundary": "4.0.13",
98
99
  "react-markdown": "8.0.7"
99
100
  },
100
101
  "peerDependencies": {