Merge branch 'polyfill/vision' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into polyfill/vision

This commit is contained in:
凤矗 2020-05-07 15:13:29 +08:00
commit a891e3be01
14 changed files with 278 additions and 124 deletions

View File

@ -25,6 +25,9 @@
align-items: stretch; align-items: stretch;
justify-content: flex-end; justify-content: flex-end;
pointer-events: all; pointer-events: all;
> * {
flex-shrink: 0;
}
} }
&-action { &-action {

View File

@ -49,13 +49,14 @@ class AliGlobalLocale {
} }
} else if (g_config) { } else if (g_config) {
if (g_config.locale) { if (g_config.locale) {
return languageMap[g_config.locale] || (g_config.locale || '').replace('_', '-'); return languageMap[g_config.locale] || g_config.locale.replace('_', '-');
} }
} }
let locale: string = ''; let locale: string = '';
if (navigator.language) { if (navigator.language) {
locale = (navigator.language as string).replace('_', '-'); const lang = (navigator.language as string);
return languageMap[lang] || lang.replace('_', '-');
} }
// IE10 及更低版本使用 browserLanguage // IE10 及更低版本使用 browserLanguage

View File

@ -0,0 +1,48 @@
class FocusingManager {
deploy() {
}
send(e: MouseEvent | KeyboardEvent) {
}
addModalCheck() {
}
create(config: FocusableConfig) {
}
activeItem() {
}
suspenceItem() {
}
}
export interface FocusableConfig {
range: HTMLElement | ((e: MouseEvent) => boolean);
modal?: boolean;
onEsc?: () => void;
onBlur?: () => void;
}
class Focusable {
readonly isModal: boolean;
constructor(private manager: FocusingManager, { range, modal }: FocusableConfig) {
this.isModal = modal == null ? false : modal;
}
checkRange(e: MouseEvent) {
}
active() {
this.manager.activeItem(this);
}
suspence() {
this.manager.suspenceItem(this);
}
purge() {
}
}

View File

