diff --git a/client/.yarnrc.yml b/client/.yarnrc.yml index 31401ce5f..6d99cee67 100644 --- a/client/.yarnrc.yml +++ b/client/.yarnrc.yml @@ -1,6 +1,6 @@ nodeLinker: node-modules -npmRegistryServer: "https://registry.npmmirror.com" +npmRegistryServer: "https://registry.npmjs.org" plugins: - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs diff --git a/client/config/test/jest.config.js b/client/config/test/jest.config.js index 0c5a5e088..f33e953a6 100644 --- a/client/config/test/jest.config.js +++ b/client/config/test/jest.config.js @@ -1,6 +1,6 @@ import path from "node:path"; -import { buildVars } from "lowcoder-dev-utils/buildVars.js"; -import { currentDirName } from "lowcoder-dev-utils/util.js"; +import { buildVars } from "../../packages/lowcoder-dev-utils/buildVars.js"; +import { currentDirName } from "../../packages/lowcoder-dev-utils/util.js"; const globals = {}; buildVars.forEach(({ name, defaultValue }) => { diff --git a/client/package.json b/client/package.json index 6e4f7236c..fe165bb59 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { - "name": "taco-fe", - "version": "0.1.0", + "name": "lowcoder-root", + "version": "2.2.0", "type": "module", "private": true, "workspaces": [ diff --git a/client/packages/create-lowcoder-plugin/index.js b/client/packages/create-lowcoder-plugin/index.js index b47bfa9f8..8b2faa57e 100755 --- a/client/packages/create-lowcoder-plugin/index.js +++ b/client/packages/create-lowcoder-plugin/index.js @@ -5,7 +5,7 @@ import { spawn } from "cross-spawn"; import { writeFileSync, existsSync } from "node:fs"; import chalk from "chalk"; import { createCommand } from "commander"; -import { readJson, currentDirName } from "lowcoder-dev-utils/util.js"; +import { readJson, currentDirName } from "../lowcoder-dev-utils/util.js"; const currentDir = currentDirName(import.meta.url); const pkg = readJson(path.resolve(currentDir, "./package.json")); diff --git a/client/packages/lowcoder-cli/config/paths.js b/client/packages/lowcoder-cli/config/paths.js index 0d4ba406c..9adf838d2 100644 --- a/client/packages/lowcoder-cli/config/paths.js +++ b/client/packages/lowcoder-cli/config/paths.js @@ -1,6 +1,6 @@ import path from "node:path"; import fs from "node:fs"; -import { currentDirName } from "lowcoder-dev-utils/util.js"; +import { currentDirName } from "../../lowcoder-dev-utils/util.js"; const currentDir = currentDirName(import.meta.url); const appDirectory = fs.realpathSync(process.cwd()); diff --git a/client/packages/lowcoder-cli/config/vite.config.js b/client/packages/lowcoder-cli/config/vite.config.js index ee5a5d5a7..e7baba258 100644 --- a/client/packages/lowcoder-cli/config/vite.config.js +++ b/client/packages/lowcoder-cli/config/vite.config.js @@ -1,12 +1,12 @@ import react from "@vitejs/plugin-react"; import svgrPlugin from "vite-plugin-svgr"; import global from "rollup-plugin-external-globals"; -import { buildVars } from "lowcoder-dev-utils/buildVars.js"; +import { buildVars } from "../../lowcoder-dev-utils/buildVars.js"; import injectCss from "vite-plugin-css-injected-by-js"; -import { getLibNames, getAllLibGlobalVarNames } from "lowcoder-dev-utils/external.js"; +import { getLibNames, getAllLibGlobalVarNames } from "../../lowcoder-dev-utils/external.js"; import paths from "./paths.js"; import { defineConfig } from "vite"; -import { readJson } from "lowcoder-dev-utils/util.js"; +import { readJson } from "../../lowcoder-dev-utils/util.js"; const isProduction = process.env.NODE_ENV === "production"; const packageJson = readJson(paths.appPackageJson); diff --git a/client/packages/lowcoder-dev-utils/package.json b/client/packages/lowcoder-dev-utils/package.json index 26983ff56..1ff32310c 100644 --- a/client/packages/lowcoder-dev-utils/package.json +++ b/client/packages/lowcoder-dev-utils/package.json @@ -3,6 +3,7 @@ "version": "0.0.6", "license": "MIT", "type": "module", + "main": "external.js", "description": "Lowcoder dev utils for lowcoder build process and lowcoder-cli", "keywords": [ "lowcoder" diff --git a/client/packages/lowcoder-plugin-demo/index.tsx b/client/packages/lowcoder-plugin-demo/index.tsx index b446b08b8..682c73d4f 100644 --- a/client/packages/lowcoder-plugin-demo/index.tsx +++ b/client/packages/lowcoder-plugin-demo/index.tsx @@ -3,7 +3,7 @@ import { CompIDE } from "lowcoder-sdk"; import { name, version, lowcoder } from "./package.json"; import compMap from "./src/index"; -import "lowcoder-sdk/dist/style.css"; +import "../lowcoder-sdk/dist/style.css"; function CompDevApp() { return ( diff --git a/client/packages/lowcoder-sdk/vite.config.mts b/client/packages/lowcoder-sdk/vite.config.mts index c8dc806b3..9dcbd4b1b 100644 --- a/client/packages/lowcoder-sdk/vite.config.mts +++ b/client/packages/lowcoder-sdk/vite.config.mts @@ -3,9 +3,9 @@ import react from "@vitejs/plugin-react"; import viteTsconfigPaths from "vite-tsconfig-paths"; import svgrPlugin from "vite-plugin-svgr"; import path from "path"; -import { ensureLastSlash } from "lowcoder-dev-utils/util"; -import { buildVars } from "lowcoder-dev-utils/buildVars"; -import { globalDepPlugin } from "lowcoder-dev-utils/globalDepPlguin"; +import { ensureLastSlash } from "../lowcoder-dev-utils/util"; +import { buildVars } from "../lowcoder-dev-utils/buildVars"; +import { globalDepPlugin } from "../lowcoder-dev-utils/globalDepPlguin"; const define = {}; buildVars.forEach(({ name, defaultValue }) => { diff --git a/client/packages/lowcoder/src/components/table/EditableCell.tsx b/client/packages/lowcoder/src/components/table/EditableCell.tsx index 9955438b2..799c21a26 100644 --- a/client/packages/lowcoder/src/components/table/EditableCell.tsx +++ b/client/packages/lowcoder/src/components/table/EditableCell.tsx @@ -34,6 +34,7 @@ export interface CellProps { size?: string; candidateTags?: string[]; candidateStatus?: { text: string; status: StatusType }[]; + textOverflow?: boolean; } export type CellViewReturn = (props: CellProps) => ReactNode; @@ -43,17 +44,6 @@ export type EditViewFn = (props: { onChangeEnd: () => void; }) => ReactNode; -export const SizeWrapper = styled.div<{ $size?: string }>` - ${(props) => - props.$size && - `padding: ${ - props.$size === "small" ? "8.5px 8px" : props.$size === "large" ? "16.5px 16px" : "12.5px 8px" - }; - line-height: 21px; - min-height: ${props.$size === "small" ? "39px" : props.$size === "large" ? "55px" : "47px"}; - `} -`; - const BorderDiv = styled.div` position: absolute; border: 1.5px solid #315efb; @@ -127,11 +117,15 @@ export function EditableCell(props: EditableCellProps) { } return ( - + {status === "toSave" && !isEditing && } - +
{normalView} - +
); } diff --git a/client/packages/lowcoder/src/components/table/columnTypeView.tsx b/client/packages/lowcoder/src/components/table/columnTypeView.tsx index d3a54cdf1..bf50fac8c 100644 --- a/client/packages/lowcoder/src/components/table/columnTypeView.tsx +++ b/client/packages/lowcoder/src/components/table/columnTypeView.tsx @@ -1,13 +1,17 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; import styled from "styled-components"; -const ColumnTypeViewWrapper = styled.div` - div { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - word-break: keep-all; - } +const ColumnTypeViewWrapper = styled.div<{ + textOverflow?: boolean +}>` + ${props => !props.textOverflow && ` + div { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + word-break: keep-all; + } + `} `; const ColumnTypeHoverView = styled.div<{ @@ -62,7 +66,10 @@ function childIsOverflow(nodes: HTMLCollection): boolean { return false; } -export default function ColumnTypeView(props: { children: React.ReactNode }) { +export default function ColumnTypeView(props: { + children: React.ReactNode, + textOverflow?: boolean, +}) { const wrapperRef = useRef(null); const hoverViewRef = useRef(null); const [isHover, setIsHover] = useState(false); @@ -161,6 +168,7 @@ export default function ColumnTypeView(props: { children: React.ReactNode }) { <> { delayMouseEnter(); }} @@ -171,7 +179,7 @@ export default function ColumnTypeView(props: { children: React.ReactNode }) { > {props.children} - {isHover && hasOverflow && wrapperRef.current && ( + {isHover && hasOverflow && wrapperRef.current && !props.textOverflow && ( ["getOriginalComp"]>; export const RenderComp = withSelectedMultiContext(ColumnTypeComp); @@ -103,7 +104,8 @@ export const columnChildrenMap = { borderWidth: withDefault(RadiusControl, ""), radius: withDefault(RadiusControl, ""), textSize: withDefault(RadiusControl, ""), - cellColor: CellColorComp, + cellColor: CellColorComp, + textOverflow: withDefault(TextOverflowControl, "ellipsis"), }; const StyledIcon = styled.span` @@ -228,6 +230,7 @@ export class ColumnComp extends ColumnInitComp { preInputNode: , placeholder: '14px', })} + {this.children.textOverflow.getPropertyView()} {this.children.cellColor.getPropertyView()} ); diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx index 6db2445f2..65555c29f 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx @@ -51,7 +51,7 @@ import { lastValueIfEqual, shallowEqual } from "util/objectUtils"; import { IContainer } from "../containerBase"; import { getSelectedRowKeys } from "./selectionControl"; import { compTablePropertyView } from "./tablePropertyView"; -import { RowColorComp, TableChildrenView, TableInitComp } from "./tableTypes"; +import { RowColorComp, RowHeightComp, TableChildrenView, TableInitComp } from "./tableTypes"; import { useContext } from "react"; import { EditorContext } from "comps/editorState"; @@ -196,6 +196,17 @@ export class TableImplComp extends TableInitComp implements IContainer { }) ) ); + comp = comp.setChild( + "rowHeight", + comp.children.rowHeight.reduce( + RowHeightComp.changeContextDataAction({ + currentRow: nextRowExample, + currentIndex: 0, + currentOriginalIndex: 0, + columnTitle: nextRowExample ? Object.keys(nextRowExample)[0] : undefined, + }) + ) + ); } if (dataChanged) { diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx index 1c6891208..811d4998a 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx @@ -2,7 +2,7 @@ import { Table } from "antd"; import { TableProps } from "antd/es/table"; import { TableCellContext, TableRowContext } from "comps/comps/tableComp/tableContext"; import { TableToolbar } from "comps/comps/tableComp/tableToolbarComp"; -import { RowColorViewType } from "comps/comps/tableComp/tableTypes"; +import { RowColorViewType, RowHeightViewType } from "comps/comps/tableComp/tableTypes"; import { COL_MIN_WIDTH, COLUMN_CHILDREN_KEY, @@ -169,6 +169,10 @@ const TableWrapper = styled.div<{ border-top: none !important; border-inline-start: none !important; + &::after { + box-shadow: none !important; + } + .ant-table-content { overflow: unset !important; } @@ -280,8 +284,10 @@ const TableTh = styled.th<{ width?: number }>` const TableTd = styled.td<{ background: string; - $style: TableColumnStyleType; + $style: TableColumnStyleType & {rowHeight?: string}; $isEditing: boolean; + $tableSize?: string; + $autoHeight?: boolean; }>` .ant-table-row-expand-icon, .ant-table-row-indent { @@ -291,16 +297,42 @@ const TableTd = styled.td<{ background: ${(props) => props.background}; border-color: ${(props) => props.$style.border}; } - background: ${(props) => props.background} !important; border-color: ${(props) => props.$style.border} !important; border-width: ${(props) => props.$style.borderWidth} !important; border-radius: ${(props) => props.$style.radius}; padding: 0 !important; - > div > div { + > div { color: ${(props) => props.$style.text}; font-size: ${(props) => props.$style.textSize}; + line-height: 21px; + + ${(props) => props.$tableSize === 'small' && ` + padding: 8.5px 8px; + min-height: ${props.$style.rowHeight || '39px'}; + ${!props.$autoHeight && ` + overflow-y: auto; + max-height: ${props.$style.rowHeight || '39px'}; + `}; + `}; + ${(props) => props.$tableSize === 'middle' && ` + padding: 12.5px 8px; + min-height: ${props.$style.rowHeight || '47px'}; + ${!props.$autoHeight && ` + overflow-y: auto; + max-height: ${props.$style.rowHeight || '47px'}; + `}; + `}; + ${(props) => props.$tableSize === 'large' && ` + padding: 16.5px 16px; + min-height: ${props.$style.rowHeight || '55px'}; + ${!props.$autoHeight && ` + overflow-y: auto; + max-height: ${props.$style.rowHeight || '55px'}; + `}; + `}; + &, > .ant-badge > .ant-badge-status-text, > div > .markdown-body { @@ -383,30 +415,40 @@ type CustomTableProps = Omit, "components" | columns: CustomColumnType[]; viewModeResizable: boolean; rowColorFn: RowColorViewType; + rowHeightFn: RowHeightViewType; columnsStyle: TableColumnStyleType; + size?: string; + rowAutoHeight?: boolean; }; function TableCellView(props: { record: RecordType; title: string; rowColorFn: RowColorViewType; + rowHeightFn: RowHeightViewType; cellColorFn: CellColorViewType; rowIndex: number; children: any; columnsStyle: TableColumnStyleType; columnStyle: TableColumnStyleType; + tableSize?: string; + autoHeight?: boolean; }) { const { record, title, rowIndex, rowColorFn, + rowHeightFn, cellColorFn, children, columnsStyle, columnStyle, + tableSize, + autoHeight, ...restProps } = props; + const [editing, setEditing] = useState(false); const rowContext = useContext(TableRowContext); let tdView; @@ -419,17 +461,24 @@ function TableCellView(props: { currentOriginalIndex: record[OB_ROW_ORI_INDEX], columnTitle: title, }); + const rowHeight = rowHeightFn({ + currentRow: record, + currentIndex: rowIndex, + currentOriginalIndex: record[OB_ROW_ORI_INDEX], + columnTitle: title, + }); const cellColor = cellColorFn({ currentCell: record[title.toLowerCase()], }); - const style: TableColumnStyleType = { + const style = { background: cellColor || rowColor || columnStyle.background || columnsStyle.background, text: columnStyle.text || columnsStyle.text, border: columnStyle.border || columnsStyle.border, radius: columnStyle.radius || columnsStyle.radius, borderWidth: columnStyle.borderWidth || columnsStyle.borderWidth, textSize: columnStyle.textSize || columnsStyle.textSize, + rowHeight: rowHeight, } let { background } = style; if (rowContext.selected) { @@ -444,6 +493,8 @@ function TableCellView(props: { background={background} $style={style} $isEditing={editing} + $tableSize={tableSize} + $autoHeight={autoHeight} > {children} @@ -511,10 +562,13 @@ function ResizeableTable(props: CustomTableProps ({ width: resizeWidth, @@ -583,6 +637,7 @@ export function TableCompView(props: { const compChildren = comp.children; const style = compChildren.style.getView(); const rowStyle = compChildren.rowStyle.getView(); + const rowAutoHeight = compChildren.rowAutoHeight.getView(); const columnsStyle = compChildren.columnsStyle.getView(); const changeSet = useMemo(() => compChildren.columns.getChangeSet(), [compChildren.columns]); const hasChange = useMemo(() => !_.isEmpty(changeSet), [changeSet]); @@ -610,7 +665,7 @@ export function TableCompView(props: { size, dynamicColumn, dynamicColumnConfig, - columnsAggrData + columnsAggrData, ), [ columnViews, @@ -711,6 +766,7 @@ export function TableCompView(props: { } }} rowColorFn={compChildren.rowColor.getView() as any} + rowHeightFn={compChildren.rowHeight.getView() as any} {...compChildren.selection.getView()(onEvent)} bordered={!compChildren.hideBordered.getView()} onChange={(pagination, filters, sorter, extra) => { @@ -722,6 +778,7 @@ export function TableCompView(props: { viewModeResizable={compChildren.viewModeResizable.getView()} dataSource={pageDataInfo.data} size={compChildren.size.getView()} + rowAutoHeight={rowAutoHeight} tableLayout="fixed" loading={ loading || diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx index 8ed0d09b0..14a18e140 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx @@ -504,11 +504,12 @@ export function compTablePropertyView {["layout", "both"].includes(editorModeStatus) && ( <>
- {comp.children.style.getPropertyView()} - + {comp.children.style.getPropertyView()}
{comp.children.rowStyle.getPropertyView()} + {comp.children.rowAutoHeight.getPropertyView()} + {comp.children.rowHeight.getPropertyView()} {comp.children.rowColor.getPropertyView()}
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx index ca60434e3..0fadfffc2 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx @@ -54,14 +54,12 @@ const getStyle = ( return css` background-color: ${style.toolbarBackground}; // Implement horizontal scrollbar and vertical page number selection is not blocked - // padding: ${position === "above" ? "13px 16px 313px 16px" : "313px 16px 13px 16px"}; - // margin: ${position === "above" ? "0 0 -300px 0" : "-300px 0 0 0"}; padding: 13px 12px; - ${fixedToolbar && ` - position: sticky; - postion: -webkit-sticky; - z-index: 99; - `}; + position: sticky; + postion: -webkit-sticky; + left: 0; + + ${fixedToolbar && `z-index: 99;`}; ${fixedToolbar && position === 'below' && `bottom: 0;`}; ${fixedToolbar && position === 'above' && `top: 0;` }; diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx index 144e61fb6..ff4656e6e 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx @@ -5,6 +5,7 @@ import { ArrayStringControl, BoolCodeControl, ColorOrBoolCodeControl, + HeightOrBoolCodeControl, JSONObjectArrayControl, RadiusControl, StringControl, @@ -108,7 +109,9 @@ const TableEventControl = eventHandlerControl(TableEventOptions); const rowColorLabel = trans("table.rowColor"); const RowColorTempComp = withContext( - new MultiCompBuilder({ color: ColorOrBoolCodeControl }, (props) => props.color) + new MultiCompBuilder({ + color: ColorOrBoolCodeControl, + }, (props) => props.color) .setPropertyViewFn((children) => children.color.propertyView({ label: rowColorLabel, @@ -134,6 +137,36 @@ export type RowColorViewType = (param: { columnTitle: string; }) => string; +const rowHeightLabel = trans("table.rowHeight"); +const RowHeightTempComp = withContext( + new MultiCompBuilder({ + height: HeightOrBoolCodeControl, + }, (props) => props.height) + .setPropertyViewFn((children) => + children.height.propertyView({ + label: rowHeightLabel, + tooltip: trans("table.rowHeightDesc"), + }) + ) + .build(), + ["currentRow", "currentIndex", "currentOriginalIndex", "columnTitle"] as const +); + +// @ts-ignore +export class RowHeightComp extends RowHeightTempComp { + override getPropertyView() { + return controlItem({ filterText: rowHeightLabel }, super.getPropertyView()); + } +} + +// fixme, should be infer from RowHeightComp, but withContext type incorrect +export type RowHeightViewType = (param: { + currentRow: any; + currentIndex: number; + currentOriginalIndex: number | string; + columnTitle: string; +}) => string; + const tableChildrenMap = { hideBordered: BoolControl, hideHeader: BoolControl, @@ -157,6 +190,8 @@ const tableChildrenMap = { onEvent: TableEventControl, loading: BoolCodeControl, rowColor: RowColorComp, + rowAutoHeight: withDefault(AutoHeightControl, "auto"), + rowHeight: RowHeightComp, dynamicColumn: BoolPureControl, // todo: support object config dynamicColumnConfig: ArrayStringControl, diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx index e56f05f25..c2f73f76f 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx @@ -267,7 +267,7 @@ export function columnsToAntdFormat( size: string, dynamicColumn: boolean, dynamicColumnConfig: Array, - columnsAggrData: ColumnsAggrData + columnsAggrData: ColumnsAggrData, ): Array> { const sortMap: Map = new Map( sort.map((s) => [s.column, s.desc ? "descend" : "ascend"]) @@ -338,7 +338,12 @@ export function columnsToAntdFormat( String(record[OB_ROW_ORI_INDEX]) ) .getView() - .view({ editable: column.editable, size, candidateTags: tags, candidateStatus: status }); + .view({ + editable: column.editable, + size, candidateTags: tags, + candidateStatus: status, + textOverflow: column.textOverflow, + }); }, ...(column.sortable ? { diff --git a/client/packages/lowcoder/src/comps/comps/textComp.tsx b/client/packages/lowcoder/src/comps/comps/textComp.tsx index 2062fab7b..80b108d24 100644 --- a/client/packages/lowcoder/src/comps/comps/textComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/textComp.tsx @@ -24,7 +24,7 @@ import { EditorContext } from "comps/editorState"; const getStyle = (style: TextStyleType) => { return css` border-radius: ${(style.radius ? style.radius : "4px")}; - border: ${(style.borderWidth ? style.borderWidth : "1px")} solid ${style.border}; + border: ${(style.borderWidth ? style.borderWidth : "0px")} solid ${style.border}; color: ${style.text}; background-color: ${style.background}; .markdown-body a { diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx index 6028c7a1e..04e52ef8a 100644 --- a/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx @@ -77,11 +77,11 @@ export const InputComp = new UICompBuilder(childrenMap, (props) => { - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( children.label.getPropertyView() )} - {useContext(EditorContext).editorModeStatus !== "layout" && ( + {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{hiddenPropertyView(children)}
@@ -94,7 +94,7 @@ export const InputComp = new UICompBuilder(childrenMap, (props) => { )} - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.style.getPropertyView()}
)} diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/mentionComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/mentionComp.tsx index 9a4eabe9b..89c75bd8e 100644 --- a/client/packages/lowcoder/src/comps/comps/textInputComp/mentionComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/textInputComp/mentionComp.tsx @@ -209,7 +209,7 @@ let MentionTmpComp = (function () { {children.placeholder.propertyView({ label: trans("prop.placeholder"), })} - {useContext(EditorContext).editorModeStatus !== "layout" && ( + {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( children.mentionList.propertyView({ label: trans("mention.mentionList"), }) @@ -217,11 +217,11 @@ let MentionTmpComp = (function () {
- {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( children.label.getPropertyView() )} - {useContext(EditorContext).editorModeStatus !== "layout" && ( + {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.onEvent.getPropertyView()} {disabledPropertyView(children)} @@ -240,11 +240,11 @@ let MentionTmpComp = (function () {
)} - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.style.getPropertyView()}
- )} + )} )) .build(); diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx index 66275bea4..0437e87b6 100644 --- a/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx @@ -79,11 +79,11 @@ const PasswordTmpComp = (function () { - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( children.label.getPropertyView() )} - {useContext(EditorContext).editorModeStatus !== "layout" && ( + {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{hiddenPropertyView(children)}
@@ -101,7 +101,7 @@ const PasswordTmpComp = (function () {
)} - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.style.getPropertyView()}
)} diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx index 6c043e30a..e11027a69 100644 --- a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx @@ -95,11 +95,11 @@ let TextAreaTmpComp = (function () { - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( children.label.getPropertyView() )} - {useContext(EditorContext).editorModeStatus !== "layout" && ( + {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.autoHeight.getPropertyView()} @@ -112,7 +112,7 @@ let TextAreaTmpComp = (function () { )} - {useContext(EditorContext).editorModeStatus === "layout" && ( + {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && ( <>
{children.style.getPropertyView()}
)} diff --git a/client/packages/lowcoder/src/comps/controls/codeControl.tsx b/client/packages/lowcoder/src/comps/controls/codeControl.tsx index 27b9197c5..3b50b3318 100644 --- a/client/packages/lowcoder/src/comps/controls/codeControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/codeControl.tsx @@ -472,6 +472,26 @@ export const RadiusControl = codeControl( } ); +export const HeightOrBoolCodeControl = codeControl( + (value: unknown) => { + const valueString = toString(value); + if (valueString === "true") { + // true default 40px + return "40px"; + } + if (valueString === "" || valueString === "false") { + return ""; + } + if (/^[0-9]+(px|%)?$/.test(valueString)) { + return valueString; + } + throw new Error(`the argument must be a number(4), a number of pixels (4px), or a percent (50%).`); + }, + { + expectedType: "CSS", + } +); + export const FunctionControl = codeControl( (value) => { if (typeof value === "function") { diff --git a/client/packages/lowcoder/src/comps/controls/styleControl.tsx b/client/packages/lowcoder/src/comps/controls/styleControl.tsx index 278944ac9..fe0f1b227 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControl.tsx @@ -135,7 +135,7 @@ function calcColors>( res[name] = themeWithDefault[config.radius]; } if (isBorderWidthConfig(config)) { - res[name] = '1px'; + res[name] = '0px'; } if (isTextSizeConfig(config)) { // TODO: remove default textSize after added in theme in backend. diff --git a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx index 311a1fa56..c77f487a5 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx @@ -279,7 +279,7 @@ const TEXT_SIZE = { name: "textSize", label: trans("style.textSize"), textSize: "textSize", -} as const; +} as const; const CONTAINERHEADERPADDING = { name: "containerheaderpadding", diff --git a/client/packages/lowcoder/src/comps/controls/textOverflowControl.tsx b/client/packages/lowcoder/src/comps/controls/textOverflowControl.tsx new file mode 100644 index 000000000..b8a60e9da --- /dev/null +++ b/client/packages/lowcoder/src/comps/controls/textOverflowControl.tsx @@ -0,0 +1,29 @@ +import { trans } from "i18n"; +import { ControlParams } from "./controlParams"; +import { dropdownAbstractControl } from "./dropdownControl"; + +const overflowOptions = [ + { + label: trans("textOverflowProp.ellipsis"), + value: "ellipsis", + }, + { + label: trans("textOverflowProp.wrap"), + value: "wrap", + }, +] as const; + +const TextOverflowTmpControl = dropdownAbstractControl(overflowOptions, "ellipsis"); +export class TextOverflowControl extends TextOverflowTmpControl { + override getView() { + return this.value !== "ellipsis"; + } + + override getPropertyView() { + return this.propertyView({ label: trans("prop.textOverflow") }); + } + + override propertyView(params: ControlParams) { + return super.propertyView({ radioButton: true, ...params }); + } +} diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index f77fe975c..fa8b1aa3a 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -186,12 +186,17 @@ export const en = { "showBody": "Show Body", "showFooter": "Show Footer", "maskClosable": "Click Outside to Close", - "showMask": "Show Mask" + "showMask": "Show Mask", + "textOverflow": "Text Overflow", }, "autoHeightProp": { "auto": "Auto", "fixed": "Fixed" }, + "textOverflowProp": { + "ellipsis": "Ellipsis", + "wrap": "Wrap" + }, "labelProp": { "text": "Label", "tooltip": "Tooltip", @@ -1290,9 +1295,11 @@ export const en = { "sortChange": "Sort Change", "pageChange": "Page Change", "refresh": "Refresh", - "rowColor": "Conditional Row Color", + "rowColor": "Conditional row color", "rowColorDesc": "Conditionally Set the Row Color Based on the Optional Variables: CurrentRow, CurrentOriginalIndex, CurrentIndex, ColumnTitle. For Example: '{{ currentRow.id > 3 ? \"green\" : \"red\" }}'", - "cellColor": "Conditional Cell Color", + "rowHeight": "Conditional row height", + "rowHeightDesc": "Conditionally Set the Row Height Based on the Optional Variables: CurrentRow, CurrentOriginalIndex, CurrentIndex, ColumnTitle. For Example: '{{ currentRow.id > 3 ? \"60px\" : \"40px\" }}'", + "cellColor": "Conditional cell color", "cellColorDesc": "Conditionally Set the Cell Color Based on the Cell Value Using CurrentCell. For Example: '{{ currentCell == 3 ? \"green\" : \"red\" }}'", "saveChangesNotBind": "No Event Handler Configured for Saving Changes. Please Bind at Least One Event Handler Before Click.", "dynamicColumn": "Use Dynamic Column Setting", diff --git a/client/packages/lowcoder/vite.config.mts b/client/packages/lowcoder/vite.config.mts index 08ef34ab5..c7b989812 100644 --- a/client/packages/lowcoder/vite.config.mts +++ b/client/packages/lowcoder/vite.config.mts @@ -8,9 +8,9 @@ import { visualizer } from "rollup-plugin-visualizer"; import path from "path"; import chalk from "chalk"; import { createHtmlPlugin } from "vite-plugin-html"; -import { ensureLastSlash } from "lowcoder-dev-utils/util"; -import { buildVars } from "lowcoder-dev-utils/buildVars"; -import { globalDepPlugin } from "lowcoder-dev-utils/globalDepPlguin"; +import { ensureLastSlash } from "../lowcoder-dev-utils/util"; +import { buildVars } from "../lowcoder-dev-utils/buildVars"; +import { globalDepPlugin } from "../lowcoder-dev-utils/globalDepPlguin"; dotenv.config(); diff --git a/client/yarn.lock b/client/yarn.lock index f3ac1c385..afc7ac179 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -8356,9 +8356,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-only-ascii@patch:eslint-plugin-only-ascii@npm%3A0.0.0#./.yarn/patches/eslint-plugin-only-ascii-npm-0.0.0-29e3417685.patch::locator=taco-fe%40workspace%3A.": +"eslint-plugin-only-ascii@patch:eslint-plugin-only-ascii@npm%3A0.0.0#./.yarn/patches/eslint-plugin-only-ascii-npm-0.0.0-29e3417685.patch::locator=lowcoder-root%40workspace%3A.": version: 0.0.0 - resolution: "eslint-plugin-only-ascii@patch:eslint-plugin-only-ascii@npm%3A0.0.0#./.yarn/patches/eslint-plugin-only-ascii-npm-0.0.0-29e3417685.patch::version=0.0.0&hash=2893de&locator=taco-fe%40workspace%3A." + resolution: "eslint-plugin-only-ascii@patch:eslint-plugin-only-ascii@npm%3A0.0.0#./.yarn/patches/eslint-plugin-only-ascii-npm-0.0.0-29e3417685.patch::version=0.0.0&hash=2893de&locator=lowcoder-root%40workspace%3A." dependencies: requireindex: ~1.1.0 checksum: 681f936c1933b0bc01e2b360df9f05a4cdb0a545a026e0311da0105a60eb3cf6f2f81145e12e5bfefd16eeff9272acfb7e41cc78a587c0487c49f311cd176a2e @@ -11942,6 +11942,58 @@ __metadata: languageName: unknown linkType: soft +"lowcoder-root@workspace:.": + version: 0.0.0-use.local + resolution: "lowcoder-root@workspace:." + dependencies: + "@babel/preset-env": ^7.20.2 + "@babel/preset-typescript": ^7.18.6 + "@lottiefiles/react-lottie-player": ^3.5.3 + "@rollup/plugin-typescript": ^8.5.0 + "@testing-library/jest-dom": ^5.16.5 + "@testing-library/react": ^12.0.0 + "@testing-library/user-event": ^13.2.1 + "@types/ali-oss": ^6.16.4 + "@types/file-saver": ^2.0.5 + "@types/jest": ^29.2.2 + "@types/mime": ^2.0.3 + "@types/qrcode.react": ^1.0.2 + "@types/react-grid-layout": ^1.3.0 + "@types/react-helmet": ^6.1.5 + "@types/react-resizable": ^3.0.5 + "@types/react-router-dom": ^5.3.2 + "@types/shelljs": ^0.8.11 + "@types/styled-components": ^5.1.19 + "@types/stylis": ^4.0.2 + "@types/tern": 0.23.4 + "@types/toposort": ^2.0.3 + "@types/ua-parser-js": ^0.7.36 + "@welldone-software/why-did-you-render": ^6.2.3 + add: ^2.0.6 + antd-mobile: ^5.28.0 + babel-jest: ^29.3.0 + babel-preset-react-app: ^10.0.1 + chalk: 4 + husky: ^8.0.1 + jest: ^29.5.0 + jest-environment-jsdom: ^29.5.0 + lint-staged: ^13.0.1 + lowcoder-dev-utils: "workspace:^" + mq-polyfill: ^1.1.8 + number-precision: ^1.6.0 + prettier: ^2.7.0 + react-player: ^2.11.0 + rimraf: ^3.0.2 + rollup: ^2.79.0 + shelljs: ^0.8.5 + svgo: ^3.0.0 + tui-image-editor: ^3.15.3 + typescript: ^4.8.4 + whatwg-fetch: ^3.6.2 + yarn: ^1.22.19 + languageName: unknown + linkType: soft + "lowcoder-sdk@workspace:^, lowcoder-sdk@workspace:packages/lowcoder-sdk": version: 0.0.0-use.local resolution: "lowcoder-sdk@workspace:packages/lowcoder-sdk" @@ -15776,9 +15828,9 @@ __metadata: languageName: node linkType: hard -"react-virtualized@patch:react-virtualized@npm%3A9.22.3#./.yarn/patches/react-virtualized-npm-9.22.3-0fff3cbf64.patch::locator=taco-fe%40workspace%3A.": +"react-virtualized@patch:react-virtualized@npm%3A9.22.3#./.yarn/patches/react-virtualized-npm-9.22.3-0fff3cbf64.patch::locator=lowcoder-root%40workspace%3A.": version: 9.22.3 - resolution: "react-virtualized@patch:react-virtualized@npm%3A9.22.3#./.yarn/patches/react-virtualized-npm-9.22.3-0fff3cbf64.patch::version=9.22.3&hash=36eda7&locator=taco-fe%40workspace%3A." + resolution: "react-virtualized@patch:react-virtualized@npm%3A9.22.3#./.yarn/patches/react-virtualized-npm-9.22.3-0fff3cbf64.patch::version=9.22.3&hash=36eda7&locator=lowcoder-root%40workspace%3A." dependencies: "@babel/runtime": ^7.7.2 clsx: ^1.0.4 @@ -17532,58 +17584,6 @@ __metadata: languageName: node linkType: hard -"taco-fe@workspace:.": - version: 0.0.0-use.local - resolution: "taco-fe@workspace:." - dependencies: - "@babel/preset-env": ^7.20.2 - "@babel/preset-typescript": ^7.18.6 - "@lottiefiles/react-lottie-player": ^3.5.3 - "@rollup/plugin-typescript": ^8.5.0 - "@testing-library/jest-dom": ^5.16.5 - "@testing-library/react": ^12.0.0 - "@testing-library/user-event": ^13.2.1 - "@types/ali-oss": ^6.16.4 - "@types/file-saver": ^2.0.5 - "@types/jest": ^29.2.2 - "@types/mime": ^2.0.3 - "@types/qrcode.react": ^1.0.2 - "@types/react-grid-layout": ^1.3.0 - "@types/react-helmet": ^6.1.5 - "@types/react-resizable": ^3.0.5 - "@types/react-router-dom": ^5.3.2 - "@types/shelljs": ^0.8.11 - "@types/styled-components": ^5.1.19 - "@types/stylis": ^4.0.2 - "@types/tern": 0.23.4 - "@types/toposort": ^2.0.3 - "@types/ua-parser-js": ^0.7.36 - "@welldone-software/why-did-you-render": ^6.2.3 - add: ^2.0.6 - antd-mobile: ^5.28.0 - babel-jest: ^29.3.0 - babel-preset-react-app: ^10.0.1 - chalk: 4 - husky: ^8.0.1 - jest: ^29.5.0 - jest-environment-jsdom: ^29.5.0 - lint-staged: ^13.0.1 - lowcoder-dev-utils: "workspace:^" - mq-polyfill: ^1.1.8 - number-precision: ^1.6.0 - prettier: ^2.7.0 - react-player: ^2.11.0 - rimraf: ^3.0.2 - rollup: ^2.79.0 - shelljs: ^0.8.5 - svgo: ^3.0.0 - tui-image-editor: ^3.15.3 - typescript: ^4.8.4 - whatwg-fetch: ^3.6.2 - yarn: ^1.22.19 - languageName: unknown - linkType: soft - "tapable@npm:^0.2.3": version: 0.2.9 resolution: "tapable@npm:0.2.9" diff --git a/deploy/docker/Dockerfile b/deploy/docker/Dockerfile index c618771a9..0bdf2a6ee 100644 --- a/deploy/docker/Dockerfile +++ b/deploy/docker/Dockerfile @@ -128,6 +128,8 @@ COPY ./client /lowcoder-client WORKDIR /lowcoder-client RUN yarn --immutable +# TODO: build lowcoder-comps + # curl is required for yarn build to succeed, because it calls it while building client RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates