@camunda/camunda-composite-components 0.1.3 → 0.1.4-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.
- package/lib/esm/api/api.d.ts +4 -2
- package/lib/esm/api/api.js +8 -1
- package/lib/esm/api/endpoints.const.d.ts +2 -0
- package/lib/esm/api/endpoints.const.js +14 -0
- package/lib/esm/api/profile.d.ts +16 -0
- package/lib/esm/api/profile.js +29 -0
- package/lib/esm/components/c3-navigation/c3-navigation-sidebar/c3-navigation-sidebar.types.d.ts +1 -1
- package/lib/esm/components/c3-navigation/c3-navigation-sidebar/c3-user-sidebar.js +8 -4
- package/lib/esm/components/c3-navigation/c3-notification-provider/c3-notification-provider.js +1 -1
- package/lib/esm/components/c3-navigation/c3-profile-provider/c3-profile-provider.d.ts +12 -0
- package/lib/esm/components/c3-navigation/c3-profile-provider/c3-profile-provider.js +40 -0
- package/lib/esm/components/c3-navigation/c3-profile-provider/c3-theme-provider.d.ts +3 -0
- package/lib/esm/components/c3-navigation/c3-profile-provider/c3-theme-provider.js +12 -0
- package/lib/esm/components/c3-navigation/index.js +2 -1
- package/lib/esm/components/c3-navigation/story-helpers.d.ts +1 -0
- package/lib/esm/components/c3-navigation/story-helpers.js +1 -1
- package/package.json +4 -2
package/lib/esm/api/api.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare class HttpError extends Error {
|
|
|
4
4
|
constructor(message: string, status: number);
|
|
5
5
|
}
|
|
6
6
|
export interface RequestPayload {
|
|
7
|
-
base?: "notifications";
|
|
7
|
+
base?: "notifications" | "theme";
|
|
8
8
|
stage?: Stage;
|
|
9
9
|
endpoints?: Endpoints;
|
|
10
10
|
url: string;
|
|
@@ -18,6 +18,8 @@ export interface RequestPayload {
|
|
|
18
18
|
token: string;
|
|
19
19
|
refreshTokenMethod: () => Promise<string>;
|
|
20
20
|
};
|
|
21
|
-
body?:
|
|
21
|
+
body?: {
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
22
24
|
}
|
|
23
25
|
export declare function request(payload: RequestPayload): Promise<any>;
|
package/lib/esm/api/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getEndpoint, NOTIFICATIONS } from "./endpoints.const";
|
|
1
|
+
import { getEndpoint, NOTIFICATIONS, THEME, } from "./endpoints.const";
|
|
2
2
|
import { JWTUtils } from "./jwt.utils";
|
|
3
3
|
export class HttpError extends Error {
|
|
4
4
|
status;
|
|
@@ -41,6 +41,13 @@ export async function request(payload) {
|
|
|
41
41
|
base = getEndpoint(payload.stage, NOTIFICATIONS);
|
|
42
42
|
}
|
|
43
43
|
break;
|
|
44
|
+
case "theme":
|
|
45
|
+
if (payload.endpoints?.theme) {
|
|
46
|
+
base = payload.endpoints.theme;
|
|
47
|
+
}
|
|
48
|
+
else if (payload.stage) {
|
|
49
|
+
base = getEndpoint(payload.stage, THEME);
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
}
|
|
46
53
|
const url = base ? `${base}/${payload.url}` : payload.url;
|
|
@@ -6,8 +6,10 @@ export interface Endpoint {
|
|
|
6
6
|
}
|
|
7
7
|
export interface Endpoints {
|
|
8
8
|
notifications?: string;
|
|
9
|
+
theme?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare const NOTIFICATIONS: Endpoint;
|
|
12
|
+
export declare const THEME: Endpoint;
|
|
11
13
|
export type Stage = "dev" | "int" | "prod";
|
|
12
14
|
export declare function getEndpoint(stage: Stage, endpoint: Endpoint): string;
|
|
13
15
|
export declare function getEndpointByOptions(options: {
|
|
@@ -4,6 +4,12 @@ export const NOTIFICATIONS = {
|
|
|
4
4
|
int: "https://notifications.cloud.ultrawombat.com",
|
|
5
5
|
prod: "https://notifications.cloud.camunda.io",
|
|
6
6
|
};
|
|
7
|
+
export const THEME = {
|
|
8
|
+
id: "theme",
|
|
9
|
+
dev: "https://accounts.cloud.dev.ultrawombat.com",
|
|
10
|
+
int: "https://accounts.cloud.ultrawombat.com",
|
|
11
|
+
prod: "https://accounts.cloud.camunda.io",
|
|
12
|
+
};
|
|
7
13
|
export function getEndpoint(stage, endpoint) {
|
|
8
14
|
switch (stage) {
|
|
9
15
|
case "dev":
|
|
@@ -25,6 +31,14 @@ export function getEndpointByOptions(options) {
|
|
|
25
31
|
else if (options.stage) {
|
|
26
32
|
return getEndpoint(options.stage, options.endpoint);
|
|
27
33
|
}
|
|
34
|
+
break;
|
|
35
|
+
case "theme":
|
|
36
|
+
if (options.endpoints?.theme) {
|
|
37
|
+
return options.endpoints.theme;
|
|
38
|
+
}
|
|
39
|
+
else if (options.stage) {
|
|
40
|
+
return getEndpoint(options.stage, options.endpoint);
|
|
41
|
+
}
|
|
28
42
|
}
|
|
29
43
|
throw new Error(`Missing stage or notifications endpoint`);
|
|
30
44
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { C3NotificationsProps } from "../components/c3-navigation/c3-navigation.types";
|
|
2
|
+
import { Theme } from "../components/c3-navigation/c3-profile-provider/c3-profile-provider";
|
|
3
|
+
export type Profile = {
|
|
4
|
+
theme: Theme;
|
|
5
|
+
};
|
|
6
|
+
export type Token = {
|
|
7
|
+
sub?: string;
|
|
8
|
+
"https://camunda.com/settings"?: {
|
|
9
|
+
theme?: Theme;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare const getUserTheme: (userToken: string) => Theme | null;
|
|
13
|
+
export type UpdateThemeOptions = C3NotificationsProps & {
|
|
14
|
+
theme: Profile["theme"];
|
|
15
|
+
};
|
|
16
|
+
export declare const updateTheme: ({ endpoints, stage, userToken, getNewUserToken, theme, }: UpdateThemeOptions) => Promise<void>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import jwt from "jwt-decode";
|
|
2
|
+
import { request } from "./api";
|
|
3
|
+
const decodeJWT = (userToken) => {
|
|
4
|
+
let decodedToken = {};
|
|
5
|
+
try {
|
|
6
|
+
decodedToken = jwt(userToken);
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
console.error("User token invalid");
|
|
10
|
+
}
|
|
11
|
+
return decodedToken;
|
|
12
|
+
};
|
|
13
|
+
export const getUserTheme = (userToken) => decodeJWT(userToken)["https://camunda.com/settings"]?.theme || null;
|
|
14
|
+
export const updateTheme = async ({ endpoints, stage, userToken, getNewUserToken, theme, }) => {
|
|
15
|
+
try {
|
|
16
|
+
await request({
|
|
17
|
+
method: "patch",
|
|
18
|
+
base: "theme",
|
|
19
|
+
stage,
|
|
20
|
+
endpoints,
|
|
21
|
+
camundaAuth: { token: userToken, refreshTokenMethod: getNewUserToken },
|
|
22
|
+
url: `external/user/theme`,
|
|
23
|
+
body: { theme },
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error(error);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -4,6 +4,7 @@ import { FormLabel, RadioButton, RadioButtonGroup, Stack, SwitcherDivider, Toggl
|
|
|
4
4
|
import { UserAvatar } from "@carbon/react/icons";
|
|
5
5
|
import styled from "styled-components";
|
|
6
6
|
import { useUserSidebarState } from "./c3-sidebar-state-provider";
|
|
7
|
+
import { useC3Profile } from "../c3-profile-provider/c3-profile-provider";
|
|
7
8
|
const VersionWrapper = styled.div `
|
|
8
9
|
align-self: end;
|
|
9
10
|
padding: 0.5rem 1rem;
|
|
@@ -28,6 +29,7 @@ const C3UserSidebar = ({ sideBar }) => {
|
|
|
28
29
|
const themeSelector = customElements?.themeSelector;
|
|
29
30
|
const stageToggle = customElements?.stageToggle;
|
|
30
31
|
const customSection = customElements?.customSection;
|
|
32
|
+
const { theme, onThemeChange, enabled } = useC3Profile();
|
|
31
33
|
const { isOpen } = useUserSidebarState();
|
|
32
34
|
const itemTabIndex = isOpen ? undefined : -1;
|
|
33
35
|
return (React.createElement(C3NavigationSideBar, { sideBar: {
|
|
@@ -51,14 +53,16 @@ const C3UserSidebar = ({ sideBar }) => {
|
|
|
51
53
|
React.createElement(Stack, null,
|
|
52
54
|
React.createElement("div", { className: "textPrimary", style: { fontSize: "14px" } }, profile.user.name),
|
|
53
55
|
React.createElement("div", { className: "textPrimary", style: { fontSize: "12px" } }, profile.user.email))))),
|
|
54
|
-
themeSelector && (React.createElement(React.Fragment, null,
|
|
56
|
+
themeSelector && (typeof themeSelector !== "boolean" || enabled) && (React.createElement(React.Fragment, null,
|
|
55
57
|
React.createElement(SwitcherDivider, null),
|
|
56
58
|
React.createElement("div", { style: {
|
|
57
59
|
padding: ".5rem 1rem",
|
|
58
60
|
} },
|
|
59
|
-
React.createElement(RadioButtonGroup, { name: "theme-radio-group",
|
|
60
|
-
themeSelector
|
|
61
|
-
|
|
61
|
+
React.createElement(RadioButtonGroup, { name: "theme-radio-group", legendText: "Theme", orientation: "vertical", onChange: (newValue) => {
|
|
62
|
+
themeSelector === true
|
|
63
|
+
? onThemeChange(newValue)
|
|
64
|
+
: themeSelector.onChange(newValue);
|
|
65
|
+
}, valueSelected: themeSelector === true ? theme : themeSelector.currentTheme },
|
|
62
66
|
React.createElement(RadioButton, { id: "light", labelText: "Light", value: "light", tabIndex: itemTabIndex }),
|
|
63
67
|
React.createElement(RadioButton, { id: "system", labelText: "System", value: "system", tabIndex: itemTabIndex }),
|
|
64
68
|
React.createElement(RadioButton, { id: "dark", labelText: "Dark", value: "dark", tabIndex: itemTabIndex }))))),
|
package/lib/esm/components/c3-navigation/c3-notification-provider/c3-notification-provider.js
CHANGED
|
@@ -16,7 +16,7 @@ const C3NotificationProvider = ({ children, }) => {
|
|
|
16
16
|
const [activeOrganizationId, setActiveOrganizationId] = useState("");
|
|
17
17
|
const [isEventStreamAvailable, setEventStreamAvailable] = useState(false);
|
|
18
18
|
const config = useContext(C3UserConfigurationContext);
|
|
19
|
-
const enabled = !!config;
|
|
19
|
+
const enabled = !!config && !!config.activeOrganizationId && !!config.userToken;
|
|
20
20
|
// if the organization changes, we need to reset the state
|
|
21
21
|
if (enabled && config.activeOrganizationId !== activeOrganizationId) {
|
|
22
22
|
setActiveOrganizationId(config.activeOrganizationId);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React, { ComponentType, FC, PropsWithChildren } from "react";
|
|
2
|
+
export type Theme = "light" | "dark" | "system";
|
|
3
|
+
export type C3ProfileContextValue = {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
theme: Theme;
|
|
6
|
+
onThemeChange: (newTheme: Theme) => void;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const C3ProfileContext: React.Context<C3ProfileContextValue>;
|
|
10
|
+
export declare const C3ProfileProvider: FC<PropsWithChildren>;
|
|
11
|
+
export declare function withProfile<P>(Component: ComponentType<P>): ComponentType<P>;
|
|
12
|
+
export declare const useC3Profile: () => C3ProfileContextValue;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useState, } from "react";
|
|
2
|
+
import { C3UserConfigurationContext } from "../../c3-user-configuration/c3-user-configuration-provider";
|
|
3
|
+
import { getUserTheme, updateTheme } from "../../../api/profile";
|
|
4
|
+
import { ThemeProvider } from "./c3-theme-provider";
|
|
5
|
+
const defaultTheme = "light";
|
|
6
|
+
export const C3ProfileContext = createContext({
|
|
7
|
+
enabled: false,
|
|
8
|
+
theme: defaultTheme,
|
|
9
|
+
onThemeChange: () => undefined,
|
|
10
|
+
isLoading: false,
|
|
11
|
+
});
|
|
12
|
+
export const C3ProfileProvider = ({ children }) => {
|
|
13
|
+
const config = useContext(C3UserConfigurationContext);
|
|
14
|
+
const enabled = !!config;
|
|
15
|
+
const [theme, setTheme] = useState(defaultTheme);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (enabled && config?.userToken) {
|
|
19
|
+
const currentTheme = getUserTheme(config.userToken);
|
|
20
|
+
if (currentTheme)
|
|
21
|
+
setTheme(currentTheme);
|
|
22
|
+
setIsLoading(false);
|
|
23
|
+
}
|
|
24
|
+
}, [config?.userToken]);
|
|
25
|
+
const onThemeChange = (newTheme) => {
|
|
26
|
+
if (enabled) {
|
|
27
|
+
setTheme(newTheme);
|
|
28
|
+
updateTheme({ ...config, theme: newTheme });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return (React.createElement(C3ProfileContext.Provider, { value: { enabled, theme, onThemeChange, isLoading } }, children));
|
|
32
|
+
};
|
|
33
|
+
export function withProfile(Component) {
|
|
34
|
+
return function WithNamespace(props) {
|
|
35
|
+
return (React.createElement(C3ProfileProvider, null,
|
|
36
|
+
React.createElement(ThemeProvider, null,
|
|
37
|
+
React.createElement(Component, { ...props }))));
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export const useC3Profile = () => useContext(C3ProfileContext);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useC3Profile } from "./c3-profile-provider";
|
|
3
|
+
import { Theme } from "@carbon/react";
|
|
4
|
+
const THEMES = { light: "g10", dark: "g100" };
|
|
5
|
+
export const ThemeProvider = ({ children }) => {
|
|
6
|
+
const { theme } = useC3Profile();
|
|
7
|
+
const carbonTheme = theme === "light" ||
|
|
8
|
+
window.matchMedia("(prefers-color-scheme: light)").matches
|
|
9
|
+
? THEMES.light
|
|
10
|
+
: THEMES.dark;
|
|
11
|
+
return React.createElement(Theme, { theme: carbonTheme }, children);
|
|
12
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { C3Navigation } from "./c3-navigation";
|
|
2
2
|
import { withNotifications } from "./c3-notification-provider/c3-notification-provider";
|
|
3
|
-
|
|
3
|
+
import { withProfile } from "./c3-profile-provider/c3-profile-provider";
|
|
4
|
+
export default withProfile(withNotifications(C3Navigation));
|
|
@@ -19,6 +19,7 @@ export declare function createOrgSideBarProps(options: {
|
|
|
19
19
|
export declare function createUserSideBarProps(options: {
|
|
20
20
|
isOpen: boolean;
|
|
21
21
|
customSection?: React.JSX.Element;
|
|
22
|
+
themeSelector?: true;
|
|
22
23
|
}): C3NavigationProps["userSideBar"];
|
|
23
24
|
export declare function createNotificationSideBarProps(options: {
|
|
24
25
|
isOpen: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camunda/camunda-composite-components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4-rc.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"clean": "rimraf lib/",
|
|
6
6
|
"build": "yarn clean && tsc",
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"eslint-plugin-storybook": "0.6.13",
|
|
67
67
|
"event-source-polyfill": "1.0.31",
|
|
68
68
|
"husky": "8.0.3",
|
|
69
|
-
"playwright": "1.37.1",
|
|
70
69
|
"prettier": "2.8.8",
|
|
71
70
|
"react": "18.2.0",
|
|
72
71
|
"react-dom": "18.2.0",
|
|
@@ -81,6 +80,9 @@
|
|
|
81
80
|
"wait-on": "7.0.1",
|
|
82
81
|
"webpack": "5.88.2"
|
|
83
82
|
},
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"jwt-decode": "3.1.2"
|
|
85
|
+
},
|
|
84
86
|
"peerDependencies": {
|
|
85
87
|
"@carbon/react": "1.x",
|
|
86
88
|
"event-source-polyfill": "1.0.x",
|