@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
161 lines (160 loc) • 8.05 kB
JavaScript
;
// refactor for v5
/// <reference types="@types/node" />
Object.defineProperty(exports, "__esModule", { value: true });
exports.useTheme = exports.getTheme = void 0;
const react_1 = require("@emotion/react");
const index_1 = require("./index");
const canvas_kit_styling_1 = require("@workday/canvas-kit-styling");
const canvas_tokens_web_1 = require("@workday/canvas-tokens-web");
/**
* Attempt to match chroma-js's darken/brighten behavior using OKLCH.
* Chroma's darken(1) reduces LAB lightness by ~18 units (out of 100).
* In OKLCH, lightness is 0-1, so we scale: value/100 * 0.18 = value * 0.0018
* @deprecated ⚠️ `shiftColor` is deprecated and will be removed in a future major version. While we work on an algorithm for color shifting, you can use [`oklch from`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) to generate a palette.
*/
const shiftColor = (color, value) => {
const shift = Math.abs(value) * 0.0018;
return `oklch(from ${color} calc(l ${value > 0 ? '+' : '-'} ${shift}) c h)`;
};
const generatePalette = (key, palette) => {
const colorPalette = palette === null || palette === void 0 ? void 0 : palette[key];
if (colorPalette) {
const defaultPalette = index_1.defaultCanvasTheme.palette[key];
return {
lightest: colorPalette.lightest ||
(colorPalette.main && shiftColor(colorPalette.main, 400)) ||
defaultPalette.lightest,
lighter: colorPalette.lighter ||
(colorPalette.main && shiftColor(colorPalette.main, 150)) ||
defaultPalette.lighter,
light: colorPalette.light ||
(colorPalette.main && shiftColor(colorPalette.main, 100)) ||
defaultPalette.light,
main: colorPalette.main || defaultPalette.main,
dark: colorPalette.dark ||
(colorPalette.main && shiftColor(colorPalette.main, -100)) ||
defaultPalette.dark,
darkest: colorPalette.darkest ||
(colorPalette.main && shiftColor(colorPalette.main, -200)) ||
defaultPalette.darkest,
contrast: colorPalette.contrast || (0, canvas_kit_styling_1.cssVar)(canvas_tokens_web_1.base.neutral0),
};
}
return index_1.defaultCanvasTheme.palette[key];
};
const generateTheme = (theme) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
return {
palette: {
primary: generatePalette('primary', (_a = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _a === void 0 ? void 0 : _a.palette),
alert: generatePalette('alert', (_b = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _b === void 0 ? void 0 : _b.palette),
error: generatePalette('error', (_c = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _c === void 0 ? void 0 : _c.palette),
success: generatePalette('success', (_d = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _d === void 0 ? void 0 : _d.palette),
neutral: generatePalette('neutral', (_e = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _e === void 0 ? void 0 : _e.palette),
common: { ...index_1.defaultCanvasTheme.palette.common, ...(_g = (_f = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _f === void 0 ? void 0 : _f.palette) === null || _g === void 0 ? void 0 : _g.common },
},
breakpoints: index_1.defaultCanvasTheme.breakpoints,
direction: ((_h = theme === null || theme === void 0 ? void 0 : theme.canvas) === null || _h === void 0 ? void 0 : _h.direction) || index_1.defaultCanvasTheme.direction,
};
};
const getFilledTheme = (theme) => {
return {
...index_1.defaultCanvasTheme,
...theme,
canvas: generateTheme(theme),
};
};
/**
* Function to get the correct theme object for `styled` and class components
* or to be used outside component.
* @param {Object=} theme - The theme object with the Canvas Kit theme.
* It should be namespaced within this variable under the `canvas` key.
* Value of `canvas` property is any partial or full theme object to overwtite default theme.
*
* @returns An object containing updated or default Canvas Kit theme under `canvas` key.
*
* The passed partial theme object will be merged with the default Canvas theme
* (using memoized createCanvasTheme()) to establish any missing fields that have
* not been defined by the consumer's theme object.
*
* If theme is not passed, the function will try to retrieve it from the window object.
* If window theme is not found, it will return the default Canvas theme.
*
* @example
* import {getTheme} from '@workday/canvas-kit-react/common';
*
* const theme = getTheme();
* const {up, down} = theme.canvas.breakpoints;
* const small = down('m'); // Returns '@media (max-width: 768px)'
* const medium = up('m'); // Returns '@media (min-width: 768px)'
*
* const styles = {
* [small]: {
* margin: space.m
* },
* [medium]: {
* margin: space.l
* }
* }
* @deprecated ⚠️ `getTheme` is deprecated and will be removed in a future major version. Please use our [CSS tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-brand-tokens--docs) to theme components.
*/
function getTheme(theme) {
var _a, _b;
if (theme === null || theme === void 0 ? void 0 : theme.canvas) {
return getFilledTheme(theme);
}
const windowTheme = typeof window !== 'undefined' && ((_b = (_a = window === null || window === void 0 ? void 0 : window.workday) === null || _a === void 0 ? void 0 : _a.canvas) === null || _b === void 0 ? void 0 : _b.theme);
if (windowTheme) {
return getFilledTheme({ canvas: windowTheme });
}
return { canvas: index_1.defaultCanvasTheme };
}
exports.getTheme = getTheme;
/**
* Hook function to get the correct theme object for functional components.
* @param {Object=} theme - The theme object with the Canvas Kit theme.
* It should be namespaced within this variable under the `canvas` key.
* Value of `canvas` property is any partial or full theme object to overwtite default theme.
*
* @returns An object containing updated or default Canvas Kit theme under `canvas` key.
*
* NOTE: If theme is not passed, the function will try to pull the theme from ThemeContext.
* If that does not work, it will try to retrieve it from the window object.
* As a last resort, it will return the default Canvas theme.
*
* The resulting theme will be merged with the default Canvas theme
* (using memoized createCanvasTheme()) to establish any missing fields that have
* not been defined by the consumer's theme object.
*
* Providing the default theme here is currently a work around for when no
* ThemeProvider or context exists.
* Tracked on https://github.com/emotion-js/emotion/issues/1193.
*
* @example
* export const ErrorMessage = () => {
* const theme = useTheme();
* return (
* <Subtext size="large" color={theme.canvas.palette.error.main}>
* );
* }
* @deprecated ⚠️ `useTheme` is deprecated and will be removed in a future major version. Please use our [CSS tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-brand-tokens--docs) to theme components.
*/
function useTheme(theme) {
if (!theme) {
try {
// eslint-disable-next-line react-hooks/rules-of-hooks
const contextTheme = (0, react_1.useTheme)();
if (contextTheme === null || contextTheme === void 0 ? void 0 : contextTheme.canvas) {
return getFilledTheme(contextTheme);
}
}
catch (e) {
if (process.env.NODE_ENV === 'development') {
console.warn('useTheme: Context not supported or invalid. Please consider using `getTheme` function instead for `styled` or class components.');
}
}
}
return getTheme(theme);
}
exports.useTheme = useTheme;