Skip to content

Commit

Permalink
feat: add useDefaultProps
Browse files Browse the repository at this point in the history
- wraps component props to extend default props from theme object
  • Loading branch information
zettca committed Aug 2, 2023
1 parent 88368c6 commit 376f97e
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 1 deletion.
2 changes: 2 additions & 0 deletions packages/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export * from "./useClickOutside";
export * from "./useControlled";
export * from "./useForkRef";
export * from "./useCss";
export * from "./useDefaultProps";
export * from "./useImageLoaded";
export * from "./useWidth";
export * from "./useLabels";
Expand Down
47 changes: 47 additions & 0 deletions packages/core/src/hooks/useDefaultProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useMemo } from "react";
import { useCss } from "./useCss";
import { useTheme } from "./useTheme";

/** Filter out `undefined` entries from `props` object. */
export function filterProps(props: Record<string, any>) {
return Object.keys(props).reduce((acc, key) => {
if (props[key] !== undefined) {
acc[key] = props[key];
}
return acc;
}, {} as typeof props);
}

/** Injects into `props` the props defined in the theme `componentName`. */
export function useDefaultProps<T extends Record<string, any>>(
/** Name of the theme component key to inject defaultProps */
componentName: string, // keyof HvThemeComponents,
props: T
): T {
const { activeTheme } = useTheme();
const { css, cx } = useCss();

const themeDefaultProps = activeTheme?.components?.[componentName];

const classes = useMemo(() => {
const themeClasses = themeDefaultProps?.classes || {};
const propsClasses = props?.classes || {};
const classKeys = [
...Object.keys(themeClasses),
...Object.keys(propsClasses),
];
return classKeys.reduce((acc, key) => {
acc[key] = cx(
themeClasses[key] && css(themeClasses[key]),
propsClasses[key]
);
return acc;
}, {} as Record<string, string>);
}, [css, cx, props?.classes, themeDefaultProps?.classes]);

return {
...themeDefaultProps,
...filterProps(props),
classes,
};
}
1 change: 1 addition & 0 deletions packages/styles/src/themes/ds3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ const ds3 = makeTheme((theme: HvTheme) => ({
textDecoration: "underline",
},
},
components: {},
actionBar: {
borderTop: `3px solid ${theme.colors.atmo2}`,
},
Expand Down
1 change: 1 addition & 0 deletions packages/styles/src/themes/ds5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const ds5 = makeTheme((theme: HvTheme) => ({
textDecoration: "underline",
},
},
components: {},
actionBar: {
borderTop: `1px solid ${theme.colors.atmo3}`,
},
Expand Down
10 changes: 9 additions & 1 deletion packages/styles/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ interface CSSProperties extends CSS.Properties<string | number> {}

export type HvThemeTokens = typeof flattenTokens;

// Theme components
/** Theme components props */
export type HvThemeComponentsProps<ComponentNames extends string = string> = {
/** Component properties to override */
components?: Record<ComponentNames, Record<string, any>>;
};

/** Theme components */
export type HvThemeComponents = {
actionBar: {
borderTop: string;
Expand Down Expand Up @@ -498,6 +504,7 @@ export type HvThemeStructure = {
name: string;
base?: HvBaseTheme;
} & HvThemeComponents &
HvThemeComponentsProps &
HvThemeTypography &
Omit<HvThemeTokens, "colors"> & {
colors: {
Expand All @@ -509,6 +516,7 @@ export type HvThemeStructure = {

// Custom theme
export type HvCustomTheme = { name: string } & HvThemeComponents &
HvThemeComponentsProps &
HvThemeTypography &
Partial<Omit<HvThemeTokens, "colors">> & {
colors: {
Expand Down

0 comments on commit 376f97e

Please sign in to comment.