{
it('should be able to override styles', () => {
const StyledBlock = styled(Block, { styles: { color: '#clear.1' } });
const { container } = render(
-
,
+
,
);
expect(container).toMatchSnapshot();
diff --git a/src/styled/styled.tsx b/src/styled/styled.tsx
index 6f56d75a..ba7ed521 100644
--- a/src/styled/styled.tsx
+++ b/src/styled/styled.tsx
@@ -1,22 +1,36 @@
import styledComponents, { createGlobalStyle } from 'styled-components';
import { ComponentType, FC, forwardRef, useContext, useMemo } from 'react';
import { isValidElementType } from 'react-is';
-import { BreakpointsContext } from '../providers/BreakpointsProvider';
-import { modAttrs } from '../utils/react';
-import { useContextStyles } from '../providers/StylesProvider';
import {
AllBaseProps,
+ BASE_STYLES,
BaseStyleProps,
- StyledProps,
+ BreakpointsContext,
GlobalStyledProps,
-} from '../components/types';
-import { renderStyles } from '../utils/renderStyles';
-import { pointsToZones } from '../utils/responsive';
-import { Styles, StylesInterface } from '../styles/types';
-import { BASE_STYLES } from '../styles/list';
-import { ResponsiveStyleValue } from '../utils/styles';
-import { mergeStyles } from '../utils/mergeStyles';
-import { deprecationWarning } from '../utils/warnings';
+ modAttrs,
+ pointsToZones,
+ renderStyles,
+ ResponsiveStyleValue,
+ Styles,
+ StylesInterface,
+ useContextStyles,
+} from '../tasty';
+import { mergeStyles } from '../tasty';
+import { deprecationWarning } from '../tasty';
+
+export type StyledProps
= {
+ /** The name of the element. It can be used to override styles in context. */
+ name?: string;
+ /** The tag name of the element. */
+ tag?: string;
+ /** Default styles of the element. */
+ styles?: Styles;
+ /** Default css of the element. */
+ css?: string;
+ props?: DefaultProps;
+ /** The list of styles that can be provided by props */
+ styleProps?: K;
+};
export type AllBasePropsWithMods =
AllBaseProps & {
@@ -50,12 +64,21 @@ type EitherLegacyPropsOrInlined<
props?: 'You Should use either legacy props field or inline props';
} & DefaultProps);
+/**
+ * @deprecated Use `tasty()` helper instead.
+ */
function styled<
K extends (keyof StylesInterface)[],
Props,
DefaultProps extends Partial = Partial,
>(options: StyledProps, secondArg?: never);
+/**
+ * @deprecated Use `tasty()` helper instead.
+ */
function styled(selector: string, styles?: Styles);
+/**
+ * @deprecated Use `tasty()` helper instead.
+ */
function styled<
K extends (keyof StylesInterface)[],
Props extends { styles?: Styles },
@@ -200,12 +223,12 @@ function styled<
let contextBreakpoints = useContext(BreakpointsContext);
let zones = pointsToZones(breakpoints ?? contextBreakpoints);
+ let renderedStyles = useMemo(
+ () => renderStyles(allStyles, zones),
+ [allStyles, zones],
+ );
- css = `${
- typeof defaultCSS === 'function' ? defaultCSS(props) : defaultCSS ?? ''
- }${typeof css === 'function' ? css(props) : css ?? ''}${
- allStyles ? renderStyles(allStyles, zones) : ''
- }`;
+ css = `${defaultCSS ?? ''}${css ?? ''}${allStyles ? renderedStyles : ''}`;
if (mods) {
Object.assign(props, modAttrs(mods));
@@ -233,6 +256,4 @@ function styled<
return _StyledComponent;
}
-const tasty = styled;
-
-export { styled, tasty };
+export { styled };
diff --git a/src/tasty/__snapshots__/tasty.test.tsx.snap b/src/tasty/__snapshots__/tasty.test.tsx.snap
new file mode 100644
index 00000000..120c0a62
--- /dev/null
+++ b/src/tasty/__snapshots__/tasty.test.tsx.snap
@@ -0,0 +1,76 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`tasty() API should be able to override styles 1`] = `
+.c0 {
+ outline: none;
+}
+
+.c0[hidden] {
+ display: none !important;
+}
+
+.c0 {
+ color: rgba(var(--black-color-rgb),0.1);
+ --current-color: var(--black-color,black);
+ --current-color-rgb: var(--black-color-rgb);
+}
+
+
+`;
+
+exports[`tasty() API should create responsive styles 1`] = `
+.c0 {
+ outline: none;
+}
+
+.c0[hidden] {
+ display: none !important;
+}
+
+@media (min-width:980px) {
+ .c0 {
+ display: grid;
+ }
+}
+
+@media (max-width:979px) {
+ .c0 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+}
+
+
+`;
+
+exports[`tasty() API should pass styles from tasty 1`] = `
+.c0 {
+ outline: none;
+}
+
+.c0[hidden] {
+ display: none !important;
+}
+
+.c0 {
+ color: rgba(var(--clear-color-rgb),0.1);
+ --current-color: var(--clear-color,clear);
+ --current-color-rgb: var(--clear-color-rgb);
+}
+
+
+`;
diff --git a/src/tasty/index.ts b/src/tasty/index.ts
new file mode 100644
index 00000000..844ad9d5
--- /dev/null
+++ b/src/tasty/index.ts
@@ -0,0 +1,47 @@
+export * from '../styled/styled';
+export { tasty } from './tasty';
+export * from './utils/filterBaseProps';
+export * from './utils/colors';
+export * from './utils/styles';
+export * from './utils/modAttrs';
+export * from './utils/responsive';
+export * from './utils/renderStyles';
+export * from './utils/dotize';
+export * from './styles/list';
+export * from './providers/BreakpointsProvider';
+export * from './providers/StylesProvider';
+export * from './utils/mergeStyles';
+export * from './utils/warnings';
+export type {
+ TastyProps,
+ GlobalTastyProps,
+ AllBasePropsWithMods,
+} from './tasty';
+export type {
+ AllBaseProps,
+ BaseProps,
+ BaseStyleProps,
+ DimensionStyleProps,
+ ColorStyleProps,
+ OuterStyleProps,
+ PositionStyleProps,
+ TextStyleProps,
+ BlockStyleProps,
+ ContainerStyleProps,
+ BasePropsWithoutChildren,
+ Props,
+ FlowStyleProps,
+ ShortGridStyles,
+ GlobalStyledProps,
+ TagNameProps,
+ TagName,
+} from './types';
+export type {
+ StylesInterface,
+ Styles,
+ StylesWithoutSelectors,
+ NoType,
+ Selector,
+ SuffixForSelector,
+ NotSelector,
+} from './styles/types';
diff --git a/src/providers/BreakpointsProvider.tsx b/src/tasty/providers/BreakpointsProvider.tsx
similarity index 100%
rename from src/providers/BreakpointsProvider.tsx
rename to src/tasty/providers/BreakpointsProvider.tsx
diff --git a/src/providers/StylesProvider.tsx b/src/tasty/providers/StylesProvider.tsx
similarity index 100%
rename from src/providers/StylesProvider.tsx
rename to src/tasty/providers/StylesProvider.tsx
diff --git a/src/styles/align.ts b/src/tasty/styles/align.ts
similarity index 100%
rename from src/styles/align.ts
rename to src/tasty/styles/align.ts
diff --git a/src/styles/border.ts b/src/tasty/styles/border.ts
similarity index 100%
rename from src/styles/border.ts
rename to src/tasty/styles/border.ts
diff --git a/src/styles/boxShadow.combinator.ts b/src/tasty/styles/boxShadow.combinator.ts
similarity index 100%
rename from src/styles/boxShadow.combinator.ts
rename to src/tasty/styles/boxShadow.combinator.ts
diff --git a/src/styles/color.ts b/src/tasty/styles/color.ts
similarity index 100%
rename from src/styles/color.ts
rename to src/tasty/styles/color.ts
diff --git a/src/styles/createStyle.ts b/src/tasty/styles/createStyle.ts
similarity index 100%
rename from src/styles/createStyle.ts
rename to src/tasty/styles/createStyle.ts
diff --git a/src/styles/dimension.ts b/src/tasty/styles/dimension.ts
similarity index 100%
rename from src/styles/dimension.ts
rename to src/tasty/styles/dimension.ts
diff --git a/src/styles/display.ts b/src/tasty/styles/display.ts
similarity index 100%
rename from src/styles/display.ts
rename to src/tasty/styles/display.ts
diff --git a/src/styles/fill.ts b/src/tasty/styles/fill.ts
similarity index 100%
rename from src/styles/fill.ts
rename to src/tasty/styles/fill.ts
diff --git a/src/styles/flow.ts b/src/tasty/styles/flow.ts
similarity index 100%
rename from src/styles/flow.ts
rename to src/tasty/styles/flow.ts
diff --git a/src/styles/font.ts b/src/tasty/styles/font.ts
similarity index 87%
rename from src/styles/font.ts
rename to src/tasty/styles/font.ts
index 6cb59132..3c7cd5a7 100644
--- a/src/styles/font.ts
+++ b/src/tasty/styles/font.ts
@@ -1,8 +1,8 @@
export function fontStyle({ font }) {
if (font == null || font === false) return null;
- const fontFamily
- = font === 'monospace'
+ const fontFamily =
+ font === 'monospace'
? 'var(--monospace-font)'
: font === true
? 'var(--font)'
diff --git a/src/styles/fontStyle.ts b/src/tasty/styles/fontStyle.ts
similarity index 100%
rename from src/styles/fontStyle.ts
rename to src/tasty/styles/fontStyle.ts
diff --git a/src/styles/gap.ts b/src/tasty/styles/gap.ts
similarity index 100%
rename from src/styles/gap.ts
rename to src/tasty/styles/gap.ts
diff --git a/src/styles/groupRadius.ts b/src/tasty/styles/groupRadius.ts
similarity index 100%
rename from src/styles/groupRadius.ts
rename to src/tasty/styles/groupRadius.ts
diff --git a/src/styles/height.ts b/src/tasty/styles/height.ts
similarity index 100%
rename from src/styles/height.ts
rename to src/tasty/styles/height.ts
diff --git a/src/styles/index.ts b/src/tasty/styles/index.ts
similarity index 100%
rename from src/styles/index.ts
rename to src/tasty/styles/index.ts
diff --git a/src/styles/justify.ts b/src/tasty/styles/justify.ts
similarity index 100%
rename from src/styles/justify.ts
rename to src/tasty/styles/justify.ts
diff --git a/src/styles/list.ts b/src/tasty/styles/list.ts
similarity index 100%
rename from src/styles/list.ts
rename to src/tasty/styles/list.ts
diff --git a/src/styles/margin.ts b/src/tasty/styles/margin.ts
similarity index 88%
rename from src/styles/margin.ts
rename to src/tasty/styles/margin.ts
index e95faee3..d364a5a7 100644
--- a/src/styles/margin.ts
+++ b/src/tasty/styles/margin.ts
@@ -35,9 +35,9 @@ export function marginStyle({
const index = DIRECTIONS.indexOf(dir);
if (
- ((!!(index % 2) && marginInline == null)
- || (!(index % 2) && marginBlock == null))
- && marginDirs[index] == null
+ ((!!(index % 2) && marginInline == null) ||
+ (!(index % 2) && marginBlock == null)) &&
+ marginDirs[index] == null
) {
styles[`margin-${dir}`] = values[index] || values[index % 2] || values[0];
}
diff --git a/src/styles/marginBlock.ts b/src/tasty/styles/marginBlock.ts
similarity index 100%
rename from src/styles/marginBlock.ts
rename to src/tasty/styles/marginBlock.ts
diff --git a/src/styles/marginInline.ts b/src/tasty/styles/marginInline.ts
similarity index 100%
rename from src/styles/marginInline.ts
rename to src/tasty/styles/marginInline.ts
diff --git a/src/styles/outline.ts b/src/tasty/styles/outline.ts
similarity index 100%
rename from src/styles/outline.ts
rename to src/tasty/styles/outline.ts
diff --git a/src/styles/padding.ts b/src/tasty/styles/padding.ts
similarity index 80%
rename from src/styles/padding.ts
rename to src/tasty/styles/padding.ts
index 3fe120a5..3d46f905 100644
--- a/src/styles/padding.ts
+++ b/src/tasty/styles/padding.ts
@@ -35,12 +35,12 @@ export function paddingStyle({
const index = DIRECTIONS.indexOf(dir);
if (
- ((!!(index % 2) && paddingInline == null)
- || (!(index % 2) && paddingBlock == null))
- && paddingDirs[index] == null
+ ((!!(index % 2) && paddingInline == null) ||
+ (!(index % 2) && paddingBlock == null)) &&
+ paddingDirs[index] == null
) {
- styles[`padding-${dir}`]
- = values[index] || values[index % 2] || values[0];
+ styles[`padding-${dir}`] =
+ values[index] || values[index % 2] || values[0];
}
return styles;
diff --git a/src/styles/paddingBlock.ts b/src/tasty/styles/paddingBlock.ts
similarity index 100%
rename from src/styles/paddingBlock.ts
rename to src/tasty/styles/paddingBlock.ts
diff --git a/src/styles/paddingInline.ts b/src/tasty/styles/paddingInline.ts
similarity index 100%
rename from src/styles/paddingInline.ts
rename to src/tasty/styles/paddingInline.ts
diff --git a/src/styles/predefined.ts b/src/tasty/styles/predefined.ts
similarity index 100%
rename from src/styles/predefined.ts
rename to src/tasty/styles/predefined.ts
diff --git a/src/styles/preset.ts b/src/tasty/styles/preset.ts
similarity index 100%
rename from src/styles/preset.ts
rename to src/tasty/styles/preset.ts
diff --git a/src/styles/radius.ts b/src/tasty/styles/radius.ts
similarity index 100%
rename from src/styles/radius.ts
rename to src/tasty/styles/radius.ts
diff --git a/src/styles/reset.ts b/src/tasty/styles/reset.ts
similarity index 100%
rename from src/styles/reset.ts
rename to src/tasty/styles/reset.ts
diff --git a/src/styles/shadow.ts b/src/tasty/styles/shadow.ts
similarity index 100%
rename from src/styles/shadow.ts
rename to src/tasty/styles/shadow.ts
diff --git a/src/styles/styledScrollbar.ts b/src/tasty/styles/styledScrollbar.ts
similarity index 100%
rename from src/styles/styledScrollbar.ts
rename to src/tasty/styles/styledScrollbar.ts
diff --git a/src/styles/transition.ts b/src/tasty/styles/transition.ts
similarity index 100%
rename from src/styles/transition.ts
rename to src/tasty/styles/transition.ts
diff --git a/src/styles/types.ts b/src/tasty/styles/types.ts
similarity index 100%
rename from src/styles/types.ts
rename to src/tasty/styles/types.ts
diff --git a/src/styles/width.ts b/src/tasty/styles/width.ts
similarity index 100%
rename from src/styles/width.ts
rename to src/tasty/styles/width.ts
diff --git a/src/tasty/tasty.test.tsx b/src/tasty/tasty.test.tsx
new file mode 100644
index 00000000..d891dd5f
--- /dev/null
+++ b/src/tasty/tasty.test.tsx
@@ -0,0 +1,56 @@
+import { getByTestId, render } from '@testing-library/react';
+import { tasty } from './tasty';
+import { Button } from '../components/actions';
+import { Block } from '../components/Block';
+
+describe('tasty() API', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ afterAll(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('should provide defaults and give ability to override', () => {
+ const SButton = tasty(Button, { type: 'primary' });
+
+ const { getByTestId, rerender } = render(
+ ,
+ );
+ expect(getByTestId('button').dataset.type).toBe('primary');
+
+ rerender();
+ expect(getByTestId('button').dataset.type).toBe('secondary');
+ });
+
+ it('should pass styles from tasty', () => {
+ const StyledBlock = tasty(Block, { styles: { color: '#clear.1' } });
+ const { container } = render();
+
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should be able to override styles', () => {
+ const StyledBlock = tasty(Block, { styles: { color: '#clear.1' } });
+ const { container } = render(
+ ,
+ );
+
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should pass qa prop', () => {
+ const StyledBlock = tasty({ qa: 'Field' });
+ const { container } = render();
+
+ expect(getByTestId(container, 'Field', {})).toBeDefined();
+ });
+
+ it('should create responsive styles', () => {
+ const StyledBlock = tasty(Block, { styles: { display: ['grid', 'flex'] } });
+ const { container } = render();
+
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/tasty/tasty.tsx b/src/tasty/tasty.tsx
new file mode 100644
index 00000000..e6d3bfae
--- /dev/null
+++ b/src/tasty/tasty.tsx
@@ -0,0 +1,215 @@
+import styledComponents, { createGlobalStyle } from 'styled-components';
+import { ComponentType, FC, forwardRef, useContext, useMemo } from 'react';
+import { isValidElementType } from 'react-is';
+import { BreakpointsContext } from './providers/BreakpointsProvider';
+import { modAttrs } from './utils/modAttrs';
+import { AllBaseProps, BaseStyleProps, Props } from './types';
+import { renderStyles } from './utils/renderStyles';
+import { pointsToZones } from './utils/responsive';
+import { Styles, StylesInterface } from './styles/types';
+import { BASE_STYLES } from './styles/list';
+import { ResponsiveStyleValue } from './utils/styles';
+import { mergeStyles } from './utils/mergeStyles';
+
+export type TastyProps<
+ K extends (keyof StylesInterface)[],
+ DefaultProps = Props,
+> = {
+ /** The tag name of the element. */
+ as?: string;
+ /** Default styles of the element. */
+ styles?: Styles;
+ /** The list of styles that can be provided by props */
+ styleProps?: K;
+} & Omit;
+
+export interface GlobalTastyProps {
+ breakpoints?: number[];
+}
+
+export type AllBasePropsWithMods =
+ AllBaseProps & {
+ [key in K[number]]?: ResponsiveStyleValue;
+ } & BaseStyleProps;
+
+type TastyPropsWithDefaults<
+ Props extends { styles?: Styles },
+ DefaultProps extends Partial,
+> = keyof DefaultProps extends never
+ ? Props
+ : {
+ [key in Extract]?: Props[key];
+ } & {
+ [key in keyof Omit]: Props[key];
+ };
+
+function tasty(
+ options: TastyProps,
+ secondArg?: never,
+);
+function tasty(selector: string, styles?: Styles);
+function tasty<
+ Props extends { styles?: Styles },
+ DefaultProps extends Partial = Partial,
+>(
+ Component: ComponentType,
+ options?: TastyProps,
+): ComponentType>;
+
+// Implementation
+function tasty<
+ K extends (keyof StylesInterface)[],
+ C = Record,
+>(Component, options) {
+ if (typeof Component === 'string') {
+ let selector = Component;
+ let styles = options;
+ let Element = createGlobalStyle`${(css) => css}`;
+
+ const _StyleDeclarationComponent: FC = ({
+ breakpoints,
+ }) => {
+ let contextBreakpoints = useContext(BreakpointsContext);
+
+ breakpoints = breakpoints ?? contextBreakpoints;
+
+ let css = useMemo(
+ () =>
+ styles
+ ? `\n{}${selector}{${renderStyles(
+ styles,
+ pointsToZones(breakpoints || contextBreakpoints),
+ )}}`
+ : '',
+ [breakpoints.join(',')],
+ );
+
+ return ;
+ };
+
+ _StyleDeclarationComponent.displayName = `TastyStyleDeclaration(${Component})`;
+
+ return _StyleDeclarationComponent;
+ }
+
+ if (isValidElementType(Component)) {
+ let { as: extendTag, ...defaultProps } = options ?? {};
+
+ let propsWithStyles = ['styles'].concat(
+ Object.keys(defaultProps).filter((prop) => prop.endsWith('Styles')),
+ );
+
+ let _WrappedComponent = forwardRef((props: C, ref) => {
+ const { as, ...restProps } = props as AllBasePropsWithMods;
+ const propsWithStylesValues = propsWithStyles.map((prop) => props[prop]);
+
+ const mergedStylesMap: Styles | undefined = useMemo(() => {
+ return propsWithStylesValues.reduce((map, prop) => {
+ if (restProps[prop] != null && defaultProps[prop] != null) {
+ map[prop] = mergeStyles(restProps[prop], defaultProps[prop]);
+ }
+
+ return map;
+ }, {});
+ }, propsWithStylesValues);
+
+ return (
+
+ );
+ });
+
+ _WrappedComponent.displayName = `TastyWrappedComponent(${
+ Component.displayName ??
+ Component.name ??
+ defaultProps.qa ??
+ extendTag ??
+ 'Anonymous'
+ })`;
+
+ return _WrappedComponent;
+ }
+
+ options = Component;
+
+ let {
+ as: originalAs = 'div',
+ styles: defaultStyles,
+ styleProps,
+ ...defaultProps
+ } = options;
+
+ let Element = styledComponents[originalAs](({ css }) => css);
+
+ let _TastyComponent = forwardRef((allProps: AllBasePropsWithMods, ref) => {
+ let { as, styles, breakpoints, mods, element, qa, qaVal, ...otherProps } =
+ allProps;
+
+ let {
+ qa: defaultQa,
+ qaVal: defaultQaVal,
+ ...otherDefaultProps
+ } = defaultProps ?? {};
+
+ let propStyles: Styles = (
+ (styleProps
+ ? (styleProps as (keyof StylesInterface)[]).concat(BASE_STYLES)
+ : BASE_STYLES) as (keyof StylesInterface)[]
+ ).reduce((map, prop) => {
+ if (prop in otherProps) {
+ map[prop] = otherProps[prop];
+
+ delete otherProps[prop];
+ }
+
+ return map;
+ }, {});
+
+ let allStyles: Styles = useMemo(
+ () => mergeStyles(defaultStyles, styles, propStyles),
+ [styles, propStyles],
+ );
+
+ let contextBreakpoints = useContext(BreakpointsContext);
+
+ breakpoints = breakpoints ?? contextBreakpoints;
+
+ let renderedStyles = useMemo(
+ () =>
+ allStyles
+ ? renderStyles(allStyles, pointsToZones(breakpoints as number[]))
+ : '',
+ [allStyles, breakpoints],
+ );
+
+ if (mods) {
+ Object.assign(otherProps, modAttrs(mods));
+ }
+
+ return (
+
+ );
+ });
+
+ _TastyComponent.displayName = `TastyComponent(${
+ defaultProps.qa || originalAs
+ })`;
+
+ return _TastyComponent;
+}
+
+export { tasty };
diff --git a/src/components/types.ts b/src/tasty/types.ts
similarity index 83%
rename from src/components/types.ts
rename to src/tasty/types.ts
index 105cd52d..061edad6 100644
--- a/src/components/types.ts
+++ b/src/tasty/types.ts
@@ -1,5 +1,5 @@
import { AllHTMLAttributes, CSSProperties } from 'react';
-import { Styles, StylesInterface } from '../styles/types';
+import { Styles } from './styles/types';
import {
BASE_STYLES,
BLOCK_STYLES,
@@ -10,26 +10,12 @@ import {
OUTER_STYLES,
POSITION_STYLES,
TEXT_STYLES,
-} from '../styles/list';
+} from './styles/list';
export interface GlobalStyledProps {
breakpoints?: number[];
}
-export type StyledProps = {
- /** The name of the element. It can be used to override styles in context. */
- name?: string;
- /** The tag name of the element. */
- tag?: string;
- /** Default styles of the element. */
- styles?: Styles;
- /** Default css of the element. */
- css?: string | ((props: Props) => string);
- props?: DefaultProps;
- /** The list of styles that can be provided by props */
- styleProps?: K;
-};
-
export interface BasePropsWithoutChildren
extends Pick, 'className' | 'role' | 'id'> {
/** QA ID for e2e testing. An alias for `data-qa` attribute. */
@@ -53,7 +39,7 @@ export interface BasePropsWithoutChildren
/** Whether the element is disabled (`disabled` attribute is set) */
isDisabled?: boolean;
/** Plain css for the element */
- css?: string | ((props: Props) => string);
+ css?: string;
/** The element name for using in style overriding */
styleName?: string;
/** The CSS style map */
diff --git a/src/utils/colors.ts b/src/tasty/utils/colors.ts
similarity index 100%
rename from src/utils/colors.ts
rename to src/tasty/utils/colors.ts
diff --git a/src/utils/dotize.ts b/src/tasty/utils/dotize.ts
similarity index 100%
rename from src/utils/dotize.ts
rename to src/tasty/utils/dotize.ts
diff --git a/src/utils/filterBaseProps.ts b/src/tasty/utils/filterBaseProps.ts
similarity index 100%
rename from src/utils/filterBaseProps.ts
rename to src/tasty/utils/filterBaseProps.ts
diff --git a/src/utils/index.ts b/src/tasty/utils/index.ts
similarity index 93%
rename from src/utils/index.ts
rename to src/tasty/utils/index.ts
index bb3a9afb..0e437311 100644
--- a/src/utils/index.ts
+++ b/src/tasty/utils/index.ts
@@ -31,7 +31,7 @@ export function getModCombinations(array: string[], allowEmpty?: boolean) {
return result.concat([array]);
}
- const f = function(prefix: string[] = [], array: string[]) {
+ const f = function (prefix: string[] = [], array: string[]) {
for (let i = 0; i < array.length; i++) {
result.push([...prefix, array[i]]);
f([...prefix, array[i]], array.slice(i + 1));
diff --git a/src/utils/mergeStyles.ts b/src/tasty/utils/mergeStyles.ts
similarity index 100%
rename from src/utils/mergeStyles.ts
rename to src/tasty/utils/mergeStyles.ts
diff --git a/src/utils/react/modAttrs.ts b/src/tasty/utils/modAttrs.ts
similarity index 100%
rename from src/utils/react/modAttrs.ts
rename to src/tasty/utils/modAttrs.ts
diff --git a/src/utils/renderStyles.ts b/src/tasty/utils/renderStyles.ts
similarity index 95%
rename from src/utils/renderStyles.ts
rename to src/tasty/utils/renderStyles.ts
index 77623808..bafc9e0e 100644
--- a/src/utils/renderStyles.ts
+++ b/src/tasty/utils/renderStyles.ts
@@ -155,15 +155,17 @@ export function renderStyles(
responsiveStyles[i] += rules || '';
});
} else {
- rawStyles
- += handler(styleMap as StyleValueStateMap, suffix) || '';
+ rawStyles +=
+ handler(styleMap as StyleValueStateMap, suffix) || '';
}
});
STYLE_CACHE[
cacheKey
] = `outline: none;\n&[hidden]{display: none !important;}${rawStyles}${
- responsive && responsive.length
+ responsive &&
+ responsive.length &&
+ responsiveStyles.filter((s) => s).length
? mediaWrapper(responsiveStyles, zones)
: ''
}${innerStyles}`;
diff --git a/src/utils/responsive.ts b/src/tasty/utils/responsive.ts
similarity index 100%
rename from src/utils/responsive.ts
rename to src/tasty/utils/responsive.ts
diff --git a/src/utils/string.ts b/src/tasty/utils/string.ts
similarity index 100%
rename from src/utils/string.ts
rename to src/tasty/utils/string.ts
diff --git a/src/utils/styles.test.ts b/src/tasty/utils/styles.test.ts
similarity index 100%
rename from src/utils/styles.test.ts
rename to src/tasty/utils/styles.test.ts
diff --git a/src/utils/styles.ts b/src/tasty/utils/styles.ts
similarity index 100%
rename from src/utils/styles.ts
rename to src/tasty/utils/styles.ts
diff --git a/src/tasty/utils/warnings.ts b/src/tasty/utils/warnings.ts
new file mode 100644
index 00000000..be7dd036
--- /dev/null
+++ b/src/tasty/utils/warnings.ts
@@ -0,0 +1,46 @@
+const PREFIX = 'Tasty';
+
+export function warn(...args) {
+ console.warn(`${PREFIX}:`, ...args);
+}
+
+export function deprecationWarning(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ condition: any,
+ {
+ property,
+ name,
+ betterAlternative,
+ reason,
+ }: {
+ property: string;
+ name: string;
+ betterAlternative: (() => string) | string;
+ reason?: (() => string) | string;
+ },
+) {
+ if (condition) return;
+
+ if (process.env.NODE_ENV === 'production') {
+ return warn(
+ `DEPRECATION ${name} "${property}" -> ${
+ typeof betterAlternative === 'function'
+ ? betterAlternative()
+ : betterAlternative
+ }`,
+ );
+ }
+
+ // we can make deprecations even better if we add the md syntax in the console.
+ // anyway, everything down below will be stripped in the production build
+ console.group(`⚠️ ${PREFIX}: Deprecation in ${name}`);
+ warn(
+ `"${property}" is deprecated, consider better alternative: ${
+ typeof betterAlternative === 'function'
+ ? betterAlternative()
+ : betterAlternative
+ }`,
+ );
+ reason && warn(`Reason: ${typeof reason === 'function' ? reason() : reason}`);
+ console.groupEnd();
+}
diff --git a/src/tokens.ts b/src/tokens.ts
index dbb46e94..c2573d8f 100644
--- a/src/tokens.ts
+++ b/src/tokens.ts
@@ -144,6 +144,11 @@ const TOKENS = {
't3m-line-height': '20px',
't3m-letter-spacing': '0.015em',
't3m-font-weight': '500',
+ // t3s
+ 't3s-font-size': '14px',
+ 't3s-line-height': '20px',
+ 't3s-letter-spacing': '0.015em',
+ 't3s-font-weight': '600',
// t4
't4-font-size': '12px',
't4-line-height': '18px',
diff --git a/src/utils/escape-string.ts b/src/utils/escape-string.ts
deleted file mode 100644
index 4f0589c3..00000000
--- a/src/utils/escape-string.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// https://github.com/sindresorhus/escape-string-regexp/blob/main/index.js
-export default function escapeStringRegexp(string) {
- if (typeof string !== 'string') {
- throw new TypeError('Expected a string');
- }
-
- // Escape characters with special meaning either inside or outside character sets.
- // Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
- return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d');
-}
diff --git a/src/utils/react/Slots.tsx b/src/utils/react/Slots.tsx
index 9e7533a3..6ec56b78 100644
--- a/src/utils/react/Slots.tsx
+++ b/src/utils/react/Slots.tsx
@@ -1,4 +1,4 @@
-import { mergeProps } from '../../utils/react/mergeProps';
+import { mergeProps } from './mergeProps';
import {
createContext,
Children,
diff --git a/src/utils/react/index.ts b/src/utils/react/index.ts
index ef064df5..5745b0c4 100644
--- a/src/utils/react/index.ts
+++ b/src/utils/react/index.ts
@@ -1,7 +1,7 @@
export { chain } from './chain';
export { isTextOnly } from './isTextOnly';
export { mergeProps } from './mergeProps';
-export { modAttrs } from './modAttrs';
+export { modAttrs } from '../../tasty';
export { useSlotProps, SlotProvider, ClearSlots } from './Slots';
export { useLayoutEffect } from './useLayoutEffect';
export { useCombinedRefs } from './useCombinedRefs';
diff --git a/src/utils/interactions.ts b/src/utils/react/interactions.ts
similarity index 100%
rename from src/utils/interactions.ts
rename to src/utils/react/interactions.ts
diff --git a/src/utils/react/mergeProps.tsx b/src/utils/react/mergeProps.tsx
index 219f9010..75cf7c60 100644
--- a/src/utils/react/mergeProps.tsx
+++ b/src/utils/react/mergeProps.tsx
@@ -1,6 +1,6 @@
import clsx from 'clsx';
import { chain, mergeIds } from '@react-aria/utils';
-import { Props } from '../../components/types';
+import { Props } from '../../tasty';
/**
* Merges multiple props objects together. Event handlers are chained,
@@ -16,34 +16,34 @@ export function mergeProps(...args: (Props | undefined)[]) {
for (let key in result) {
// Chain events
if (
- /^on[A-Z]/.test(key)
- && typeof result[key] === 'function'
- && props
- && typeof props[key] === 'function'
+ /^on[A-Z]/.test(key) &&
+ typeof result[key] === 'function' &&
+ props &&
+ typeof props[key] === 'function'
) {
result[key] = chain(result[key], props[key]);
// Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check
} else if (
- key === 'className'
- && typeof result.className === 'string'
- && props
- && typeof props.className === 'string'
+ key === 'className' &&
+ typeof result.className === 'string' &&
+ props &&
+ typeof props.className === 'string'
) {
result[key] = clsx(result.className, props.className);
} else if (
- key === 'styles'
- && typeof result.styles === 'object'
- && props
- && typeof props.styles === 'object'
+ key === 'styles' &&
+ typeof result.styles === 'object' &&
+ props &&
+ typeof props.styles === 'object'
) {
result[key] = { ...result.styles, ...props.styles };
} else if (key === 'id' && result.id && props?.id) {
result.id = mergeIds(result.id, props?.id);
// Override others
} else {
- result[key]
- = props && props[key] !== undefined ? props[key] : result[key];
+ result[key] =
+ props && props[key] !== undefined ? props[key] : result[key];
}
}
diff --git a/src/utils/react/nullableValue.ts b/src/utils/react/nullableValue.ts
index d7f0b797..4c14cd24 100644
--- a/src/utils/react/nullableValue.ts
+++ b/src/utils/react/nullableValue.ts
@@ -1,4 +1,4 @@
-import { Props } from '../../components/types';
+import { Props } from '../../tasty';
export function castNullableStringValue(props: T): T {
return castNullableField(props, ['value', 'defaultValue'], 'string', (v) =>