diff --git a/client/packages/lowcoder/src/comps/comps/buttonComp/buttonCompConstants.tsx b/client/packages/lowcoder/src/comps/comps/buttonComp/buttonCompConstants.tsx index 1fe2f3270..377d662a9 100644 --- a/client/packages/lowcoder/src/comps/comps/buttonComp/buttonCompConstants.tsx +++ b/client/packages/lowcoder/src/comps/comps/buttonComp/buttonCompConstants.tsx @@ -8,8 +8,8 @@ import { refMethods } from "comps/generators/withMethodExposing"; import { blurMethod, clickMethod, focusWithOptions } from "comps/utils/methodUtils"; export function getButtonStyle(buttonStyle: ButtonStyleType) { - const hoverColor = genHoverColor(buttonStyle.background); - const activeColor = genActiveColor(buttonStyle.background); + const hoverColor = buttonStyle.background && genHoverColor(buttonStyle.background); + const activeColor = buttonStyle.background && genActiveColor(buttonStyle.background); return css` &&& { border-radius: ${buttonStyle.radius}; diff --git a/client/packages/lowcoder/src/comps/comps/buttonComp/linkComp.tsx b/client/packages/lowcoder/src/comps/comps/buttonComp/linkComp.tsx index 95ec1a5df..863a22081 100644 --- a/client/packages/lowcoder/src/comps/comps/buttonComp/linkComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/buttonComp/linkComp.tsx @@ -36,7 +36,7 @@ const Link = styled(Button)<{ padding: ${props.$style.padding}; font-size: ${props.$style.textSize}; font-style:${props.$style.fontStyle}; - font-family:${props.$style.fontFamily}; + ${props.$style.fontFamily && `font-family: ${props.$style.fontFamily}`}; font-weight:${props.$style.textWeight}; border: ${props.$style.borderWidth} ${props.$style.borderStyle} ${props.$style.border}; border-radius:${props.$style.radius ? props.$style.radius:'0px'}; diff --git a/client/packages/lowcoder/src/comps/comps/dividerComp.tsx b/client/packages/lowcoder/src/comps/comps/dividerComp.tsx index a97c76bed..7c73fb04c 100644 --- a/client/packages/lowcoder/src/comps/comps/dividerComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/dividerComp.tsx @@ -17,7 +17,7 @@ import { AutoHeightControl } from "comps/controls/autoHeightControl"; import { useContext } from "react"; import { EditorContext } from "comps/editorState"; -import { useMergeCompStyles } from "@lowcoder-ee/index.sdk"; +import { useMergeCompStyles } from "@lowcoder-ee/util/hooks"; type IProps = DividerProps & { $style: DividerStyleType; diff --git a/client/packages/lowcoder/src/comps/comps/navComp/navComp.tsx b/client/packages/lowcoder/src/comps/comps/navComp/navComp.tsx index b09e5928b..6b686b009 100644 --- a/client/packages/lowcoder/src/comps/comps/navComp/navComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/navComp/navComp.tsx @@ -22,6 +22,7 @@ import { trans } from "i18n"; import { useContext } from "react"; import { EditorContext } from "comps/editorState"; +import { useMergeCompStyles } from "@lowcoder-ee/util/hooks"; type IProps = { $justify: boolean; @@ -135,8 +136,8 @@ const childrenMap = { logoUrl: StringControl, logoEvent: withDefault(eventHandlerControl(logoEventHandlers), [{ name: "click" }]), horizontalAlignment: alignWithJustifyControl(), - style: migrateOldData(styleControl(NavigationStyle), fixOldStyleData), - animationStyle: styleControl(AnimationStyle), + style: migrateOldData(styleControl(NavigationStyle, 'style'), fixOldStyleData), + animationStyle: styleControl(AnimationStyle, 'animationStyle'), items: withDefault(navListComp(), [ { label: trans("menuItem") + " 1", @@ -144,7 +145,9 @@ const childrenMap = { ]), }; -const NavCompBase = new UICompBuilder(childrenMap, (props) => { +const NavCompBase = new UICompBuilder(childrenMap, (props, dispatch) => { + useMergeCompStyles(props, dispatch); + const data = props.items; const items = ( <> diff --git a/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx b/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx index e6e92f8ee..83953144c 100644 --- a/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx @@ -6,6 +6,7 @@ import { CommonNameConfig, NameConfig, withExposingConfigs } from "../../generat import { SliderChildren, SliderPropertyView, SliderStyled, SliderWrapper } from "./sliderCompConstants"; import { hasIcon } from "comps/utils"; import { BoolControl } from "comps/controls/boolControl"; +import { useMergeCompStyles } from "@lowcoder-ee/util/hooks"; const RangeSliderBasicComp = (function () { const childrenMap = { @@ -14,7 +15,8 @@ const RangeSliderBasicComp = (function () { end: numberExposingStateControl("end", 60), vertical: BoolControl, }; - return new UICompBuilder(childrenMap, (props) => { + return new UICompBuilder(childrenMap, (props, dispatch) => { + useMergeCompStyles(props as Record, dispatch); return props.label({ style: props.style, labelStyle: props.labelStyle, diff --git a/client/packages/lowcoder/src/comps/comps/rootComp.tsx b/client/packages/lowcoder/src/comps/comps/rootComp.tsx index 4ed578d3b..a3080ebb6 100644 --- a/client/packages/lowcoder/src/comps/comps/rootComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/rootComp.tsx @@ -73,7 +73,7 @@ function RootView(props: RootViewProps) { localDefaultTheme; const themeId = selectedTheme ? selectedTheme.id : ( - previewTheme ? "" : 'default-theme-id' + previewTheme ? "preview-theme" : 'default-theme-id' ); useEffect(() => { diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx index 30137c366..d701256d4 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx @@ -75,14 +75,10 @@ export const getStyle = (style: CheckboxStyleType) => { &:hover .ant-checkbox-inner, .ant-checkbox:hover .ant-checkbox-inner, .ant-checkbox-input + ant-checkbox-inner { - background-color:${style.hoverBackground ? style.hoverBackground : '#fff'}; + ${style.hoverBackground && `background-color: ${style.hoverBackground}`}; } - &:hover .ant-checkbox-checked .ant-checkbox-inner, - .ant-checkbox:hover .ant-checkbox-inner, - .ant-checkbox-input + ant-checkbox-inner { - background-color:${style.hoverBackground ? style.hoverBackground : '#ffff'}; - } + &:hover .ant-checkbox-inner, .ant-checkbox:hover .ant-checkbox-inner, diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx index b71750320..5dd6feb82 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx @@ -25,9 +25,9 @@ let MultiSelectBasicComp = (function () { defaultValue: arrayStringExposingStateControl("defaultValue", ["1", "2"]), value: arrayStringExposingStateControl("value"), style: styleControl(InputFieldStyle , 'style'), - labelStyle:styleControl(LabelStyle , 'labelStyle'), - inputFieldStyle:styleControl(MultiSelectStyle , 'inputFieldStyle'), - childrenInputFieldStyle:styleControl(ChildrenMultiSelectStyle), + labelStyle: styleControl(LabelStyle , 'labelStyle'), + inputFieldStyle: styleControl(MultiSelectStyle , 'inputFieldStyle'), + childrenInputFieldStyle: styleControl(ChildrenMultiSelectStyle, 'childrenInputFieldStyle'), margin: MarginControl, padding: PaddingControl, }; diff --git a/client/packages/lowcoder/src/comps/controls/styleControl.tsx b/client/packages/lowcoder/src/comps/controls/styleControl.tsx index 95aac2a97..497722ebf 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControl.tsx @@ -863,17 +863,23 @@ export function styleControl( const {comp, compType} = useContext(CompContext); const theme = useContext(ThemeContext); const bgColor = useContext(BackgroundColorContext); + const { themeId } = theme || {}; + const isPreviewTheme = themeId === 'preview-theme'; + const isDefaultTheme = themeId === 'default-theme-id'; + const appSettingsComp = editorState?.getAppSettingsComp(); const preventAppStylesOverwriting = appSettingsComp?.getView()?.preventAppStylesOverwriting; - const { themeId } = theme || {}; const { appliedThemeId, preventStyleOverwriting } = comp?.comp?.container || comp?.comp || {}; - const appTheme = !preventStyleOverwriting && !preventAppStylesOverwriting + const appTheme = isPreviewTheme || isDefaultTheme || (!preventStyleOverwriting && !preventAppStylesOverwriting) ? theme?.theme : undefined; - const compTheme = compType && !preventStyleOverwriting && !preventAppStylesOverwriting + const compTheme = isPreviewTheme || isDefaultTheme || (compType && !preventStyleOverwriting && !preventAppStylesOverwriting) ? { - ...(theme?.theme?.components?.[compType]?.[styleKey] || {}) as unknown as Record + ...( + theme?.theme?.components?.[compType]?.[styleKey] + || defaultTheme.components?.[compType]?.[styleKey] + ) as unknown as Record } : undefined; const styleProps = (!comp && !compType) || preventStyleOverwriting || preventAppStylesOverwriting || appliedThemeId === themeId diff --git a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx index e32d45ec8..0fd7310ac 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx @@ -1459,8 +1459,8 @@ export const TableHeaderStyle = [ FONT_FAMILY, FONT_STYLE, TEXT, - getStaticBackground(SURFACE_COLOR), - getBackground("primarySurface"), + // getStaticBackground(SURFACE_COLOR), + // getBackground("primarySurface"), { name: "headerBackground", label: trans("style.tableHeaderBackground"), diff --git a/client/packages/lowcoder/src/constants/routesURL.ts b/client/packages/lowcoder/src/constants/routesURL.ts index b57f27ac2..c48af0680 100644 --- a/client/packages/lowcoder/src/constants/routesURL.ts +++ b/client/packages/lowcoder/src/constants/routesURL.ts @@ -15,6 +15,7 @@ export const ORGANIZATION_SETTING = "/setting/organization"; export const THEME_SETTING = "/setting/theme"; export const PLUGINS_SETTING = "/setting/plugins"; export const THEME_DETAIL = "/setting/theme/detail"; +export const THEME_DETAIL_URL = `${THEME_DETAIL}/:themeId`; export const OAUTH_PROVIDER_SETTING = "/setting/oauth-provider"; export const OAUTH_PROVIDER_DETAIL = "/setting/oauth-provider/detail"; diff --git a/client/packages/lowcoder/src/constants/themeConstants.ts b/client/packages/lowcoder/src/constants/themeConstants.ts index 5f3f5c6b6..b05871961 100644 --- a/client/packages/lowcoder/src/constants/themeConstants.ts +++ b/client/packages/lowcoder/src/constants/themeConstants.ts @@ -1,5 +1,29 @@ import { ThemeDetail } from "@lowcoder-ee/api/commonSettingApi"; +const theme = { + primary: "#3377FF", + textDark: "#222222", + textLight: "#FFFFFF", + canvas: "#F5F5F6", + primarySurface: "#FFFFFF", + border: "#D7D9E0", + radius: "4px", + borderWidth: "1px", + borderStyle: "solid", + margin: "3px", + padding: "3px", + gridColumns: "24", + textSize: "14px", + text: "#222222", + animation: "", + animationDelay: "", + animationDuration: "", + opacity: "1", + boxShadow: "", + boxShadowColor: "", + animationIterationCount: "", +}; + const text = { style: { borderWidth: 0, @@ -16,7 +40,14 @@ const input = { }, inputFieldStyle: { borderWidth: '1px', - border: '#D7D9E0' + border: theme.border, + } +}; + +const select = { + ...input, + childrenInputFieldStyle: { + borderWidth: '0px', } }; @@ -77,12 +108,6 @@ const step = { style: {text:'#D7D9E0'} }; -const treeSelect = { - inputFieldStyle: { - borderWidth: '1px', - } -}; - const pageLayout = { style: { borderWidth: '1px', @@ -95,34 +120,45 @@ const qrCode = { } }; -const divider = { +const divider = { style: { radius: "0px" } }; +const navigation = { + style: { + borderWidth: '0px', + } +} + +const slider = { + ...input, + inputFieldStyle: { + ...input.inputFieldStyle, + track: '#D7D9E0', + } +} + +const switchComp = { + ...input, + inputFieldStyle: { + ...input.inputFieldStyle, + unchecked: '#D7D9E0', + } +} + +const checkbox = { + ...input, + inputFieldStyle: { + ...input.inputFieldStyle, + uncheckedBorder: '#D7D9E0', + } +} + + export const defaultTheme: ThemeDetail = { - primary: "#3377FF", - textDark: "#222222", - textLight: "#FFFFFF", - canvas: "#F5F5F6", - primarySurface: "#FFFFFF", - border: "#D7D9E0", - radius: "4px", - borderWidth: "1px", - borderStyle: "solid", - margin: "3px", - padding: "3px", - gridColumns: "24", - textSize: "14px", - text: "#222222", - animation: "", - animationDelay: "", - animationDuration: "", - opacity: "1", - boxShadow: "", - boxShadowColor: "", - animationIterationCount: "", + ...theme, components: { text, input, @@ -133,24 +169,25 @@ export const defaultTheme: ThemeDetail = { tabbedContainer, step, qrCode, - treeSelect, pageLayout, divider, + navigation, + slider, + checkbox, password: input, numberInput: input, textArea: input, autocomplete: input, - switch: input, - checkbox: input, - radio: input, + switch: switchComp, + radio: checkbox, date: input, dateRange: input, time: input, timeRange: input, - slider: input, - rangeSlider: input, + rangeSlider: slider, segmentedControl, - select: input, - multiSelect: input, + select: select, + multiSelect: select, + treeSelect: select, }, }; diff --git a/client/packages/lowcoder/src/pages/setting/theme/detail/index.tsx b/client/packages/lowcoder/src/pages/setting/theme/detail/index.tsx index 6dc0fe1a6..513a598cf 100644 --- a/client/packages/lowcoder/src/pages/setting/theme/detail/index.tsx +++ b/client/packages/lowcoder/src/pages/setting/theme/detail/index.tsx @@ -87,50 +87,55 @@ type ThemeDetailPageProps = { themeList?: ThemeType[]; orgId: string; location: Location & { state: LocationProp }; + match: any; }; type ThemeDetailPageState = { - name: string; - theme: ThemeDetail; + name?: string; + theme?: ThemeDetail; canLeave: boolean; compDsl?: JSONObject; }; class ThemeDetailPage extends React.Component { - themeDefault: ThemeDetail; + themeDefault?: ThemeDetail; readonly id: string; - readonly type: string; + // readonly type: string; readonly inputRef: React.RefObject; footerRef = React.createRef(); constructor(props: ThemeDetailPageProps) { super(props); - const { name, id, theme, type } = props.location.state || {}; - if (!name || !id || !theme || !type) { - history.replace(BASE_URL); - window.location.reload(); - } - - if (theme.chart) { - this.themeDefault = theme; - } else { - this.themeDefault = { - ...theme, - chart: undefined, - }; - } + this.id = this.props.match.params.themeId; - this.id = id; - this.type = type; this.state = { - theme, - name, canLeave: false, compDsl: undefined, }; this.inputRef = React.createRef(); } + findCurrentTheme() { + const themeDetail = this.props.themeList?.find(item => item.id === this.id); + this.setState({ + name: themeDetail?.name, + theme: themeDetail?.theme, + }); + this.themeDefault = themeDetail?.theme; + } + + componentDidMount() { + if(this.props.themeList?.length) { + this.findCurrentTheme(); + } + } + + componentDidUpdate(prevProps: ThemeDetailPageProps, prevState: ThemeDetailPageState) { + if (prevProps.themeList?.length !== this.props.themeList?.length) { + this.findCurrentTheme(); + } + } + handleReset() { this.setState({ theme: this.themeDefault }); } @@ -164,6 +169,8 @@ class ThemeDetailPage extends React.Component +

Oops! Theme not found.

+ + + ) + } + return ( <> )} {item.items.map((colorItem) => ( - + - + @@ -403,7 +423,7 @@ class ThemeDetailPage extends React.Component )} {item.items.map((layoutSettingsItem) => ( - + {layoutSettingsItem.type == "fontFamily" && - + @@ -447,7 +467,7 @@ class ThemeDetailPage extends React.Component )} {item.items.map((layoutSettingsItem) => ( - + {layoutSettingsItem.type == "radius" && - + @@ -534,18 +554,20 @@ class ThemeDetailPage extends React.Component ) => { - this.setState({ - theme: { - ...this.state.theme, - components: { - ...this.state.theme.components, - [compName]: { - ...this.state.theme.components?.[compName], - [styleKey]: compStyle, + if (this.state.theme) { + this.setState({ + theme: { + ...this.state.theme, + components: { + ...this.state.theme.components, + [compName]: { + ...this.state.theme.components?.[compName], + [styleKey]: compStyle, + } } - } - }, - }); + }, + }); + } }} /> @@ -571,7 +593,7 @@ class ThemeDetailPage extends React.Component this.configChange({ themeSettingKey: "chart", chart: value.doc.toString() ? value.doc.toString() : undefined, @@ -585,7 +607,7 @@ class ThemeDetailPage extends React.Component - + diff --git a/client/packages/lowcoder/src/pages/setting/theme/index.tsx b/client/packages/lowcoder/src/pages/setting/theme/index.tsx index 11367cbfc..31e672fdb 100644 --- a/client/packages/lowcoder/src/pages/setting/theme/index.tsx +++ b/client/packages/lowcoder/src/pages/setting/theme/index.tsx @@ -1,13 +1,25 @@ import { Route, Switch } from "react-router"; import ThemePage from "./themePage"; import ThemeDetailPage from "./detail"; -import { THEME_DETAIL, THEME_SETTING } from "constants/routesURL"; +import { THEME_DETAIL_URL, THEME_SETTING } from "constants/routesURL"; +import { useDispatch, useSelector } from "react-redux"; +import { getUser } from "@lowcoder-ee/redux/selectors/usersSelectors"; +import { useEffect } from "react"; +import { fetchCommonSettings } from "@lowcoder-ee/redux/reduxActions/commonSettingsActions"; export const ThemeHome = () => { + const dispatch = useDispatch(); + const user = useSelector(getUser); + const orgId = user.currentOrgId; + + useEffect(() => { + dispatch(fetchCommonSettings({ orgId })); + }, []); + return ( - + ); }; diff --git a/client/packages/lowcoder/src/pages/setting/theme/themePage.tsx b/client/packages/lowcoder/src/pages/setting/theme/themePage.tsx index 5a27f0a4e..d5976a94a 100644 --- a/client/packages/lowcoder/src/pages/setting/theme/themePage.tsx +++ b/client/packages/lowcoder/src/pages/setting/theme/themePage.tsx @@ -43,17 +43,6 @@ class ThemePage extends React.Component { modalVisible: false, }; } - componentDidMount() { - if (this.props.orgId) { - this.props.fetchCommonSettings(this.props.orgId); - } - } - - componentDidUpdate(prevProps: ThemeProps, prevState: ThemeState) { - if (prevProps.orgId !== this.props.orgId) { - this.props.fetchCommonSettings(this.props.orgId); - } - } GoDetail(params: ThemeType, themeList: ThemeType[], type: string) { this.props.setCommonSettings({ @@ -62,10 +51,9 @@ class ThemePage extends React.Component { key: "themeList", value: themeList, }, - }); - history.push({ - pathname: THEME_DETAIL, - state: { ...params, type }, + onSuccess: () => { + history.push(`${THEME_DETAIL}/${params.id}`) + }, }); } @@ -152,13 +140,7 @@ class ThemePage extends React.Component { this.copyTheme(info.themeId); break; case MENU_TYPE.EDIT: - history.push({ - pathname: THEME_DETAIL, - state: { - ...this.props.themeList?.find((theme) => theme.id === info.themeId), - type: DETAIL_TYPE.EDIT, - }, - }); + history.push(`${THEME_DETAIL}/${info.themeId}`) break; case MENU_TYPE.RENAME: this.setCommonSettings(