@ -13,7 +13,7 @@
align-items: center; align-items: center;
} }
.lc-field-icon { .lc-field-icon {
margin-right: @x-gap; // margin-right: @x-gap;
transform-origin: center; transform-origin: center;
transition: transform 0.1s; transition: transform 0.1s;
} }
@ -21,7 +21,7 @@
&.lc-plain-field { &.lc-plain-field {
// for top-level style // for top-level style
padding: 8px 10px; // padding: 8px 10px;
> .lc-field-body { > .lc-field-body {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
@ -34,7 +34,16 @@
display: flex; display: flex;
align-items: center; align-items: center;
// for top-level style // for top-level style
padding: 8px 10px; padding: 16px;
&:first-child{
padding-top: 16px;
}
&:last-child{
padding-bottom: 16px;
}
&+.lc-inline-field{
padding-top: 0;
}
> .lc-field-head { > .lc-field-head {
width: 70px; width: 70px;
@ -58,19 +67,29 @@
border-top: 1px solid var(--color-line-normal); border-top: 1px solid var(--color-line-normal);
} }
> .lc-field-head { > .lc-field-head {
padding-left: @x-gap; // padding-left: @x-gap;
height: 32px; height: 32px;
display: flex; display: flex;
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
background: var(--color-block-background-shallow, rgba(31,56,88,.06)); // background: var(--color-block-background-shallow, rgba(31,56,88,.06));
border-bottom: 1px solid var(--color-line-normal); // border-bottom: 1px solid var(--color-line-normal);
color: var(--color-title); // color: var(--color-title);
padding: 0 16px;
background-color: #F7F9FC;
color: #8F9BB3;
user-select: none; user-select: none;
} }
> .lc-field-body { > .lc-field-body {
padding: @y-gap @x-gap/2; // padding: @y-gap @x-gap/2;
padding: 16px;
.lc-inline-field{
margin-bottom: 16px;
&:last-child{
margin-bottom: 0;
}
}
} }
+ .lc-inline-field { + .lc-inline-field {
@ -94,7 +113,11 @@
} }
&.lc-accordion-field { &.lc-accordion-field {
position: relative;
// collapsed // collapsed
&:last-child.lc-field-is-collapsed{
border-bottom: 1px solid var(--color-line-normal);
}
&.lc-field-is-collapsed { &.lc-field-is-collapsed {
> .lc-field-head .lc-field-icon { > .lc-field-head .lc-field-icon {
transform: rotate(180deg); transform: rotate(180deg);
@ -106,14 +129,15 @@
// 邻近的保持上下距离 // 邻近的保持上下距离
+ .lc-field { + .lc-field {
margin-top: @y-gap; // margin-top: @y-gap;
} }
} }
// 2rd level reset // 2rd level reset
.lc-field-body { .lc-field-body {
.lc-inline-field { .lc-inline-field {
padding: @y-gap @x-gap/2 0 @x-gap/2; // padding: @y-gap @x-gap/2 0 @x-gap/2;
padding: 0;
&:first-child { &:first-child {
padding-top: 0; padding-top: 0;
} }
@ -132,7 +156,8 @@
background: var(--color-block-background-light); background: var(--color-block-background-light);
border-bottom-color: var(--color-line-light, rgba(31, 56, 88, .1)); border-bottom-color: var(--color-line-light, rgba(31, 56, 88, .1));
> .lc-field-icon { > .lc-field-icon {
margin-right: @x-gap/2; // margin-right: @x-gap/2;
margin-right: 0;
} }
} }
} }

View File

@ -42,9 +42,22 @@
margin-right: 0; margin-right: 0;
>.lc-setter-actions { >.lc-setter-actions {
position: absolute; position: absolute;
right: 10px; right: 16px;
top: 0; top: 0;
height: 32px; height: 32px;
transform: none; transform: none;
} }
} }
.lc-block-field > .lc-field-body > .lc-setter-mixed{
}
.lc-accordion-field > .lc-field-body > .lc-setter-mixed{
position: static;
margin-right: 0;
> .lc-setter-actions{
right: 32px;
top: 6px;
transform: none;
}
}

View File

@ -15,7 +15,7 @@
height: 30px; height: 30px;
display: flex; display: flex;
align-items: center; align-items: center;
padding-left: 5px; padding: 0 16px;
border-bottom: 1px solid var(--color-line-normal); border-bottom: 1px solid var(--color-line-normal);
.lc-settings-navigator-icon { .lc-settings-navigator-icon {
width: 16px; width: 16px;

View File

@ -12,6 +12,8 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
} }
private dispose?: () => void; private dispose?: () => void;
// private focusing?: FocusingItem;
private shell: HTMLElement | null = null;
componentDidMount() { componentDidMount() {
const { area } = this.props; const { area } = this.props;
const triggerClose = () => area.setVisible(false); const triggerClose = () => area.setVisible(false);
@ -19,18 +21,44 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
this.dispose = () => { this.dispose = () => {
area.skeleton.editor.removeListener('designer.dragstart', triggerClose); area.skeleton.editor.removeListener('designer.dragstart', triggerClose);
} }
/*
this.focusing = focusingTrack.create(this.shell!, {
onEsc: () => {
this.props.area.setVisible(false);
},
onBlur: () => {
this.props.area.setVisible(false);
},
// modal: boolean
});
*/
this.onEffect();
}
onEffect() {
/*
const { area } = this.props;
if (area.visible) {
this.focusing?.active();
} else {
this.focusing?.suspense();
}
*/
}
componentDidUpdate() {
this.onEffect();
} }
componentWillUnmount() { componentWillUnmount() {
// this.focusing?.purge();
this.dispose?.(); this.dispose?.();
} }
render() { render() {
const { area } = this.props; const { area } = this.props;
// TODO: add focusingManager
// focusin set focus (push|replace)
// focusout remove focus
// onEsc
const width = area.current?.config.props?.width; const width = area.current?.config.props?.width;
const hideTitleBar = area.current?.config.props?.hideTitleBar; const hideTitleBar = area.current?.config.props?.hideTitleBar;
const style = width ? { const style = width ? {
@ -38,6 +66,7 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
} : undefined; } : undefined;
return ( return (
<div <div
ref={(ref) => { this.shell = ref }}
className={classNames('lc-left-float-pane', { className={classNames('lc-left-float-pane', {
'lc-area-visible': area.visible, 'lc-area-visible': area.visible,
})} })}

View File

@ -54,14 +54,11 @@ body {
display: none; display: none;
} }
.lc-panel-title { .lc-panel-title {
height: 48px;
font-size: 16px;
// background-color: var(--pane-title-bg-color,rgba(31,56,88,.04)); // background-color: var(--pane-title-bg-color,rgba(31,56,88,.04));
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
padding: 0 15px; padding: 0 15px;
border-bottom: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
.lc-help-tip { .lc-help-tip {
margin-left: 4px; margin-left: 4px;
@ -69,6 +66,14 @@ body {
cursor: pointer; cursor: pointer;
} }
} }
> .lc-panel-title {
height: 48px;
font-size: 16px;
padding: 0 15px;
// border-bottom: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
color: #0F1726;
font-weight: bold;
}
.lc-panel-body { .lc-panel-body {
position: absolute; position: absolute;
@ -111,6 +116,9 @@ body {
} }
*/ */
} }
.lc-outline-pane{
border-top: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
}
} }
.lc-panel { .lc-panel {
height: 100%; height: 100%;
@ -155,87 +163,86 @@ body {
*/ */
/*覆盖旧面板*/ /*覆盖旧面板*/
/*组件面板*/ /*组件面板*/
.ve-component-list { // .ve-component-list {
.ve-component-list-body{ // .ve-component-list-body{
.ve-component-list-sidebar{ // .ve-component-list-sidebar{
.ve-component-list-navigator{ // .ve-component-list-navigator{
.navigator-group{ // .navigator-group{
&:last-child{ // &:last-child{
&::after{ // &::after{
display: none; // display: none;
} // }
} // }
&::after{ // &::after{
content: ''; // content: '';
display: block; // display: block;
height: 1px; // height: 1px;
background-color: #EDEFF3; // background-color: #EDEFF3;
line-height: 0; // line-height: 0;
margin: 4px 12px 0; // margin: 4px 12px 0;
} // }
.navigator-group-head{ // .navigator-group-head{
.navigator-group-title{ // .navigator-group-title{
border-bottom: none; // border-bottom: none;
} // }
} // }
.navigator-group-item{ // .navigator-group-item{
border-left: 2px solid transparent; // border-left: 2px solid transparent;
&.active{ // &.active{
border-left-color: #0079f2; // border-left-color: #0079f2;
border-right: none; // border-right: none;
} // }
} // }
} // }
} // }
} // }
} // }
} // }
/*数据源*/ /*数据源*/
.engine-datapool{ // .engine-datapool{
.engine-datapool-view-group{ // .engine-datapool-view-group{
padding-top: 48px; // padding-top: 48px;
.engine-datapool-view-group-title{ // .engine-datapool-view-group-title{
height: 48px; // height: 48px;
line-height: 48px; // line-height: 48px;
font-size: 16px; // font-size: 16px;
background-color: transparent; // background-color: transparent;
padding: 0 16px; // padding: 0 16px;
border-bottom: 1px solid #EDEFF3; // border-bottom: 1px solid #EDEFF3;
} // }
} // }
} // }
/*动作面板*/ /*动作面板*/
.ve-action-pane{ // .ve-action-pane{
border-top: none; // border-top: none;
.rc-tabs{ // .rc-tabs{
.rc-tabs-bar{ // .rc-tabs-bar{
background-color: transparent; // background-color: transparent;
.rc-tabs-tab{ // .rc-tabs-tab{
line-height: 1; // line-height: 1;
&.rc-tabs-tab-active{ // &.rc-tabs-tab-active{
} // }
} // }
} // }
} // }
} // }
}
.my-dock { /*设置面板*/
padding: 0px 10px; // .ve-field .ve-field-head,
cursor: pointer; // .ve-field.ve-accordion2-field > .ve-field-head .ve-field-title-content{
align-self: stretch; // padding: 0;
display: flex; // }
align-items: center; // .ve-field.ve-accordion2-field > .ve-field-split-line{
.my-title-label { // display: none;
user-select: none; // }
} // .vs-style .vs-style-source{
&.actived, &:hover { // margin: 0 0 16px;
background-color: var(--pane-title-bg-color); // }
.my-title { // .vs-code-button,
color: var(--color-actived); // .vs-json-button{
} // margin: 0;
} // }
} }
@ -250,7 +257,7 @@ body {
width: 100%; width: 100%;
display: flex; display: flex;
margin-bottom: 2px; margin-bottom: 2px;
padding: 8px; padding: 8px 12px 8px 16px;
.lc-top-area-center{ .lc-top-area-center{
flex: 1; flex: 1;
@ -306,7 +313,6 @@ body {
align-items: center; align-items: center;
// background: rgba(31,56,88,0.04); // background: rgba(31,56,88,0.04);
border-bottom: 1px solid #EDEFF3; border-bottom: 1px solid #EDEFF3;
margin-top: 48px;
.lc-tab-title{ .lc-tab-title{
flex: 1; flex: 1;
height: 32px; height: 32px;
@ -315,14 +321,16 @@ body {
justify-content: center; justify-content: center;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
cursor: pointer; cursor: pointer;
&.actived{ font-size: 12px;
&.actived {
color: #0079F2;
border-bottom-color: #0079F2; border-bottom-color: #0079F2;
} }
} }
} }
.lc-tabs-content { .lc-tabs-content {
position: absolute; position: absolute;
top: 80px; top: 32px;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
@ -346,23 +354,23 @@ body {
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
.lc-title{ .lc-title {
padding: 12px;
flex-direction: column; flex-direction: column;
width: 46px; width: 46px;
height: 46px; height: 46px;
display: flex;
align-items: center;
justify-content: center;
svg { &.has-tip {
// fill: var(--color-icon-normal,rgba(31,56,88,.4));
}
&.has-tip{
cursor: pointer; cursor: pointer;
} }
&.actived{ &.actived{
color: #0079F2; color: #0079F2;
} }
.lc-title-icon{ .lc-title-icon {
height: 20px;
width: 20px;
margin: 0; margin: 0;
.next-icon:before { .next-icon:before {
line-height: 1 !important; line-height: 1 !important;

View File

@ -59,14 +59,14 @@ export default class PanelDock implements IWidget {
this.id = uniqueId(`dock:${name}$`); this.id = uniqueId(`dock:${name}$`);
this.panelName = config.panelName || name; this.panelName = config.panelName || name;
if (content) { if (content) {
const _panelProps: any = { ...panelProps };
if (_panelProps.title == null && props) {
_panelProps.title = composeTitle(props.title, undefined, props.description, true, true);
}
this._panel = this.skeleton.add({ this._panel = this.skeleton.add({
type: "Panel", type: "Panel",
name: this.panelName, name: this.panelName,
props: { props: _panelProps,
// FIXME! give default title for panel
title: props ? composeTitle(props?.title, props?.icon, props?.description, true) : '',
...panelProps,
},
contentProps, contentProps,
content, content,
area: panelProps?.area area: panelProps?.area

View File

@ -62,6 +62,9 @@ export default class Panel implements IWidget {
this.plain = hideTitleBar || !title; this.plain = hideTitleBar || !title;
this.help = help; this.help = help;
if (Array.isArray(content)) { if (Array.isArray(content)) {
if (content.length === 1) {
// todo: not show tabs
}
this.container = this.skeleton.createContainer( this.container = this.skeleton.createContainer(
name, name,
(item) => { (item) => {

View File

@ -1,7 +1,7 @@
import { IconType, TitleContent, isI18nData, TipContent } from '@ali/lowcode-types'; import { IconType, TitleContent, isI18nData, TipContent, isTitleConfig } from '@ali/lowcode-types';
import { isValidElement } from 'react'; import { isValidElement } from 'react';
export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean) { export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean, noIcon?: boolean) {
if (!title) { if (!title) {
title = {}; title = {};
if (!icon || tipAsTitle) { if (!icon || tipAsTitle) {
@ -11,6 +11,19 @@ export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipCon
} }
if (icon || tip) { if (icon || tip) {
if (typeof title !== 'object' || isValidElement(title) || isI18nData(title)) { if (typeof title !== 'object' || isValidElement(title) || isI18nData(title)) {
if (isValidElement(title)) {
if (title.type === 'svg' || (title.type as any).getIcon) {
if (!icon) {
icon = title as any;
}
if (tipAsTitle) {
title = tip as any;
tip = null;
} else {
title = undefined;
}
}
}
title = { title = {
label: title, label: title,
icon, icon,
@ -24,5 +37,8 @@ export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipCon
}; };
} }
} }
if (isTitleConfig(title) && noIcon) {
title.icon = undefined;
}
return title; return title;
} }

View File

@ -1,12 +1,12 @@
import Pane from './views/pane'; import Pane from './views/pane';
import { IconOutline } from './icons/outline'; import { IconOutline } from './icons/outline';
import { intl } from './locale'; import { intlNode } from './locale';
export default { export default {
name: 'outline-pane', name: 'outline-pane',
props: { props: {
icon: IconOutline, icon: IconOutline,
description: intl('Outline Tree'), description: intlNode('Outline Tree'),
}, },
content: Pane, content: Pane,
}; };

View File

@ -1,5 +1,5 @@
import { ReactElement, ReactNode } from 'react'; import { ReactElement, ReactNode } from 'react';
import { I18nData } from './i18n'; import { I18nData, isI18nData } from './i18n';
import { TipContent } from './tip'; import { TipContent } from './tip';
import { IconType } from './icon'; import { IconType } from './icon';
@ -13,6 +13,14 @@ export interface TitleConfig {
export type TitleContent = string | I18nData | ReactElement | TitleConfig; export type TitleContent = string | I18nData | ReactElement | TitleConfig;
export function isTitleConfig(obj: any): obj is TitleConfig { function isPlainObject(value: any): value is object {
return obj && (obj.label || obj.tip || obj.icon); if (typeof value !== 'object') {
return false;
}
const proto = Object.getPrototypeOf(value);
return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null;
}
export function isTitleConfig(obj: any): obj is TitleConfig {
return isPlainObject(obj) && !isI18nData(obj);
} }

View File

@ -1,6 +1,6 @@
import { isObject } from './is-object'; import { isObject } from './is-object';
export function isPlainObject(value: any) { export function isPlainObject(value: any): value is object {
if (!isObject(value)) { if (!isObject(value)) {
return false; return false;
} }