@camunda/camunda-composite-components 0.2.0 → 0.2.1-rc.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.
@@ -1,10 +1,11 @@
1
1
  import { FC } from "react";
2
2
  import { Persona } from "./c3-help-center.types";
3
3
  import { Dict } from "mixpanel-browser";
4
+ import { Theme } from "../c3-user-configuration/c3-profile-provider/c3-profile-provider";
4
5
  export interface C3HelpCenterProps {
5
6
  isOpen: boolean;
6
7
  origin: "console" | "webmodeler" | "operate" | "tasklist" | "optimize";
7
- theme?: "light" | "dark";
8
+ theme?: Theme;
8
9
  flags?: string[];
9
10
  activeTab?: string;
10
11
  autoStartSurvey?: boolean;
@@ -1,13 +1,19 @@
1
1
  import { ComposedModal, Layer } from "@carbon/react";
2
- import React, { useState } from "react";
2
+ import React, { useEffect, useRef, useState } from "react";
3
3
  import { HelpCenter } from "./help-center";
4
4
  import { defaultHelpCenterConfig } from "./defaultHelpCenterConfig";
5
5
  import { C3OnboardingSurvey } from "../c3-onboarding-survey/c3-onboarding-survey";
6
6
  import { getClusters, getConfig, getOrg, updatePersona, } from "../../api/help-center";
7
7
  import { decodeJWT } from "../c3-user-configuration/authToken";
8
8
  import { useC3UserConfiguration } from "../c3-user-configuration/c3-user-configuration-provider";
9
- export const C3HelpCenter = ({ autoStartSurvey, origin, flags, isOpen, onRequestClose, mixpanelTrack, onRequestOpen, theme = "light", onPersonaChange, activeTab, }) => {
10
- const { userToken, activeOrganizationId } = useC3UserConfiguration() || {};
9
+ import { defaultTheme, useC3Profile, } from "../c3-user-configuration/c3-profile-provider/c3-profile-provider";
10
+ import { resolveTheme, } from "../c3-user-configuration/c3-profile-provider/carbon-theme-provider";
11
+ export const C3HelpCenter = ({ autoStartSurvey, origin, flags, isOpen, onRequestClose, mixpanelTrack, onRequestOpen, theme, onPersonaChange, activeTab, }) => {
12
+ const { userToken, activeOrganizationId, handleTheme } = useC3UserConfiguration() || {};
13
+ const { theme: themeConfig, isEnabled } = useC3Profile();
14
+ const themeHandlingEnabled = isEnabled && !!handleTheme && !!themeConfig;
15
+ const themeRef = useRef();
16
+ const [resolvedTheme, setResolvedTheme] = useState(defaultTheme);
11
17
  const [persona, setPersona] = useState(undefined);
12
18
  const [userId, setUserId] = useState("");
13
19
  const [token, setToken] = useState("");
@@ -17,6 +23,26 @@ export const C3HelpCenter = ({ autoStartSurvey, origin, flags, isOpen, onRequest
17
23
  const [helpCenterConfig, setHelpCenterConfig] = useState(defaultHelpCenterConfig);
18
24
  const [email, setEmail] = useState("");
19
25
  const [showSurvey, setShowSurvey] = useState(autoStartSurvey);
26
+ useEffect(() => {
27
+ const updateResolvedTheme = ({ matches }) => {
28
+ if (themeRef.current === "system") {
29
+ setResolvedTheme(matches ? "light" : "dark");
30
+ }
31
+ };
32
+ window
33
+ .matchMedia("(prefers-color-scheme: light)")
34
+ .addEventListener("change", updateResolvedTheme);
35
+ return () => {
36
+ window
37
+ .matchMedia("(prefers-color-scheme: light)")
38
+ .removeEventListener("change", updateResolvedTheme);
39
+ };
40
+ }, []);
41
+ useEffect(() => {
42
+ const newTheme = themeHandlingEnabled ? themeConfig : theme;
43
+ themeRef.current = newTheme;
44
+ setResolvedTheme(resolveTheme(newTheme || "light"));
45
+ }, [theme, themeConfig, isOpen]);
20
46
  const fetchData = async () => {
21
47
  const decodedToken = decodeJWT(userToken);
22
48
  if (!decodedToken)
@@ -133,5 +159,5 @@ export const C3HelpCenter = ({ autoStartSurvey, origin, flags, isOpen, onRequest
133
159
  onRequestClose?.();
134
160
  };
135
161
  return (React.createElement(Layer, null,
136
- React.createElement(ComposedModal, { open: isOpen, size: "lg", onClose: closeFn, className: "help-center", "aria-label": "HelpCenter" }, showSurvey || !persona ? (React.createElement(C3OnboardingSurvey, { personaCallback: personaCallback, persona: persona, mixpanelTrack: mixpanelTrack, onRequestClose: closeFn, onRequestSkip: onRequestSkipSurvey, theme: theme, origin: origin, modal: true })) : (React.createElement(HelpCenter, { configuration: helpCenterConfig, persona: persona, audience: audience, organization: organization, clusters: clusters || [], flags: flags, onRequestResumeSurvey: onRequestResumeSurvey, onRequestRetakeSurvey: onRequestRetakeSurvey, onRequestClose: closeFn, mixpanelTrack: mixpanelTrack, email: email, theme: theme, origin: origin, initialTab: activeTab })))));
162
+ React.createElement(ComposedModal, { open: isOpen, size: "lg", onClose: closeFn, className: "help-center", "aria-label": "HelpCenter" }, showSurvey || !persona ? (React.createElement(C3OnboardingSurvey, { personaCallback: personaCallback, persona: persona, mixpanelTrack: mixpanelTrack, onRequestClose: closeFn, onRequestSkip: onRequestSkipSurvey, theme: resolvedTheme, origin: origin, modal: true })) : (React.createElement(HelpCenter, { configuration: helpCenterConfig, persona: persona, audience: audience, organization: organization, clusters: clusters || [], flags: flags, onRequestResumeSurvey: onRequestResumeSurvey, onRequestRetakeSurvey: onRequestRetakeSurvey, onRequestClose: closeFn, mixpanelTrack: mixpanelTrack, email: email, theme: resolvedTheme, origin: origin, initialTab: activeTab })))));
137
163
  };
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { C3NavigationAppProps, C3NavigationElementProps, C3NavigationNavBarProps, C3NavigationProps } from "./c3-navigation.types";
3
+ import { C3HelpCenterProps } from "../c3-help-center/c3-help-center";
3
4
  export declare function createAppProps(): C3NavigationAppProps;
4
5
  export declare function createAppBarProps(options?: {
5
6
  isOpen?: boolean;
@@ -24,3 +25,4 @@ export declare function createUserSideBarProps(options: {
24
25
  export declare function createNotificationSideBarProps(options: {
25
26
  isOpen: boolean;
26
27
  }): C3NavigationProps["notificationSideBar"];
28
+ export declare const createHelpCenterProps: (options?: C3HelpCenterProps) => C3NavigationProps["helpCenter"];
@@ -212,3 +212,8 @@ export function createNotificationSideBarProps(options) {
212
212
  isOpen: options.isOpen,
213
213
  };
214
214
  }
215
+ export const createHelpCenterProps = (options) => ({
216
+ origin: options?.origin || "console",
217
+ theme: options?.theme,
218
+ mixpanelTrack: (event, data) => console.log(`Mixpanel event ${event} tracked: ${data}`),
219
+ });
@@ -1,8 +1,11 @@
1
1
  import React, { FC, PropsWithChildren } from "react";
2
+ import { ResolvedTheme } from "./carbon-theme-provider";
2
3
  export type Theme = "light" | "dark" | "system";
4
+ export declare const defaultTheme: "light";
3
5
  export type C3ProfileContextValue = {
4
6
  isEnabled: boolean;
5
7
  theme: Theme;
8
+ resolvedTheme: ResolvedTheme;
6
9
  onThemeChange: (newTheme: Theme) => void;
7
10
  };
8
11
  export declare const C3ProfileContext: React.Context<C3ProfileContextValue>;
@@ -1,33 +1,57 @@
1
- import React, { createContext, useContext, useEffect, useState, } from "react";
1
+ import React, { createContext, useContext, useEffect, useRef, useState, } from "react";
2
2
  import { C3UserConfigurationContext } from "../c3-user-configuration-provider";
3
3
  import { getUserTheme, updateTheme } from "../../../api/profile";
4
- import { CarbonThemeProvider } from "./carbon-theme-provider";
5
- const defaultTheme = "light";
4
+ import { CarbonThemeProvider, resolveTheme, } from "./carbon-theme-provider";
5
+ export const defaultTheme = "light";
6
6
  export const C3ProfileContext = createContext({
7
7
  isEnabled: false,
8
8
  theme: defaultTheme,
9
+ resolvedTheme: defaultTheme,
9
10
  onThemeChange: () => undefined,
10
11
  });
11
12
  export const C3ProfileProvider = ({ children }) => {
12
13
  const config = useContext(C3UserConfigurationContext);
13
14
  const isEnabled = !!config;
14
- const [theme, setTheme] = useState(getUserTheme(config.userToken) || defaultTheme);
15
+ const themeRef = useRef(getUserTheme(config.userToken) || defaultTheme);
16
+ const [resolvedTheme, setResolvedTheme] = useState(defaultTheme);
17
+ useEffect(() => {
18
+ const updateSystemTheme = ({ matches }) => {
19
+ if (themeRef.current === "system")
20
+ setResolvedTheme(matches ? "dark" : "light");
21
+ };
22
+ window
23
+ .matchMedia("(prefers-color-scheme: dark)")
24
+ .addEventListener("change", updateSystemTheme);
25
+ return () => {
26
+ window
27
+ .matchMedia("(prefers-color-scheme: dark)")
28
+ .removeEventListener("change", updateSystemTheme);
29
+ };
30
+ }, []);
15
31
  useEffect(() => {
16
32
  if (isEnabled && config.userToken && config.handleTheme) {
17
33
  const currentTheme = getUserTheme(config.userToken);
18
- if (currentTheme)
19
- setTheme(currentTheme);
34
+ if (currentTheme) {
35
+ themeRef.current = currentTheme;
36
+ setResolvedTheme(resolveTheme(currentTheme));
37
+ }
20
38
  }
21
39
  }, [config?.userToken]);
22
40
  const onThemeChange = (newTheme) => {
23
41
  if (isEnabled) {
24
- setTheme(newTheme);
42
+ themeRef.current = newTheme;
43
+ setResolvedTheme(resolveTheme(newTheme));
25
44
  updateTheme({ ...config, theme: newTheme });
26
45
  }
27
46
  };
28
47
  if (!isEnabled)
29
48
  return children;
30
- return config.handleTheme ? (React.createElement(C3ProfileContext.Provider, { value: { isEnabled, theme, onThemeChange } },
49
+ return config.handleTheme ? (React.createElement(C3ProfileContext.Provider, { value: {
50
+ isEnabled,
51
+ theme: themeRef.current,
52
+ resolvedTheme,
53
+ onThemeChange,
54
+ } },
31
55
  React.createElement(CarbonThemeProvider, null, children))) : (children);
32
56
  };
33
57
  export const useC3Profile = () => useContext(C3ProfileContext);
@@ -1,3 +1,13 @@
1
1
  import { FC, PropsWithChildren } from "react";
2
+ import { Theme } from "./c3-profile-provider";
2
3
  export type CarbonTheme = "white" | "g10" | "g90" | "g100";
4
+ declare const THEMES: {
5
+ readonly light: "g10";
6
+ readonly dark: "g100";
7
+ };
8
+ export type ResolvedTheme = keyof typeof THEMES;
9
+ export declare const getSystemTheme: () => ResolvedTheme;
10
+ export declare const resolveTheme: (theme: Theme) => ResolvedTheme;
11
+ export declare const setCarbonThemeAttribute: (theme: CarbonTheme) => void;
3
12
  export declare const CarbonThemeProvider: FC<PropsWithChildren>;
13
+ export {};
@@ -1,43 +1,23 @@
1
- import React, { useEffect, useRef, useState, } from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import { useC3Profile } from "./c3-profile-provider";
3
3
  import { GlobalTheme } from "@carbon/react";
4
4
  const THEMES = {
5
5
  light: "g10",
6
6
  dark: "g100",
7
7
  };
8
- const getCarbonTheme = (theme) => {
9
- if (theme === "light" ||
10
- (theme === "system" &&
11
- window.matchMedia("(prefers-color-scheme: light)").matches)) {
12
- return THEMES.light;
13
- }
14
- return THEMES.dark;
15
- };
8
+ export const getSystemTheme = () => window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
9
+ export const resolveTheme = (theme) => theme === "system" ? getSystemTheme() : theme;
10
+ const getCarbonTheme = (theme) => THEMES[resolveTheme(theme)];
11
+ export const setCarbonThemeAttribute = (theme) => document.documentElement.setAttribute("data-carbon-theme", theme);
16
12
  export const CarbonThemeProvider = ({ children }) => {
17
- const { theme } = useC3Profile();
18
- const themeRef = useRef();
19
- const [carbonTheme, setCarbonTheme] = useState(getCarbonTheme(theme));
13
+ const { resolvedTheme } = useC3Profile();
14
+ const [carbonTheme, setCarbonTheme] = useState(getCarbonTheme(resolvedTheme));
20
15
  const updateCarbonTheme = (newTheme) => {
21
16
  setCarbonTheme(newTheme);
22
- document.documentElement.setAttribute("data-carbon-theme", newTheme);
17
+ setCarbonThemeAttribute(newTheme);
23
18
  };
24
19
  useEffect(() => {
25
- const updateSystemTheme = ({ matches }) => {
26
- if (themeRef.current === "system")
27
- updateCarbonTheme(matches ? THEMES.dark : THEMES.light);
28
- };
29
- window
30
- .matchMedia("(prefers-color-scheme: dark)")
31
- .addEventListener("change", updateSystemTheme);
32
- return () => {
33
- window
34
- .matchMedia("(prefers-color-scheme: dark)")
35
- .removeEventListener("change", updateSystemTheme);
36
- };
37
- }, []);
38
- useEffect(() => {
39
- themeRef.current = theme;
40
- updateCarbonTheme(getCarbonTheme(theme));
41
- }, [theme]);
20
+ updateCarbonTheme(getCarbonTheme(resolvedTheme));
21
+ }, [resolvedTheme]);
42
22
  return React.createElement(GlobalTheme, { theme: carbonTheme }, children);
43
23
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/camunda-composite-components",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-rc.0",
4
4
  "scripts": {
5
5
  "clean": "rimraf lib/",
6
6
  "build": "yarn clean && tsc",
@@ -55,7 +55,7 @@
55
55
  "@typescript-eslint/eslint-plugin": "5.62.0",
56
56
  "@typescript-eslint/parser": "5.62.0",
57
57
  "axe-playwright": "1.2.3",
58
- "babel-loader": "8.3.0",
58
+ "babel-loader": "9.1.3",
59
59
  "copyfiles": "2.4.1",
60
60
  "css-loader": "6.8.1",
61
61
  "eslint": "8.47.0",