diff --git a/devtool/package.json b/devtool/package.json index 81eb1fed..881c1471 100644 --- a/devtool/package.json +++ b/devtool/package.json @@ -83,7 +83,7 @@ "react-dom": "^17.0.2" }, "scripts": { - "start": "INLINE_RUNTIME_CHUNK=false node scripts/start.js", + "start": "node scripts/start.js", "build": "node scripts/build.js", "build:theme": "node_modules/@morfeo/cli/bin/run build --config=./.morfeorc.ts", "start:firefox": "node scripts/start.js firefox", diff --git a/devtool/src/_shared/components/Card/index.tsx b/devtool/src/_shared/components/Card/index.tsx index 73c38327..2755c085 100644 --- a/devtool/src/_shared/components/Card/index.tsx +++ b/devtool/src/_shared/components/Card/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useStyle, Style } from '@morfeo/react'; +import { Style, useStyle } from '@morfeo/react'; import styles from './style.module.css'; import clsx from 'clsx'; import { CopyButton } from '../CopyButton'; diff --git a/devtool/src/_shared/components/CodeSnippets/snippets/index.ts b/devtool/src/_shared/components/CodeSnippets/snippets/index.ts index 952ca8e3..befcb6c1 100644 --- a/devtool/src/_shared/components/CodeSnippets/snippets/index.ts +++ b/devtool/src/_shared/components/CodeSnippets/snippets/index.ts @@ -43,6 +43,13 @@ const map: Record = { property: 'p', cssProperty: 'padding', }), + gradients: (value: string) => + general({ + slice: 'gradients', + value, + property: 'gradient', + cssProperty: 'background', + }), opacities: (value: string) => general({ slice: 'opacities', value, property: 'opacity' }), fontSizes: (value: string) => diff --git a/devtool/src/_shared/components/Grid/style.module.css b/devtool/src/_shared/components/Grid/style.module.css index 21949bf2..7f1ecda4 100644 --- a/devtool/src/_shared/components/Grid/style.module.css +++ b/devtool/src/_shared/components/Grid/style.module.css @@ -1,6 +1,6 @@ .section { display: flex; flex-wrap: wrap; - justify-content: space-between; + justify-content: flex-start; position: relative; } \ No newline at end of file diff --git a/devtool/src/_shared/components/Slices/Colors/Detail/index.tsx b/devtool/src/_shared/components/Slices/Colors/Detail/index.tsx index 2ad0dbf2..c267aa57 100644 --- a/devtool/src/_shared/components/Slices/Colors/Detail/index.tsx +++ b/devtool/src/_shared/components/Slices/Colors/Detail/index.tsx @@ -1,5 +1,5 @@ -import React, { useMemo } from 'react'; -import { Color, useTheme } from '@morfeo/react'; +import React from 'react'; +import { Color, useStyle } from '@morfeo/react'; import { Card } from '../../../Card'; import { useRouter } from '../../../../hooks'; import styles from './style.module.css'; @@ -41,19 +41,15 @@ export const Detail: React.FC = () => { const { route } = useRouter(); const { state } = route; - const theme = useTheme(); - const colorSlice = useMemo(() => (theme || {})['colors'] || {}, [theme]); - - const bgColor = useMemo( - () => - (state?.detailKey && (colorSlice || {})[state.detailKey as Color]) || - 'white', - [colorSlice, state?.detailKey], - ); + const cardStyle = useStyle({ bg: state?.detailKey as Color }); + const bgColor = cardStyle['background']?.toString() || '#fff'; return (
- +

RGBA: {bgColor.includes('#') ? hex2rgba(bgColor) : bgColor} diff --git a/devtool/src/_shared/components/Slices/Components/MorfeoComponent.ts b/devtool/src/_shared/components/Slices/Components/MorfeoComponent.ts index 1fe83311..41ce54a1 100644 --- a/devtool/src/_shared/components/Slices/Components/MorfeoComponent.ts +++ b/devtool/src/_shared/components/Slices/Components/MorfeoComponent.ts @@ -15,10 +15,8 @@ export const MorfeoComponent: React.FC = ({ children, ...props }) => { - const { tag = 'div', props: componentProps = {} } = component( - name, - variant, - ).get(); + const { tag = 'div', props: componentProps = {} } = + component(name, variant).get() || {}; const { classes } = getStyles({ [name]: { componentName: name as Component, diff --git a/devtool/src/_shared/components/Slices/Gradients/Detail/index.tsx b/devtool/src/_shared/components/Slices/Gradients/Detail/index.tsx new file mode 100644 index 00000000..e584be8f --- /dev/null +++ b/devtool/src/_shared/components/Slices/Gradients/Detail/index.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { + Gradient, + useStyle, + useThemeSlice, + useThemeValue, +} from '@morfeo/react'; +import { getContrast } from 'polished'; +import { Card } from '../../../Card'; +import { useRouter } from '../../../../hooks'; +import styles from './style.module.css'; +import { RouteState } from '../../../../contexts'; + +export const Detail: React.FC = () => { + const { route } = useRouter(); + const { state = {} as RouteState } = route; + const { detailKey } = state; + const gradientStyle = useStyle({ + gradient: detailKey as Gradient, + }); + const colorsSlice = useThemeSlice('colors'); + const { colors } = useThemeValue('gradients', detailKey as Gradient); + const averageRatio = colors.reduce((acc, color) => { + const mappedColor = colorsSlice?.[color] || '#fff'; + const contrastRatio = getContrast(mappedColor, '#fff'); + + return acc + contrastRatio / colors.length; + }, 0); + + return ( +
+ +

+ {gradientStyle['background']} +

+
+
+ ); +}; diff --git a/devtool/src/_shared/components/Slices/Gradients/Detail/style.module.css b/devtool/src/_shared/components/Slices/Gradients/Detail/style.module.css new file mode 100644 index 00000000..26e15f15 --- /dev/null +++ b/devtool/src/_shared/components/Slices/Gradients/Detail/style.module.css @@ -0,0 +1,4 @@ +.container { + padding-left: var(--spacings-xs); + padding-right: var(--spacings-xs); +} \ No newline at end of file diff --git a/devtool/src/_shared/components/Slices/Gradients/index.tsx b/devtool/src/_shared/components/Slices/Gradients/index.tsx new file mode 100644 index 00000000..854fa126 --- /dev/null +++ b/devtool/src/_shared/components/Slices/Gradients/index.tsx @@ -0,0 +1,65 @@ +import React, { useMemo, useCallback } from 'react'; +import { Gradient, useThemeSlice } from '@morfeo/react'; +import clsx from 'clsx'; +import { Card } from '../../Card'; +import { useRouter } from '../../../hooks/useRouter'; +import { RouteName } from '../../../contexts'; +import { SliceName } from '../../../contexts/Routing/types'; +import { Grid, Item } from '../../Grid'; +import styles from './style.module.css'; +export { Detail } from './Detail'; + +type Props = { + gradient: Gradient; +}; + +const GradientCard: React.FC = ({ gradient }) => { + const { navigate } = useRouter(); + + const onClick = useCallback(() => { + navigate(RouteName.SLICE, { + slice: SliceName.GRADIENTS, + detailKey: gradient, + }); + }, [gradient, navigate]); + + return ( +
+ +

+ {gradient} +

+
+ ); +}; + +export const Gradients: React.FC = () => { + const gradients = useThemeSlice('gradients'); + + const gradientKeys = useMemo( + () => + (Object.keys(gradients) || []).sort((first, second) => + first.localeCompare(second), + ) as Gradient[], + [gradients], + ); + + const section = useMemo(() => { + return gradientKeys.map(key => { + return ( + + + + ); + }); + }, [gradientKeys]); + + return {section}; +}; diff --git a/devtool/src/_shared/components/Slices/Gradients/style.module.css b/devtool/src/_shared/components/Slices/Gradients/style.module.css new file mode 100644 index 00000000..daade618 --- /dev/null +++ b/devtool/src/_shared/components/Slices/Gradients/style.module.css @@ -0,0 +1,18 @@ + +.gradientContainer { + width: 100%; +} + +.gradientName { + max-width: 10rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.gradientSection { + display: flex; + flex-wrap: wrap; + justify-content: stretch; + box-sizing: border-box; +} \ No newline at end of file diff --git a/devtool/src/_shared/components/Slices/index.tsx b/devtool/src/_shared/components/Slices/index.tsx index b8de6734..9936bb3f 100644 --- a/devtool/src/_shared/components/Slices/index.tsx +++ b/devtool/src/_shared/components/Slices/index.tsx @@ -1,106 +1,113 @@ import { SliceName } from '../../contexts'; import { Colors, Detail as ColorDetail } from './Colors'; +import { Gradients, Detail as GradientDetail } from './Gradients'; import { Components, Detail as ComponentDetail } from './Components'; -export const slices = { +export type SliceConfig = { + render: React.FC; + displayName: string; + renderDetail: React.FC; +}; + +export const slices: Record = { [SliceName.COLORS]: { - render: , - renderDetail: , + render: () => , + renderDetail: () => , displayName: 'colors', }, [SliceName.COMPONENTS]: { - render: , - renderDetail: , + render: () => , + renderDetail: () => , displayName: 'components', }, [SliceName.RADII]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'radii', }, [SliceName.SIZES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'sizes', }, [SliceName.FONTS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'fonts', }, [SliceName.SHADOWS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'shadows', }, [SliceName.BORDERS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'borders', }, [SliceName.SPACINGS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'spacings', }, [SliceName.Z_INDICES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'zIndices', }, [SliceName.FONT_SIZES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'fontSizes', }, [SliceName.GRADIENTS]: { - render: <>, - renderDetail: <>, + render: () => , + renderDetail: () => , displayName: 'gradients', }, [SliceName.OPACITIES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'opacities', }, [SliceName.FONT_WEIGHTS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'fontWeights', }, [SliceName.LINE_HEIGHTS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'lineHeights', }, [SliceName.BREAKPOINTS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'breakpoints', }, [SliceName.TRANSITIONS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'transitions', }, [SliceName.BORDER_WIDTHS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'borderWidths', }, [SliceName.MEDIA_QUERIES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'mediaQueries', }, [SliceName.BORDER_STYLES]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'borderStyles', }, [SliceName.LETTER_SPACINGS]: { - render: <>, - renderDetail: <>, + render: () => <>, + renderDetail: () => <>, displayName: 'letterSpacings', }, }; diff --git a/devtool/src/_shared/constants/index.ts b/devtool/src/_shared/constants/index.ts index 13c7d0be..709f5dac 100644 --- a/devtool/src/_shared/constants/index.ts +++ b/devtool/src/_shared/constants/index.ts @@ -12,22 +12,24 @@ export const ASSETS_PATHS = { }; export const THEME_KEYS: ThemeKey[] = [ - 'sizes', 'radii', + 'sizes', + 'fonts', 'colors', - 'borders', 'shadows', - 'zIndices', + 'borders', 'spacings', - 'opacities', + 'zIndices', 'fontSizes', + 'gradients', + 'opacities', 'components', - 'transitions', - 'breakpoints', - 'lineHeights', 'fontWeights', + 'lineHeights', + 'breakpoints', + 'transitions', 'borderWidths', - 'borderStyles', 'mediaQueries', + 'borderStyles', 'letterSpacings', ]; diff --git a/devtool/src/_shared/template/Header/index.tsx b/devtool/src/_shared/template/Header/index.tsx index e519a69e..5dd52ad2 100644 --- a/devtool/src/_shared/template/Header/index.tsx +++ b/devtool/src/_shared/template/Header/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useEffect } from 'react'; +import React, { useMemo, useState } from 'react'; import clsx from 'clsx'; import { Color, morfeo, ThemeName, useTheme } from '@morfeo/react'; import { DropDown, Icon } from '../../components'; @@ -48,12 +48,6 @@ export const Header: React.FC = () => { return undefined; }, [currentTheme, theme, themes]); - useEffect(() => { - if (theme) { - setCurrentTheme(morfeo.getCurrent()); - } - }, [theme]); - return (
diff --git a/devtool/src/_shared/template/SideBar/Menus.tsx b/devtool/src/_shared/template/SideBar/Menus.tsx index bcec84c3..0320e09d 100644 --- a/devtool/src/_shared/template/SideBar/Menus.tsx +++ b/devtool/src/_shared/template/SideBar/Menus.tsx @@ -1,11 +1,11 @@ import React, { useMemo } from 'react'; import { Color, useThemeSlice } from '@morfeo/react'; import { Icon, Link } from '../../components'; -import { useThemeSlices } from '../../hooks'; import { RouteName } from '../../contexts'; import { SliceName } from '../../contexts/Routing/types'; import { IconName } from '../../components/Icon/icons'; import styles from './style.module.css'; +import { THEME_KEYS } from '../../constants'; type Props = { onNavigate?: () => void; @@ -70,7 +70,7 @@ export const Menu: React.FC = ({ items, onNavigate }) => ( ); export const Slices: React.FC = ({ onNavigate }) => { - const slices = useThemeSlices(); + const slices = THEME_KEYS; const items: MenuItemType[] = useMemo( () => slices.map(slice => ({ diff --git a/devtool/src/devtool/index.tsx b/devtool/src/devtool/index.tsx index 5c21c317..3e6362fe 100644 --- a/devtool/src/devtool/index.tsx +++ b/devtool/src/devtool/index.tsx @@ -1,6 +1,6 @@ import ReactDOM from 'react-dom'; import browser from 'webextension-polyfill'; -import { resetCss } from '@morfeo/react'; +import { resetCss, MorfeoProvider } from '@morfeo/react'; import { getThemeFromAppAndInitMorfeo } from '../_shared/utils'; import { MORFEO_DEVTOOL_PANEL_NAME, ASSETS_PATHS } from '../_shared/constants'; import Devtool from './Devtool'; @@ -15,4 +15,9 @@ browser.devtools.panels.create( ASSETS_PATHS.devtool.view, ); -ReactDOM.render(, document.getElementById('devtool')); +ReactDOM.render( + + + , + document.getElementById('devtool'), +); diff --git a/devtool/src/devtool/pages/ComponentPage/index.tsx b/devtool/src/devtool/pages/ComponentPage/index.tsx index 91927d42..e7588d23 100644 --- a/devtool/src/devtool/pages/ComponentPage/index.tsx +++ b/devtool/src/devtool/pages/ComponentPage/index.tsx @@ -2,7 +2,8 @@ import React, { useMemo } from 'react'; import { Component } from '@morfeo/react'; import { Page } from '../../../_shared/template/Page'; import { useRouter } from '../../../_shared/hooks/useRouter'; -import { CodeSnippets, Grid, Item, slices } from '../../../_shared/components'; +import { CodeSnippets, Grid, Item } from '../../../_shared/components'; +import { Detail } from '../../../_shared/components/Slices/Components/Detail'; import { SliceName } from '../../../_shared/contexts/Routing/types'; import { Variants } from '../../../_shared/components/Slices/Components/Variants'; import { Preview } from '../../../_shared/components/Slices/Components/Preview'; @@ -15,23 +16,10 @@ export const ComponentPage: React.FC = () => { const { state } = route; const { slice, detailKey, componentVariant } = state || {}; - const breadCrumbSlice = slices[slice as SliceName]?.displayName || 'slice'; const breadCrumbDetail = detailKey || ''; const breadCrumb = componentVariant - ? [breadCrumbSlice, breadCrumbDetail, componentVariant] - : [breadCrumbSlice, breadCrumbDetail]; - - const renderContent = useMemo(() => { - if (detailKey && slice) { - return slices[slice].renderDetail || <>; - } - - if (slice) { - return slices[slice].render; - } - - return <>; - }, [detailKey, slice]); + ? [breadCrumbDetail, componentVariant] + : [breadCrumbDetail]; const title = useMemo(() => { if (componentVariant) { @@ -42,16 +30,12 @@ export const ComponentPage: React.FC = () => { return detailKey; } - if (slice) { - return slices[slice]?.displayName; - } - return ''; - }, [detailKey, slice, componentVariant]); + }, [detailKey, componentVariant]); return ( - - {renderContent} + + {state && state.detailKey && (
{ const { route } = useRouter(); const { state } = route; - const breadCrumbSlice = - (state && slices[state.slice as SliceName]?.displayName) || 'slice'; + const sliceConfig = useMemo( + () => (state ? slices[state.slice as SliceName] : ({} as SliceConfig)), + [state], + ); + + const breadCrumbSlice = sliceConfig.displayName || 'slice'; const breadCrumbDetail = state?.detailKey; const breadCrumb = breadCrumbDetail ? [breadCrumbSlice, breadCrumbDetail] : [breadCrumbSlice]; - const renderContent = useMemo(() => { + const Content = useMemo(() => { if (state?.detailKey) { - return slices[state.slice].renderDetail || <>; + return sliceConfig.renderDetail; } if (state?.slice) { - return slices[state.slice].render; + return sliceConfig.render; } - return <>; - }, [state?.detailKey, state?.slice]); + return () => <>; + }, [ + sliceConfig.render, + sliceConfig.renderDetail, + state?.detailKey, + state?.slice, + ]); const title = useMemo(() => { if (state?.detailKey) { @@ -41,7 +50,7 @@ export const Slice: React.FC = () => { return ( - {renderContent} + {state && state.detailKey && (