feat(system): dynamic variants generator created, types are working, build types failing

This commit is contained in:
Junior Garcia 2022-10-30 03:39:08 -03:00
parent d1e9bc4894
commit e34591611a
7 changed files with 142 additions and 73 deletions

View File

@ -1,5 +1,4 @@
import {BaseItem, ItemProps} from "@nextui-org/aria-utils";
import {CSSProp} from "@nextui-org/system";
import {FocusableProps} from "@react-types/shared";
import {ReactNode} from "react";

View File

@ -10,7 +10,6 @@ import {
StyledCollapseItemButton,
StyledCollapseItemTitle,
StyledCollapseItemIndicator,
collapseItemVariants,
} from "./collapse.styles";
import {UseCollapseItemProps, useCollapseItem} from "./use-collapse-item";
@ -59,7 +58,7 @@ const CollapseItem = forwardRef<CollapseItemProps, "div">((props, ref) => {
return (
<StyledCollapseItem
className={clsx("nextui-collapse-item", collapseItemVariants(), className)}
className={clsx("nextui-collapse-item", className)}
isDisabled={isDisabled}
isOpen={isOpen}
{...otherProps}

View File

@ -1,6 +1,14 @@
import {styled, css, getVariants, VariantProps} from "@nextui-org/system";
import {styled, generateVariants, GeneratedVariantsProps} from "@nextui-org/system";
import {cssFocusVisible} from "@nextui-org/shared-css";
/**
* Variants
*/
export const itemVariants = generateVariants({
borderWeight: "borderWidth",
dividerWeight: "borderWidth",
});
export const StyledCollapse = styled("div", {
width: "100%",
maxWidth: "400px",
@ -10,41 +18,45 @@ export const StyledCollapse = styled("div", {
margin: "0",
});
export const StyledCollapseItem = styled("div", {
zIndex: "inherit",
position: "relative",
display: "list-item",
margin: "0",
marginBottom: "$4",
borderBottom: "#333333 solid transparent",
"&:first-of-type": {
borderTop: "#333333 solid transparent",
},
".collapse-item-heading": {
margin: 0,
},
".collapse-item-indicator": {
marginLeft: "8px",
},
".collapse-item-content": {
display: "none",
background: "red",
padding: "6px 10px 10px",
},
variants: {
isOpen: {
true: {
".collapse-item-content": {
display: "block",
export const StyledCollapseItem = styled(
"div",
{
zIndex: "inherit",
position: "relative",
display: "list-item",
margin: "0",
marginBottom: "$4",
borderBottom: "#333333 solid transparent",
"&:first-of-type": {
borderTop: "#333333 solid transparent",
},
".collapse-item-heading": {
margin: 0,
},
".collapse-item-indicator": {
marginLeft: "8px",
},
".collapse-item-content": {
display: "none",
background: "red",
padding: "6px 10px 10px",
},
variants: {
isOpen: {
true: {
".collapse-item-content": {
display: "block",
},
},
},
},
isSelectable: {},
isDisabled: {
true: {},
isSelectable: {},
isDisabled: {
true: {},
},
},
},
});
itemVariants as any,
);
export const StyledCollapseItemHeading = styled("h2", {});
@ -87,15 +99,4 @@ export const StyledCollapseItemIndicator = styled("span", {
},
});
export const collapseItemVariants = css({
variants: {
borderWeight: {
...getVariants("borderWidths", "borderWidth"),
},
dividerWeight: {
...getVariants("borderWidths", "borderWidth"),
},
},
});
export type CollapseItemVariantProps = VariantProps<typeof collapseItemVariants>;
export type CollapseItemVariantProps = GeneratedVariantsProps<typeof itemVariants>;

View File

@ -5,7 +5,7 @@ import {TreeState} from "@react-stately/tree";
import {callAllHandlers, ReactRef} from "@nextui-org/shared-utils";
import {useAccordionItem, NodeWithProps} from "@nextui-org/aria-utils";
import {useDOMRef} from "@nextui-org/dom-utils";
import {Key, useMemo} from "react";
import {Key} from "react";
import CollapseIcon from "./collapse-icon";
@ -75,25 +75,13 @@ export function useCollapseItem<T extends object>(props: UseCollapseItemProps<T>
onFocusChange?.(false);
};
const scopeTokens = useMemo(() => {
return {
$$collapseItemBorderWeight: `$borderWeights${borderWeight}`,
$$collapseItemDividerWeight: `$borderWeights${dividerWeight}`,
};
}, [borderWeight, dividerWeight]);
const itemCss = useMemo(() => {
return {
...scopeTokens,
...css,
};
}, [css, scopeTokens]);
return {
as,
domRef,
item,
css: itemCss,
css,
borderWeight,
dividerWeight,
indicator,
subtitle,
variant,

View File

@ -10,7 +10,7 @@ export default {
export const Default = () => (
<Collapse selectionMode="single">
<Collapse.Item key="1" dividerWeight="black" title="Your files">
<Collapse.Item key="1" title="Your files">
file
</Collapse.Item>
<Collapse.Item key="2" title="Shared with you">
@ -32,14 +32,7 @@ export const CustomIndicator = () => {
return (
<Collapse selectionMode="single">
<Collapse.Item
key="1"
dividerWeight={{
"@xsMax": "black",
}}
indicator={renderIndicator}
title="Your files"
>
<Collapse.Item key="1" indicator={renderIndicator} title="Your files">
file
</Collapse.Item>
<Collapse.Item key="2" title="Shared with you">

View File

@ -270,7 +270,20 @@ export const defaultTokens = {
dropdownItem:
"background 0.12s ease, transform 0.12s ease, color 0.12s ease, box-shadow 0.12s ease 0s",
},
borderStyles: {
solid: "solid",
dashed: "dashed",
dotted: "dotted",
double: "double",
groove: "groove",
ridge: "ridge",
inset: "inset",
outset: "outset",
hidden: "hidden",
none: "none",
},
colors: defaultColors,
shadows: {},
};
export const defaultMedia = {
@ -563,7 +576,9 @@ export type Space = typeof defaultTokens.space;
export type Sizes = typeof defaultTokens.sizes;
export type Radii = typeof defaultTokens.radii;
export type ZIndices = typeof defaultTokens.zIndices;
export type BorderStyles = typeof defaultTokens.borderStyles;
export type BorderWidths = typeof defaultTokens.borderWidths;
export type Shadows = typeof defaultTokens.shadows;
export type Transitions = typeof defaultTokens.transitions;
export type Colors = typeof defaultColors;
@ -580,6 +595,8 @@ export type TokensGroup = {
borderWidths: BorderWidths;
transitions: Transitions;
colors: Colors;
borderStyles: BorderStyles;
shadows: Shadows;
};
// defaultMedia

View File

@ -1,15 +1,25 @@
import type * as Stitches from "@stitches/react";
import {TokensGroup, defaultTokens} from "./common";
import {CssComponent} from "@stitches/react/types/styled-component";
import {TokensGroup, ThemeMap, Media, defaultTokens, defaultThemeMap} from "./common";
// TODO: Take ThemeMap, token keys & default theme map, from `theme` (stitches.config.ts)
type TokenKeys = keyof typeof defaultTokens;
type CSSProperties = Stitches.CSSProperties;
type VariantsToGenerate = {
[K in string]: keyof ThemeMap;
};
/**
*
* This function returns the possible key/values for a given token scale. It allows to generate variant values
* dynamically based on the tokens defined in the theme.
*
* @param tokensGroup The tokens group to use
* @param tokenKey The token key to use
*
* @example
* getVariants("fonts", "fontFamily")
*
@ -40,3 +50,65 @@ export function getVariants<TK extends TokenKeys>(scale: TK, prop: keyof CSSProp
[K in keyof TokensGroup[TK]]: {[P in keyof CSSProperties]: TokensGroup[TK][K]};
};
}
/**
* This function generates variants based on the key & tokens defined in the theme.
*
* @param variants The variants to generate
*
* @example
* generateVariants({
* bgColor: "backgroundColor",
* color: "colors",
* })
*
* // returns
*
* variants: {
* "bgColor": {
* "primary": {},
* "secondary": {},
* "success": {},
* .... all the colors defined in the theme
* },
* "color": {
* "primary": {},
* "secondary": {},
* "success": {},
* .... all the colors defined in the theme
* },
* ... all the variants to generate
* }
*/
export function generateVariants<VG extends VariantsToGenerate>(vg: VG) {
const variants = Object.keys(vg).reduce((acc, themeMapKey) => {
const key = vg[themeMapKey];
if (!defaultThemeMap[key as keyof ThemeMap]) {
return acc;
}
const mapKey = defaultThemeMap[key];
// @ts-ignore
acc[themeMapKey] = getVariants(mapKey, key);
return acc;
}, {});
return {variants} as unknown as {
variants: {
[K in keyof VG]?: keyof TokensGroup[ThemeMap[VG[K]]];
};
};
}
type ComponentVariants = {
variants?: {
[Name in string]: unknown;
};
};
export type GeneratedVariantsProps<V extends ComponentVariants> = V extends ComponentVariants
? Stitches.VariantProps<CssComponent<never, V["variants"], Media>>
: never;