From bf7b99eaef5fea657e9394f639186c7dc78e23c7 Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Wed, 8 Jan 2025 16:49:25 +0100 Subject: [PATCH 01/14] fix Tabs stories --- src/components/Tabs/stories/Tab.stories.tsx | 2 +- src/components/Tabs/stories/TabPanel.stories.tsx | 2 +- src/components/Tabs/stories/TabTitle.stories.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Tabs/stories/Tab.stories.tsx b/src/components/Tabs/stories/Tab.stories.tsx index d7a567748..44ec92bdc 100644 --- a/src/components/Tabs/stories/Tab.stories.tsx +++ b/src/components/Tabs/stories/Tab.stories.tsx @@ -4,7 +4,7 @@ import { Meta, StoryFn } from "@storybook/react"; import { Tab as TabDummyForStorybook, Tabs } from "./../../../../"; export default { - title: "Components/Tabs", + title: "Components/Tabs/Tab", component: TabDummyForStorybook, argTypes: { backgroundColor: { diff --git a/src/components/Tabs/stories/TabPanel.stories.tsx b/src/components/Tabs/stories/TabPanel.stories.tsx index 0ba72f783..270a513ed 100644 --- a/src/components/Tabs/stories/TabPanel.stories.tsx +++ b/src/components/Tabs/stories/TabPanel.stories.tsx @@ -5,7 +5,7 @@ import { Meta, StoryFn } from "@storybook/react"; import { TabPanel } from "./../../../"; export default { - title: "Components/Tabs", + title: "Components/Tabs/TabPanel", component: TabPanel, argTypes: {}, } as Meta; diff --git a/src/components/Tabs/stories/TabTitle.stories.tsx b/src/components/Tabs/stories/TabTitle.stories.tsx index 8bb53ba50..c4124754d 100644 --- a/src/components/Tabs/stories/TabTitle.stories.tsx +++ b/src/components/Tabs/stories/TabTitle.stories.tsx @@ -4,7 +4,7 @@ import { Meta, StoryFn } from "@storybook/react"; import { Tabs, TabTitle as TabTitleOrg } from "./../../../"; export default { - title: "Components/Tabs", + title: "Components/Tabs/TabTitle", component: TabTitleOrg, argTypes: {}, } as Meta; From 0210d34c6e316ea09ac1dac6dd6dc66adf195ccc Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 9 Jan 2025 15:45:59 +0100 Subject: [PATCH 02/14] include color palette as custom properties --- src/components/Application/_colors.scss | 15 ++++ src/components/Application/application.scss | 1 + src/configuration/_palettes.scss | 91 +++++++++++++++++++++ src/configuration/_variables.scss | 2 + 4 files changed, 109 insertions(+) create mode 100644 src/components/Application/_colors.scss create mode 100644 src/configuration/_palettes.scss diff --git a/src/components/Application/_colors.scss b/src/components/Application/_colors.scss new file mode 100644 index 000000000..6c79ea7fe --- /dev/null +++ b/src/components/Application/_colors.scss @@ -0,0 +1,15 @@ +@use "sass:map"; +@use "sass:list"; + +:root { + @each $palette-group-name, $palette-group-tints in $eccgui-color-palette-light { + @each $palette-tint-name, $palette-tint-colors in $palette-group-tints { + @for $i from 1 through list.length($palette-tint-colors) { + #{eccgui-color-name($palette-group-name, $palette-tint-name, $i * 100)}: #{list.nth( + $palette-tint-colors, + $i + )}; + } + } + } +} diff --git a/src/components/Application/application.scss b/src/components/Application/application.scss index 78d1b5d45..ea0de1677 100644 --- a/src/components/Application/application.scss +++ b/src/components/Application/application.scss @@ -1,4 +1,5 @@ // @import 'config'; +@import "colors"; @import "header"; @import "toolbar"; diff --git a/src/configuration/_palettes.scss b/src/configuration/_palettes.scss new file mode 100644 index 000000000..f93c8c8de --- /dev/null +++ b/src/configuration/_palettes.scss @@ -0,0 +1,91 @@ +@use "sass:list"; +@use "sass:color"; +@use "sass:math"; + +/** + * Always provide a list of 9 color tints. + * If the list do not provide 9 colors then create them based on the first and last color in the list. + */ +@function eccgui-create-color-tints($colorset) { + $colorset-steps: 9; // number of tints + $count-colors: list.length($colorset); + + @if $count-colors == $colorset-steps { + @return $colorset; + } + + @if $count-colors < 1 { + @error "Need at least 1 color to create color tints."; + } + + @debug "Got only #{$count-colors} tints: #{$colorset}"; + + $color-tint-start: rgb( + color.red(list.nth($colorset, 1)), + color.green(list.nth($colorset, 1)), + color.blue(list.nth($colorset, 1)) + ); + $color-tint-end: rgb( + color.red(list.nth($colorset, -1)), + color.green(list.nth($colorset, -1)), + color.blue(list.nth($colorset, -1)) + ); + $colorset-fallback: $color-tint-start; + + @for $i from 2 to $colorset-steps { + $tint-step: color.mix($color-tint-end, $color-tint-start, 100% * math.div($i, $colorset-steps)); + $colorset-fallback: list.append( + $colorset-fallback, + rgb(color.red($tint-step), color.green($tint-step), color.blue($tint-step)) + ); + } + + $colorset-fallback: list.append($colorset-fallback, $color-tint-end); + + @debug "Create fallback with 9 tints: #{$colorset-fallback}"; + @return $colorset-fallback; +} + +/** + * Create name for custom property + */ +@function eccgui-color-name($group_or_name, $tint: null, $weight: null) { + @if $group_or_name && $tint && $weight { + @return "--#{$eccgui}-color-palette-#{$group_or_name}-#{$tint}-#{$weight}"; + } @else { + @return "--#{$eccgui}-color-#{$group_or_name}"; + } +} + +/** + * Base definition for colors. + * Can be overwritten if defined before this file is included. + * You need to define all or nothing, we currently support overwriting it only partly. + */ + +$eccgui-color-palette-light: ( + "identity": ( + "brand": eccgui-create-color-tints(#fae1cc rgb(254 143 1)), + "accent": eccgui-create-color-tints(#e5f4fb rgb(10 103 163)), + ), + "semantic": ( + "info": eccgui-create-color-tints(rgb(227 242 253) rgb(21 101 192)), + "success": eccgui-create-color-tints(rgb(232 245 233) #1b5e20), + "warning": eccgui-create-color-tints(rgb(255 243 224) #e65100), + "danger": eccgui-create-color-tints(rgb(255 235 238) #b71c1c), + ), + "layout": ( + "indigo": eccgui-create-color-tints(#ebcef2 #46247a), + "pink": eccgui-create-color-tints(#fadaec #b23a78), + "rajah": eccgui-create-color-tints(#fef0e1 #88592c), + "yellow": eccgui-create-color-tints(#fce7e7 #d4af37), + "lime": eccgui-create-color-tints(#cde0d6 #789f3f), + "teal": eccgui-create-color-tints(#9addd6 #1f7a68), + "cyan": eccgui-create-color-tints(#ccf9fe #00a3c4), + "brown": eccgui-create-color-tints(#da780d #632114), + "blue": eccgui-create-color-tints(#e5f4fb #0074b1), + "grey": eccgui-create-color-tints(#dcdde4 #101016), + "red": eccgui-create-color-tints(#f9ecf4 #c41e3a), + "green": eccgui-create-color-tints(#e8ede9 #008c30), + ), +) !default; diff --git a/src/configuration/_variables.scss b/src/configuration/_variables.scss index 6f980db67..43750488f 100644 --- a/src/configuration/_variables.scss +++ b/src/configuration/_variables.scss @@ -15,6 +15,8 @@ $eccgui: "eccgui" !default; +@import "palettes"; + // -- Configuration stack of colors -------------------------------------------- $eccgui-color-primary: rgb(254 143 1) !default; From 3799bac8194f35cd4ccea21a5a03df015282b50e Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 9 Jan 2025 15:53:36 +0100 Subject: [PATCH 03/14] allow filtering when fetching css custom properties --- src/common/utils/CssCustomProperties.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/common/utils/CssCustomProperties.ts b/src/common/utils/CssCustomProperties.ts index ec9495c1d..8522a83c0 100644 --- a/src/common/utils/CssCustomProperties.ts +++ b/src/common/utils/CssCustomProperties.ts @@ -13,6 +13,7 @@ interface getLocalCssStyleRulePropertiesProps extends getLocalCssStyleRulesProps propertyType?: "all" | "normal" | "custom"; } interface getCustomPropertiesProps extends getLocalCssStyleRulesProps { + filterName?: (name?: string) => boolean; removeDashPrefix?: boolean; returnObject?: boolean; } @@ -87,7 +88,7 @@ export default class CssCustomProperties { const { propertyType = "all", ...otherFilters } = filter; return CssCustomProperties.listLocalCssStyleRules(otherFilters) .map((cssrule) => { - return [...(cssrule as any).style].map((propertyname) => { + return [...(cssrule as AllowedCSSRule).style].map((propertyname) => { return [propertyname.trim(), (cssrule as CSSStyleRule).style.getPropertyValue(propertyname).trim()]; }); }) @@ -104,17 +105,21 @@ export default class CssCustomProperties { }; static listCustomProperties = (props: getCustomPropertiesProps = {}) => { - const { removeDashPrefix = true, returnObject = true, ...filterProps } = props; + const { removeDashPrefix = true, returnObject = true, filterName = () => true, ...filterProps } = props; const customProperties = CssCustomProperties.listLocalCssStyleRuleProperties({ ...filterProps, propertyType: "custom", - }).map((declaration) => { - if (removeDashPrefix) { - return [declaration[0].substr(2), declaration[1]]; - } - return declaration; - }); + }) + .filter((declaration) => { + return filterName(declaration[0]); + }) + .map((declaration) => { + if (removeDashPrefix) { + return [declaration[0].substr(2), declaration[1]]; + } + return declaration; + }); return returnObject ? Object.fromEntries(customProperties) : customProperties; }; From f702e2d7e5db13d78b74772bf5e64b2bd35f7e6a Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 9 Jan 2025 16:09:02 +0100 Subject: [PATCH 04/14] use story to include protype for color palette tool --- src/cmem/markdown/Markdown.stories.tsx | 1 - src/common/utils/CssCustomProperties.ts | 2 +- .../stories/Application.stories.tsx | 4 +- .../stories/ColorPalettes.stories.tsx | 220 ++++++++++++++++++ 4 files changed, 223 insertions(+), 4 deletions(-) create mode 100644 src/components/Application/stories/ColorPalettes.stories.tsx diff --git a/src/cmem/markdown/Markdown.stories.tsx b/src/cmem/markdown/Markdown.stories.tsx index d067e7912..2754e20cf 100644 --- a/src/cmem/markdown/Markdown.stories.tsx +++ b/src/cmem/markdown/Markdown.stories.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { Blockquote } from "@blueprintjs/core"; import { Meta, StoryFn } from "@storybook/react"; import { Markdown } from "./../../../index"; diff --git a/src/common/utils/CssCustomProperties.ts b/src/common/utils/CssCustomProperties.ts index 8522a83c0..a7166fcc9 100644 --- a/src/common/utils/CssCustomProperties.ts +++ b/src/common/utils/CssCustomProperties.ts @@ -13,7 +13,7 @@ interface getLocalCssStyleRulePropertiesProps extends getLocalCssStyleRulesProps propertyType?: "all" | "normal" | "custom"; } interface getCustomPropertiesProps extends getLocalCssStyleRulesProps { - filterName?: (name?: string) => boolean; + filterName?: (name: string) => boolean; removeDashPrefix?: boolean; returnObject?: boolean; } diff --git a/src/components/Application/stories/Application.stories.tsx b/src/components/Application/stories/Application.stories.tsx index e2feb5907..7e0aa6cf4 100644 --- a/src/components/Application/stories/Application.stories.tsx +++ b/src/components/Application/stories/Application.stories.tsx @@ -29,11 +29,11 @@ interface ApplicationBasicExampleProps { } function ApplicationBasicExample(args: ApplicationBasicExampleProps) { - return <>; + return args ? <> : <>; } export default { - title: "Components/Application", + title: "Components/Application/Elements", component: ApplicationBasicExample, subcomponents: { ApplicationContainer, diff --git a/src/components/Application/stories/ColorPalettes.stories.tsx b/src/components/Application/stories/ColorPalettes.stories.tsx new file mode 100644 index 000000000..432f24ca4 --- /dev/null +++ b/src/components/Application/stories/ColorPalettes.stories.tsx @@ -0,0 +1,220 @@ +import React from "react"; +import { Meta, StoryFn } from "@storybook/react"; +import Color from "color"; + +import CssCustomProperties from "./../../../common/utils/CssCustomProperties"; +import { + Button, + CLASSPREFIX as eccgui, + FieldItem, + FieldItemRow, + Section, + SectionHeader, + Spacing, + Tabs, + TextArea, + TextField, + TitleSubsection, +} from "./../../../index"; + +interface ColorPaletteConfiguratorProps { + customColorProperties?: string; +} + +const ColorPaletteConfigurator = ({ customColorProperties }: ColorPaletteConfiguratorProps) => { + const palettePrefix = `--${eccgui}-color-palette-`; + + const createPaletteData = (csscustomprops: string | undefined) => { + const colors = ( + csscustomprops + ? csscustomprops.split(";").map((rule: string) => { + return rule.split(":").map((rulepart: string) => { + return rulepart.trim(); + }); + }) + : new CssCustomProperties({ + selectorText: `:root`, + filterName: (name: string) => { + return name.includes(palettePrefix); + }, + removeDashPrefix: false, + returnObject: false, + }).customProperties() + ) + .filter((colorconfig: object) => { + if (!Array.isArray(colorconfig)) { + return false; + } + if (colorconfig.length !== 2) { + return false; + } + return true; + }) + .map((colorconfig: object) => { + return [colorconfig[0].replace(palettePrefix, ""), Color(colorconfig[1]).rgb()]; + }); + + const data = new Object(); + + for (const [key, value] of colors) { + const hierarchy = key.split("-"); + if (!data[hierarchy[0]]) { + data[hierarchy[0]] = new Object(); + } + if (!data[hierarchy[0]][hierarchy[1]]) { + data[hierarchy[0]][hierarchy[1]] = new Object(); + } + if (!data[hierarchy[0]][hierarchy[1]][hierarchy[2]]) { + data[hierarchy[0]][hierarchy[1]][hierarchy[2]] = value; + } + } + + return data; + }; + + const createCustomPropsSerialization = (data: object) => { + let serialization = ""; + for (const [group, tints] of Object.entries(data)) { + for (const [tint, weights] of Object.entries(tints as object)) { + for (const [weight, value] of Object.entries(weights)) { + serialization = + serialization + + `--${eccgui}-color-palette-${group}-${tint}-${weight}: ${(value as Color).hex()};\n`; + } + } + } + return serialization.trim(); + }; + + const createSassSerialization = (data: object) => { + const createTintData = (tint: string, weights: object) => { + return `\t\t"${tint}": eccgui-create-color-tints(${Object.values(weights) + .map((color) => color.hex()) + .join(" ")}),\n`; + }; + + const createGroupData = (group: string, tints: object) => { + let groupData = `\t"${group}": (\n`; + for (const [tint, weights] of Object.entries(tints)) { + groupData = groupData + createTintData(tint, weights); + } + return groupData + `\t),\n`; + }; + + let sassData = `$eccgui-color-palette-light: (\n`; + + for (const [group, tints] of Object.entries(data)) { + sassData = sassData + createGroupData(group, tints); + } + + return sassData + `) !default;`; + }; + + const [paletteData, setPaletteData] = React.useState(undefined); + const [userPaletteProps, setUserPaletteProps] = React.useState(undefined); + + React.useEffect(() => { + const paletteData = createPaletteData(customColorProperties); + //console.log("paletteData", paletteData); + setPaletteData(paletteData); + }, [customColorProperties]); + + const editorPanel = ( +
+ {paletteData && + Object.keys(paletteData).map((group, id) => { + return ( +
+ + {group} + + + {Object.keys(paletteData[group]).map((tint, id) => { + return ( + + {Object.keys(paletteData[group][tint]).map((weight, id) => { + return ( + + { + paletteData[group][tint][weight] = Color(newcolor).rgb(); + // console.log("new palette", paletteData); + setPaletteData({ ...paletteData }); + }} + /> + + ); + })} + + ); + })} + +
+ ); + })} +
+ ); + + return ( + {}} + tabs={[ + { + id: "editor", + panel: editorPanel, + title: "Editor", + }, + { + id: "css", + panel: ( +
+