documentation-site/components/yard/provider.ts (120 lines of code) (raw):
/*
Copyright (c) Uber Technologies, Inc.
This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
import * as t from "@babel/types";
import traverse from "@babel/traverse";
import type { Theme } from "baseui";
import type { TProvider } from "react-view";
import { getAstJsxElement } from "react-view";
export const getThemeFromContext = (theme: Theme, themeConfig: string[]) => {
const componentThemeObj: { [key: string]: string } = {};
themeConfig.forEach((key) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
componentThemeObj[key] = (theme.colors as any)[key];
});
return componentThemeObj;
};
export const getActiveTheme = (
values: { [key: string]: string },
initialValues: { [key: string]: string },
) => {
const activeValues: { [key: string]: string } = {};
Object.keys(initialValues).forEach((key) => {
activeValues[key] = initialValues[key];
if (values && values[key]) {
activeValues[key] = values[key];
}
});
return activeValues;
};
export const getThemeDiff = (
values: { [key: string]: string },
initialValues: { [key: string]: string },
) => {
const diff: { [key: string]: string } = {};
Object.keys(values).forEach((key) => {
if (
initialValues[key] &&
values[key] &&
initialValues[key] !== values[key]
) {
diff[key] = values[key];
}
});
return diff;
};
export type TProviderValue = { [key: string]: string } | undefined;
export const getProvider = (
initialThemeValues: { [key: string]: string },
themePrimitives: string,
): TProvider => {
return {
value: undefined,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parse: (astRoot: any): TProviderValue => {
const newThemeValues: { [key: string]: string } = {};
traverse(astRoot, {
CallExpression(path) {
if (
//@ts-ignore
path.node.callee.name === "createTheme" &&
path.node.arguments.length === 2 &&
//@ts-ignore
path.node.arguments[1].properties.length === 1
) {
//@ts-ignore
const colors = path.node.arguments[1].properties[0].value;
colors.properties.forEach((prop: t.ObjectProperty) => {
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initialThemeValues[(prop.key as any).name] !==
(prop.value as t.StringLiteral).value
) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
newThemeValues[(prop.key as any).name] = (
prop.value as t.StringLiteral
).value;
}
});
}
},
});
return Object.keys(newThemeValues).length > 0
? newThemeValues
: undefined;
},
//@ts-ignore
generate: (value: TProviderValue, childTree: t.JSXElement) =>
generate(value, childTree, themePrimitives),
imports: {
baseui: {
named: ["ThemeProvider", "createTheme", themePrimitives],
},
},
};
};
export const generate = (
values: { [key: string]: string } | undefined,
childTree: t.JSXElement,
themePrimitives: string,
) => {
if (!values || Object.keys(values).length === 0) {
return childTree;
}
return getAstJsxElement(
"ThemeProvider",
[
t.jsxAttribute(
t.jsxIdentifier("theme"),
t.jsxExpressionContainer(
t.callExpression(t.identifier("createTheme"), [
t.identifier(themePrimitives),
t.objectExpression([
t.objectProperty(
t.identifier("colors"),
t.objectExpression(
Object.entries(values).map(([name, value]) =>
t.objectProperty(
t.identifier(name),
t.stringLiteral(value as string),
),
),
),
),
]),
]),
),
),
],
[childTree],
);
};