mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-01 19:58:15 +08:00
updates...
This commit is contained in:
parent
03da153052
commit
61796cbc27
@ -27,6 +27,7 @@
|
||||
"beautiful-react-hooks": "^0.35.0",
|
||||
"constate": "^3.3.0",
|
||||
"lodash": "^4.17.21",
|
||||
"monaco-editor": "^0.25.2",
|
||||
"react-dnd": "^14.0.2",
|
||||
"react-dnd-html5-backend": "^14.0.0",
|
||||
"react-dnd-preview": "^6.0.2",
|
||||
|
@ -1,51 +0,0 @@
|
||||
import React from 'react';
|
||||
import { createFromIconfontCN } from '@ant-design/icons';
|
||||
import * as antIcons from '@ant-design/icons';
|
||||
|
||||
export const IconFont = createFromIconfontCN({
|
||||
scriptUrl: ['//at.alicdn.com/t/font_2261954_u9jzwc44ug.js'],
|
||||
});
|
||||
|
||||
export const icons = new Map<string, any>();
|
||||
|
||||
export function registerIcon(type: string, icon: any = IconFont) {
|
||||
icons.set(type.toLowerCase(), icon);
|
||||
}
|
||||
|
||||
export function hasIcon(type: string) {
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
return icons.has(type.toLowerCase());
|
||||
}
|
||||
|
||||
export function registerIcons(components) {
|
||||
Object.keys(components).forEach((type) => {
|
||||
registerIcon(type, components[type]);
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(antIcons).forEach((name) => {
|
||||
if (name.endsWith('Outlined')) {
|
||||
registerIcon(name, antIcons[name]);
|
||||
}
|
||||
});
|
||||
|
||||
interface IconProps {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export function Icon(props: IconProps) {
|
||||
const { type = '', ...restProps } = props;
|
||||
if (type && icons.has(type.toLowerCase())) {
|
||||
const IconComponent = icons.get(type.toLowerCase());
|
||||
if (IconComponent === IconFont) {
|
||||
return <IconFont type={type} />;
|
||||
}
|
||||
return <IconComponent {...restProps} />;
|
||||
}
|
||||
return <IconFont type={type} />;
|
||||
}
|
||||
|
||||
export default Icon;
|
@ -0,0 +1,50 @@
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
import { SchemaRenderer, useDesignable, useSchema } from '..';
|
||||
import { uid } from '@formily/shared';
|
||||
|
||||
const Hello = () => {
|
||||
return <div>Hello</div>;
|
||||
};
|
||||
|
||||
const AddNew = () => {
|
||||
const { schema, refresh, insertBefore } = useDesignable();
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
insertBefore({
|
||||
type: 'void',
|
||||
'x-component': 'Hello',
|
||||
});
|
||||
refresh();
|
||||
console.log({ schema });
|
||||
}}
|
||||
>
|
||||
Add New
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaRenderer
|
||||
debug={true}
|
||||
components={{ Hello, AddNew }}
|
||||
schema={{
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
type: 'void',
|
||||
'x-component': 'Hello',
|
||||
},
|
||||
addnew: {
|
||||
type: 'void',
|
||||
'x-component': 'AddNew',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
1
packages/client/src/components/schema-renderer/index.md
Normal file
1
packages/client/src/components/schema-renderer/index.md
Normal file
@ -0,0 +1 @@
|
||||
<code src="./demos/demo1.tsx"/>
|
@ -1,46 +1,51 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { createForm } from '@formily/core';
|
||||
import {
|
||||
Field,
|
||||
ISchema,
|
||||
observer,
|
||||
Schema,
|
||||
createSchemaField,
|
||||
FormProvider,
|
||||
useField,
|
||||
ISchema,
|
||||
Schema,
|
||||
SchemaOptionsContext,
|
||||
useFieldSchema,
|
||||
useForm,
|
||||
SchemaOptionsContext,
|
||||
} from '@formily/react';
|
||||
import { observable } from '@formily/reactive';
|
||||
import { uid, clone } from '@formily/shared';
|
||||
import { uid } from '@formily/shared';
|
||||
import constate from 'constate';
|
||||
import { get } from 'lodash';
|
||||
import React, { createContext } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { CodeOutlined } from '@ant-design/icons';
|
||||
import Editor from '@monaco-editor/react';
|
||||
|
||||
import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd';
|
||||
|
||||
import { Space, Card, Modal, Spin } from 'antd';
|
||||
import { Action, useLogin, useRegister, useSubmit, useDesignableValues } from '../action';
|
||||
import { AddNew } from '../add-new';
|
||||
import { Cascader } from '../cascader';
|
||||
import { Checkbox } from '../checkbox';
|
||||
import { ColorSelect } from '../color-select';
|
||||
import { DatabaseField } from '../database-field';
|
||||
import { DatePicker } from '../date-picker';
|
||||
import { Filter } from '../filter';
|
||||
import { Form } from '../form';
|
||||
import { Grid } from '../grid';
|
||||
import { IconPicker } from '../icon-picker';
|
||||
import { Input } from '../input';
|
||||
import { InputNumber } from '../input-number';
|
||||
import { Markdown } from '../markdown';
|
||||
import { Menu } from '../menu';
|
||||
import { Password } from '../password';
|
||||
import { Radio } from '../radio';
|
||||
import { Select } from '../select';
|
||||
import {
|
||||
Action,
|
||||
useLogin,
|
||||
useRegister,
|
||||
useSubmit,
|
||||
useDesignableValues,
|
||||
} from '../../schemas/action';
|
||||
import { AddNew } from '../../schemas/add-new';
|
||||
import { Cascader } from '../../schemas/cascader';
|
||||
import { Checkbox } from '../../schemas/checkbox';
|
||||
import { ColorSelect } from '../../schemas/color-select';
|
||||
import { DatabaseField } from '../../schemas/database-field';
|
||||
import { DatePicker } from '../../schemas/date-picker';
|
||||
import { Filter } from '../../schemas/filter';
|
||||
import { Form } from '../../schemas/form';
|
||||
import { Grid } from '../../schemas/grid';
|
||||
import { IconPicker } from '../../schemas/icon-picker';
|
||||
import { Input } from '../../schemas/input';
|
||||
import { InputNumber } from '../../schemas/input-number';
|
||||
import { Markdown } from '../../schemas/markdown';
|
||||
import { Menu } from '../../schemas/menu';
|
||||
import { Password } from '../../schemas/password';
|
||||
import { Radio } from '../../schemas/radio';
|
||||
import { Select } from '../../schemas/select';
|
||||
import {
|
||||
Table,
|
||||
useTableRow,
|
||||
@ -48,23 +53,25 @@ import {
|
||||
useTableUpdateAction,
|
||||
useTableDestroyAction,
|
||||
useTableFilterAction,
|
||||
} from '../table';
|
||||
import { Tabs } from '../tabs';
|
||||
import { TimePicker } from '../time-picker';
|
||||
import { Upload } from '../upload';
|
||||
import { FormItem } from '../form-item';
|
||||
import { BlockItem } from '../block-item';
|
||||
import { DragAndDrop } from '../drag-and-drop';
|
||||
|
||||
import { CodeOutlined } from '@ant-design/icons';
|
||||
import Editor from '@monaco-editor/react';
|
||||
import { get } from 'lodash';
|
||||
} from '../../schemas/table';
|
||||
import { Tabs } from '../../schemas/tabs';
|
||||
import { TimePicker } from '../../schemas/time-picker';
|
||||
import { Upload } from '../../schemas/upload';
|
||||
import { FormItem } from '../../schemas/form-item';
|
||||
import { BlockItem } from '../../schemas/block-item';
|
||||
import { DragAndDrop } from '../../schemas/drag-and-drop';
|
||||
|
||||
export const BlockContext = createContext({ dragRef: null });
|
||||
|
||||
const Div = (props) => <div {...props} />;
|
||||
|
||||
export const scope = {
|
||||
interface DesignableContextProps {
|
||||
schema?: Schema;
|
||||
refresh?: any;
|
||||
}
|
||||
|
||||
export const SchemaField = createSchemaField({
|
||||
scope: {
|
||||
useLogin,
|
||||
useRegister,
|
||||
useSubmit,
|
||||
@ -74,9 +81,8 @@ export const scope = {
|
||||
useTableRow,
|
||||
useTableUpdateAction,
|
||||
useDesignableValues,
|
||||
};
|
||||
|
||||
export const components = {
|
||||
},
|
||||
components: {
|
||||
Card,
|
||||
Div,
|
||||
Space,
|
||||
@ -112,30 +118,16 @@ export const components = {
|
||||
Tabs,
|
||||
TimePicker,
|
||||
Upload,
|
||||
};
|
||||
|
||||
export function registerScope(scopes) {
|
||||
Object.keys(scopes).forEach((key) => {
|
||||
scope[key] = scopes[key];
|
||||
});
|
||||
}
|
||||
|
||||
export function registerComponents(values) {
|
||||
Object.keys(values).forEach((key) => {
|
||||
components[key] = values[key];
|
||||
});
|
||||
}
|
||||
|
||||
export interface DesignableContextProps {
|
||||
schema: Schema;
|
||||
refresh: () => void;
|
||||
}
|
||||
|
||||
export const DesignableContext = createContext<DesignableContextProps>({
|
||||
schema: null,
|
||||
refresh: null,
|
||||
},
|
||||
});
|
||||
|
||||
export const DesignableContext = createContext<DesignableContextProps>(null);
|
||||
|
||||
export function useSchema(path?: any) {
|
||||
const { schema, refresh } = useContext(DesignableContext);
|
||||
return { schema, refresh };
|
||||
}
|
||||
|
||||
export function pathToArray(path): string[] {
|
||||
if (Array.isArray(path)) {
|
||||
return [...path];
|
||||
@ -188,13 +180,16 @@ export function addPropertyAfter(target: Schema, data: ISchema) {
|
||||
export function useDesignable(path?: any) {
|
||||
const { schema, refresh } = useContext(DesignableContext);
|
||||
const schemaPath = path || useSchemaPath();
|
||||
const currentSchema = findPropertyByPath(schema, schemaPath) || ({} as Schema);
|
||||
console.log('useDesignable', { schema, schemaPath, currentSchema });
|
||||
const fieldSchema = useFieldSchema();
|
||||
const currentSchema =
|
||||
findPropertyByPath(schema, schemaPath) || ({} as Schema);
|
||||
// console.log('useDesignable', { schema, schemaPath, currentSchema });
|
||||
const options = useContext(SchemaOptionsContext);
|
||||
const DesignableBar = get(options.components, currentSchema['x-designable-bar']) || (() => null);
|
||||
const DesignableBar =
|
||||
get(options.components, currentSchema['x-designable-bar']) || (() => null);
|
||||
return {
|
||||
DesignableBar,
|
||||
schema: currentSchema,
|
||||
schema: currentSchema || fieldSchema,
|
||||
refresh,
|
||||
prepend: (property: ISchema, targetPath?: any): Schema => {
|
||||
let target = currentSchema;
|
||||
@ -218,7 +213,7 @@ export function useDesignable(path?: any) {
|
||||
current.parent.removeProperty(current.name);
|
||||
properties[current.name] = current.toJSON();
|
||||
});
|
||||
console.log({ properties }, target.properties);
|
||||
// console.log({ properties }, target.properties);
|
||||
target.setProperties(properties);
|
||||
refresh();
|
||||
return target.properties[property.name];
|
||||
@ -331,7 +326,7 @@ export function getSchemaPath(schema: Schema) {
|
||||
path.unshift(parent.name);
|
||||
parent = parent.parent;
|
||||
}
|
||||
console.log('getSchemaPath', path, schema);
|
||||
// console.log('getSchemaPath', path, schema);
|
||||
return [...path];
|
||||
}
|
||||
|
||||
@ -341,38 +336,6 @@ export function useSchemaPath() {
|
||||
return [...path];
|
||||
}
|
||||
|
||||
console.log({ scope, components });
|
||||
|
||||
export const createDesignableSchemaField = (options) => {
|
||||
const SchemaField = createSchemaField(options);
|
||||
|
||||
const DesignableSchemaField = (props) => {
|
||||
|
||||
const schema = useMemo(() => new Schema(props.schema), [props.schema]);
|
||||
const [, refresh] = useState(0);
|
||||
if (props.designable === false) {
|
||||
return <SchemaField schema={schema} />;
|
||||
}
|
||||
return (
|
||||
<DesignableContext.Provider
|
||||
value={{
|
||||
schema,
|
||||
refresh: () => {
|
||||
refresh(Math.random());
|
||||
props.onRefresh && props.onRefresh(schema);
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SchemaField scope={props.scope} components={props.components} schema={schema} />
|
||||
{props.debug && <CodePreview schema={schema} />}
|
||||
{props.debug && <FormValues />}
|
||||
</DesignableContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
return DesignableSchemaField;
|
||||
};
|
||||
|
||||
const FormValues = () => {
|
||||
const form = useForm();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -400,7 +363,10 @@ const CodePreview = ({ schema }) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<CodeOutlined style={{position: 'relative', zIndex: 100}} onClick={() => setVisible(true)} />
|
||||
<CodeOutlined
|
||||
style={{ position: 'relative', zIndex: 100 }}
|
||||
onClick={() => setVisible(true)}
|
||||
/>
|
||||
<Modal
|
||||
width={'50%'}
|
||||
onOk={() => setVisible(false)}
|
||||
@ -418,31 +384,25 @@ const CodePreview = ({ schema }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const SchemaField = createSchemaField({
|
||||
scope,
|
||||
components,
|
||||
});
|
||||
|
||||
export const DesignableSchemaField = createDesignableSchemaField({
|
||||
scope,
|
||||
components,
|
||||
});
|
||||
|
||||
export interface SchemaRendererProps {
|
||||
schema: ISchema;
|
||||
schema: Schema | ISchema;
|
||||
form?: any;
|
||||
designable?: boolean;
|
||||
onRefresh?: any;
|
||||
onlyRenderProperties?: boolean;
|
||||
scope?: any;
|
||||
render?: any;
|
||||
components?: any;
|
||||
scope?: any;
|
||||
debug?: boolean;
|
||||
onlyRenderProperties?: boolean;
|
||||
onRefresh?: any;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export const SchemaRenderer = (props: SchemaRendererProps) => {
|
||||
const form = useMemo(() => props.form || createForm({}), []);
|
||||
|
||||
const [, refresh] = useState(uid());
|
||||
const form = useMemo(() => props.form || createForm(), []);
|
||||
const schema = useMemo(() => {
|
||||
if (Schema.isSchemaInstance(props.schema)) {
|
||||
return schema;
|
||||
}
|
||||
let s = props.schema;
|
||||
if (props.onlyRenderProperties) {
|
||||
s = {
|
||||
@ -457,21 +417,32 @@ export const SchemaRenderer = (props: SchemaRendererProps) => {
|
||||
},
|
||||
};
|
||||
}
|
||||
return s;
|
||||
return new Schema(s);
|
||||
}, []);
|
||||
|
||||
console.log('SchemaRenderer', schema, props.schema);
|
||||
|
||||
return (
|
||||
const defaultRender = ({ schema }) => (
|
||||
<FormProvider form={form}>
|
||||
<DesignableSchemaField
|
||||
debug={props.debug}
|
||||
scope={props.scope}
|
||||
<SchemaField
|
||||
components={props.components}
|
||||
onRefresh={props.onRefresh}
|
||||
designable={props.designable}
|
||||
scope={props.scope}
|
||||
schema={schema}
|
||||
/>
|
||||
{props.debug && <CodePreview schema={schema} />}
|
||||
{props.debug && <FormValues />}
|
||||
</FormProvider>
|
||||
);
|
||||
return (
|
||||
<DesignableContext.Provider
|
||||
value={{
|
||||
schema,
|
||||
refresh: () => {
|
||||
props.onRefresh && props.onRefresh(schema);
|
||||
refresh(uid());
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DesignableContext.Consumer>
|
||||
{props.render || defaultRender}
|
||||
</DesignableContext.Consumer>
|
||||
</DesignableContext.Provider>
|
||||
);
|
||||
};
|
30
packages/client/src/schemas/action/demos/demo1.tsx
Normal file
30
packages/client/src/schemas/action/demos/demo1.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* title: 按钮操作
|
||||
* desc: 可以通过配置 `useAction` 来处理操作逻辑
|
||||
*/
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import { SchemaRenderer } from '@nocobase/client';
|
||||
|
||||
function useAction() {
|
||||
return {
|
||||
run() {
|
||||
alert('这是自定义的操作逻辑');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Action.DesignableBar',
|
||||
'x-component-props': {
|
||||
useAction: '{{ useAction }}',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer debug={true} scope={{ useAction }} schema={schema} />;
|
||||
};
|
16
packages/client/src/schemas/action/demos/demo2.tsx
Normal file
16
packages/client/src/schemas/action/demos/demo2.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '@nocobase/client';
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component-props': {
|
||||
to: 'abc',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />;
|
||||
};
|
16
packages/client/src/schemas/action/demos/demo3.tsx
Normal file
16
packages/client/src/schemas/action/demos/demo3.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '@nocobase/client';
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action.URL',
|
||||
'x-component-props': {
|
||||
url: 'https://www.nocobase.com/',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />;
|
||||
};
|
92
packages/client/src/schemas/action/demos/demo4.tsx
Normal file
92
packages/client/src/schemas/action/demos/demo4.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '@nocobase/client';
|
||||
|
||||
function useAction() {
|
||||
return {
|
||||
run() {
|
||||
alert('这是自定义的操作逻辑');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '下拉菜单',
|
||||
'x-component': 'Action.Dropdown',
|
||||
properties: {
|
||||
action1: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction,
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
type: 'void',
|
||||
title: 'Drawer 按钮',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '抽屉标题',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
action2: {
|
||||
type: 'void',
|
||||
title: '打开二级抽屉',
|
||||
// 'x-decorator': 'FormItem',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '二级抽屉标题',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
action3: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: 'Popover 按钮',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
popover1: {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-component': 'Action.Popover',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />;
|
||||
};
|
@ -77,180 +77,19 @@ group:
|
||||
|
||||
### Action - 常规操作
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* title: 按钮操作
|
||||
* desc: 可以通过配置 `useAction` 来处理操作逻辑
|
||||
*/
|
||||
import React from 'react';
|
||||
import { SchemaRenderer, registerScope } from '../';
|
||||
|
||||
function useAction() {
|
||||
return {
|
||||
run() {
|
||||
alert('这是自定义的操作逻辑');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Action.DesignableBar',
|
||||
'x-component-props': {
|
||||
useAction: '{{ useAction }}',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer debug={true} scope={{ useAction }} schema={schema} />
|
||||
}
|
||||
```
|
||||
<code src="./demos/demo1.tsx">
|
||||
|
||||
### Action.Link - 内链跳转
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '../';
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component-props': {
|
||||
to: 'abc',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />
|
||||
}
|
||||
```
|
||||
<code src="./demos/demo2.tsx">
|
||||
|
||||
### Action.URL - 外链跳转
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '../';
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action.URL',
|
||||
'x-component-props': {
|
||||
url: 'https://www.nocobase.com/',
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />
|
||||
}
|
||||
```
|
||||
<code src="./demos/demo3.tsx">
|
||||
|
||||
### Action.Dropdown - 下拉操作
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { SchemaRenderer } from '../';
|
||||
|
||||
function useAction() {
|
||||
return {
|
||||
run() {
|
||||
alert('这是自定义的操作逻辑');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const popoverSchema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
popover1: {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-component': 'Action.Popover',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const drawerSchema = {
|
||||
type: 'void',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '抽屉标题',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
action2: {
|
||||
type: 'void',
|
||||
title: '打开二级抽屉',
|
||||
// 'x-decorator': 'FormItem',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '二级抽屉标题',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '下拉菜单',
|
||||
'x-component': 'Action.Dropdown',
|
||||
properties: {
|
||||
action1: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction,
|
||||
},
|
||||
},
|
||||
action2: drawerSchema,
|
||||
action3: popoverSchema,
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />
|
||||
}
|
||||
```
|
||||
<code src="./demos/demo4.tsx">
|
||||
|
||||
### Action.Popover - 打开气泡
|
||||
|
||||
@ -288,9 +127,10 @@ export default () => {
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Space } from 'antd';
|
||||
import { SchemaRenderer } from '../';
|
||||
|
||||
const schema = {
|
||||
const schema1 = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '按钮',
|
||||
@ -332,8 +172,40 @@ const schema = {
|
||||
},
|
||||
};
|
||||
|
||||
const schema2 = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: 'x-decorator=Form',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
// footer: null,
|
||||
},
|
||||
'x-decorator': 'Form',
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
title: '输入框',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return <SchemaRenderer schema={schema} />
|
||||
return (
|
||||
<Space>
|
||||
<SchemaRenderer schema={schema1} />
|
||||
<SchemaRenderer schema={schema2} />
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@ -367,7 +239,9 @@ const schema = {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-component': 'Action.Modal',
|
||||
'x-component-props': {},
|
||||
'x-component-props': {
|
||||
// footer: null,
|
||||
},
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
@ -418,7 +292,9 @@ const schema2 = {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-component': 'Action.Modal',
|
||||
'x-component-props': {},
|
||||
'x-component-props': {
|
||||
// footer: null,
|
||||
},
|
||||
'x-decorator': 'Form',
|
||||
properties: {
|
||||
input: {
|
||||
|
@ -86,24 +86,18 @@ export type ActionType = React.FC<ActionProps> & {
|
||||
DesignableBar?: React.FC<any>;
|
||||
};
|
||||
|
||||
function Blank() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function useDesignableBar() {
|
||||
const schema = useFieldSchema();
|
||||
const options = useContext(SchemaOptionsContext);
|
||||
const DesignableBar = get(options.components, schema['x-designable-bar']);
|
||||
|
||||
return {
|
||||
DesignableBar: DesignableBar || Blank,
|
||||
DesignableBar: DesignableBar || (() => null),
|
||||
};
|
||||
}
|
||||
|
||||
const [VisibleProvider, useVisibleContext] = constate((props: any = {}) => {
|
||||
const { initialVisible = false, containerRef = null } = props;
|
||||
const [visible, setVisible] = useState(initialVisible);
|
||||
|
||||
return { containerRef, visible, setVisible };
|
||||
});
|
||||
|
||||
@ -123,6 +117,7 @@ const BaseAction = observer((props: any) => {
|
||||
const { setVisible } = useVisibleContext();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { schema } = useDesignable();
|
||||
|
||||
useEffect(() => {
|
||||
field.componentProps.setVisible = setVisible;
|
||||
}, []);
|
||||
@ -130,7 +125,7 @@ const BaseAction = observer((props: any) => {
|
||||
const renderButton = () => (
|
||||
<ButtonComponent
|
||||
{...others}
|
||||
icon={<Icon type={icon} />}
|
||||
icon={icon ? <Icon type={icon} /> : null}
|
||||
className={classNames(className, `name-${schema.name}`)}
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation && e.stopPropagation();
|
||||
@ -237,13 +232,29 @@ Action.Drawer = observer((props) => {
|
||||
const { visible, setVisible } = useVisibleContext();
|
||||
const { run } = useAction();
|
||||
const form = useForm();
|
||||
console.log(`schema['x-decorator']`, schema['x-decorator'])
|
||||
console.log(`schema['x-decorator']`, schema['x-decorator']);
|
||||
if (schema['x-decorator'] === 'Form.Decorator') {
|
||||
Object.assign(others, {
|
||||
footer: (
|
||||
<Space>
|
||||
<Button type={'primary'}>Ok</Button>
|
||||
<Button>Cancel</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
await form.submit();
|
||||
await run();
|
||||
setVisible(false);
|
||||
}}
|
||||
type={'primary'}
|
||||
>
|
||||
OK
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
form.clearErrors();
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
});
|
||||
@ -258,8 +269,10 @@ Action.Drawer = observer((props) => {
|
||||
width={'50%'}
|
||||
{...others}
|
||||
visible={visible}
|
||||
destroyOnClose
|
||||
onClose={(e) => {
|
||||
e.stopPropagation();
|
||||
form.clearErrors();
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
@ -273,8 +286,6 @@ const [DesignableContextProvider, useDesignableContext] = constate(() => {
|
||||
});
|
||||
|
||||
import { DesignableBar } from './designableBar';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { clone } from '@formily/shared';
|
||||
|
||||
export function useDesignableValues() {
|
||||
const { schema } = useDesignableContext();
|
||||
@ -313,7 +324,11 @@ Action.Modal = observer((props) => {
|
||||
const { visible, setVisible } = useVisibleContext();
|
||||
const { run } = useAction();
|
||||
const form = useForm();
|
||||
if (schema['x-decorator'] !== 'Form.Decorator') {
|
||||
// console.log('Action.Modal', schema['x-component-props'], Object.keys(others).includes('footer'));
|
||||
if (
|
||||
!Object.keys(others).includes('footer') &&
|
||||
schema['x-decorator'] !== 'Form.Decorator'
|
||||
) {
|
||||
Object.assign(others, { footer: null });
|
||||
}
|
||||
return (
|
||||
@ -328,13 +343,13 @@ Action.Modal = observer((props) => {
|
||||
onCancel={async (e) => {
|
||||
e.stopPropagation();
|
||||
setVisible(false);
|
||||
// await form.reset();
|
||||
setDropdownVisible && setDropdownVisible(false);
|
||||
}}
|
||||
onOk={async (e) => {
|
||||
console.log('onOk', form.values);
|
||||
// await form.submit();
|
||||
await run();
|
||||
// e.stopPropagation();
|
||||
setVisible(false);
|
||||
setDropdownVisible && setDropdownVisible(false);
|
||||
}}
|
||||
@ -348,12 +363,13 @@ Action.Modal = observer((props) => {
|
||||
);
|
||||
});
|
||||
|
||||
const [DropdownVisibleProvider, useDropdownVisibleContext] = constate((props: any = {}) => {
|
||||
const [DropdownVisibleProvider, useDropdownVisibleContext] = constate(
|
||||
(props: any = {}) => {
|
||||
const { initialVisible = false } = props;
|
||||
const [visible, setVisible] = useState(initialVisible);
|
||||
|
||||
return { visible, setVisible };
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
const ActionDropdown = observer((props: any) => {
|
||||
const { icon, ...others } = props;
|
||||
@ -371,7 +387,7 @@ const ActionDropdown = observer((props: any) => {
|
||||
content={props.children}
|
||||
placement={'bottomLeft'}
|
||||
>
|
||||
<Button icon={<Icon type={icon} />} {...others}>
|
||||
<Button icon={icon ? <Icon type={icon} /> : null} {...others}>
|
||||
{schema.title}
|
||||
</Button>
|
||||
</Popover>
|
||||
|
@ -46,7 +46,7 @@ import {
|
||||
DownOutlined,
|
||||
DatabaseOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { useDesignable, useSchemaPath } from '../DesignableSchemaField';
|
||||
import { useDesignable, useSchemaPath } from '../';
|
||||
import { uid } from '@formily/shared';
|
||||
|
||||
const generateGridBlock = (schema: ISchema) => {
|
||||
|
@ -16,7 +16,7 @@ import './style.less';
|
||||
import get from 'lodash/get';
|
||||
import { GridBlockContext } from '../grid';
|
||||
import { uid } from '@formily/shared';
|
||||
import { useDesignable, useSchemaPath } from '../DesignableSchemaField';
|
||||
import { useDesignable, useSchemaPath } from '../';
|
||||
import { AddNew } from '../add-new';
|
||||
import { Card } from 'antd';
|
||||
import {
|
||||
|
@ -12,7 +12,7 @@ import { ArrayCollapse } from '@formily/antd';
|
||||
import { uid } from '@formily/shared';
|
||||
import '@formily/antd/lib/form-tab/style';
|
||||
import { Collapse, Button, Dropdown, Menu, Tag } from 'antd';
|
||||
import { interfaces } from './interfaces';
|
||||
import { options, interfaces } from './interfaces';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
|
||||
export const DatabaseField: any = observer((props) => {
|
||||
@ -33,24 +33,11 @@ export const DatabaseField: any = observer((props) => {
|
||||
console.log({ schema });
|
||||
return (
|
||||
<Collapse.Panel
|
||||
// extra={[
|
||||
// <Button onClick={() => field.moveUp(index)}>Up</Button>,
|
||||
// <Button
|
||||
// onClick={() => {
|
||||
// field.remove(index);
|
||||
// field.insert(index, {
|
||||
// ...item,
|
||||
// interface: 'textarea',
|
||||
// });
|
||||
// }}
|
||||
// >
|
||||
// Update
|
||||
// </Button>,
|
||||
// ]}
|
||||
header={
|
||||
<>
|
||||
{(item.ui && item.ui.title) || <i style={{color: 'rgba(0, 0, 0, 0.25)'}}>未命名</i>}{' '}
|
||||
<Tag>{schema.title}</Tag>
|
||||
<span style={{ color: 'rgba(0, 0, 0, 0.25)', fontSize: 14 }}>{item.name}</span>
|
||||
</>
|
||||
}
|
||||
extra={[
|
||||
@ -100,18 +87,24 @@ export const DatabaseField: any = observer((props) => {
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
...schema.default,
|
||||
id: uid(),
|
||||
name: uid(),
|
||||
interface: info.key,
|
||||
...schema.default,
|
||||
};
|
||||
field.push(data);
|
||||
setActiveKey(data.id);
|
||||
console.log('info.key', info.key, schema);
|
||||
}}
|
||||
>
|
||||
{Array.from(interfaces).map(([key, schema]) => (
|
||||
<Menu.Item key={key}>{schema.title}</Menu.Item>
|
||||
{options.map(option => (
|
||||
<Menu.ItemGroup title={option.label}>
|
||||
{
|
||||
option.children.map(item => (
|
||||
<Menu.Item key={item.name}>{item.title}</Menu.Item>
|
||||
))
|
||||
}
|
||||
</Menu.ItemGroup>
|
||||
))}
|
||||
</Menu>
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { set } from 'lodash';
|
||||
|
||||
import { select } from './select';
|
||||
import { string } from './string';
|
||||
@ -7,7 +8,33 @@ import { textarea } from './textarea';
|
||||
|
||||
export const interfaces = new Map<string, ISchema>();
|
||||
|
||||
interfaces.set('select', select);
|
||||
interfaces.set('string', string);
|
||||
interfaces.set('subTable', subTable);
|
||||
interfaces.set('textarea', textarea);
|
||||
const fields = {};
|
||||
const groupLabels = {};
|
||||
|
||||
export function registerField(group: string, type: string, schema) {
|
||||
fields[group] = fields[group] || {};
|
||||
set(fields, [group, type], schema);
|
||||
interfaces.set(type, schema);
|
||||
}
|
||||
|
||||
export function registerGroupLabel(key: string, label: string) {
|
||||
groupLabels[key] = label;
|
||||
}
|
||||
|
||||
registerField('basic', 'string', string);
|
||||
registerField('basic', 'textarea', textarea);
|
||||
registerField('choices', 'select', select);
|
||||
registerField('relation', 'subTable', subTable);
|
||||
|
||||
registerGroupLabel('basic', '基本类型');
|
||||
registerGroupLabel('choices', '选择类型');
|
||||
registerGroupLabel('relation', '关系类型');
|
||||
|
||||
export const options = Object.keys(fields).map((groupName) => {
|
||||
return {
|
||||
label: groupLabels[groupName],
|
||||
children: Object.keys(fields[groupName]).map((type) => {
|
||||
return fields[groupName][type];
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
|
||||
export const select: ISchema = {
|
||||
name: 'select',
|
||||
type: 'object',
|
||||
title: '下拉选择',
|
||||
group: 'choices',
|
||||
default: {
|
||||
dataType: 'string',
|
||||
// name,
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
|
||||
export const string: ISchema = {
|
||||
name: 'string',
|
||||
type: 'object',
|
||||
title: '单行文本',
|
||||
group: 'basic',
|
||||
default: {
|
||||
dataType: 'string',
|
||||
// name,
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
|
||||
export const subTable: ISchema = {
|
||||
name: 'subTable',
|
||||
type: 'object',
|
||||
title: '子表格',
|
||||
group: 'relation',
|
||||
default: {
|
||||
// name,
|
||||
ui: {
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
|
||||
export const textarea: ISchema = {
|
||||
name: 'textarea',
|
||||
type: 'object',
|
||||
title: '多行文本',
|
||||
group: 'basic',
|
||||
default: {
|
||||
dataType: 'text',
|
||||
// name,
|
||||
|
@ -1,9 +1,5 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
connect,
|
||||
mapProps,
|
||||
mapReadPretty,
|
||||
} from '@formily/react';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { useDynamicList } from 'ahooks';
|
||||
import { Select } from 'antd';
|
||||
|
@ -16,7 +16,7 @@ import { MenuOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import get from 'lodash/get';
|
||||
import { GridBlockContext } from '../grid';
|
||||
import { uid } from '@formily/shared';
|
||||
import { useDesignable } from '../DesignableSchemaField';
|
||||
import { useDesignable } from '../';
|
||||
import { AddNew } from '../add-new';
|
||||
import { BlockItem } from '../block-item';
|
||||
import { DraggableBlockContext } from '../../components/drag-and-drop';
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
FormProvider,
|
||||
ISchema,
|
||||
} from '@formily/react';
|
||||
import { SchemaRenderer, useDesignable } from '../DesignableSchemaField';
|
||||
import { SchemaRenderer, useDesignable } from '../';
|
||||
import get from 'lodash/get';
|
||||
import { Dropdown, Menu } from 'antd';
|
||||
import {
|
||||
@ -56,19 +56,14 @@ export const Form: any = observer((props: any) => {
|
||||
const schema = useFieldSchema();
|
||||
const { schema: designableSchema, refresh } = useDesignable();
|
||||
const formSchema: ISchema = schema['x-decorator'] === 'Form' ? {
|
||||
type: 'void',
|
||||
"x-component": 'Blank',
|
||||
type: 'object',
|
||||
properties: {
|
||||
[schema.name]: {
|
||||
...schema.toJSON(),
|
||||
"x-decorator": 'Form.Decorator',
|
||||
}
|
||||
}
|
||||
} : {
|
||||
...schema.toJSON(),
|
||||
'x-component': 'Form.Blank',
|
||||
'x-component-props': {},
|
||||
};
|
||||
} : schema.toJSON();
|
||||
return (
|
||||
<SchemaRenderer
|
||||
scope={scope}
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
import './style.less';
|
||||
import cls from 'classnames';
|
||||
|
||||
import { useDesignable, useSchemaPath } from '../DesignableSchemaField';
|
||||
import { useDesignable, useSchemaPath } from '../';
|
||||
import {
|
||||
useDrag,
|
||||
useDrop,
|
||||
|
@ -1 +1,2 @@
|
||||
export * from './DesignableSchemaField';
|
||||
// export * from './DesignableSchemaField';
|
||||
export * from '../components/schema-renderer';
|
||||
|
@ -425,6 +425,7 @@ export default () => {
|
||||
<Layout>
|
||||
<Layout.Header>
|
||||
<SchemaRenderer
|
||||
debug={true}
|
||||
schema={schema}
|
||||
scope={{ onSelect, sideMenuRef }}
|
||||
/>
|
||||
|
@ -3,7 +3,6 @@ import { connect, mapReadPretty } from '@formily/react';
|
||||
import { Input } from 'antd';
|
||||
import { PasswordProps } from 'antd/lib/input';
|
||||
import { PasswordStrength } from './PasswordStrength';
|
||||
import { Descriptions } from '../descriptions';
|
||||
|
||||
export interface IPasswordProps extends PasswordProps {
|
||||
checkStrength: boolean;
|
||||
|
@ -14,7 +14,7 @@ import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { SelectProps } from 'antd/lib/select';
|
||||
import { isArr, isValid, toArr } from '@formily/shared';
|
||||
import { useState } from 'react';
|
||||
import { useDesignable } from '../DesignableSchemaField';
|
||||
import { useDesignable } from '../';
|
||||
import { createContext } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { SelectedRowKeysContext, useTableContext } from '../table';
|
||||
|
@ -33,7 +33,7 @@ import {
|
||||
SortableElement,
|
||||
} from 'react-sortable-hoc';
|
||||
import cls from 'classnames';
|
||||
import { getSchemaPath, useDesignable, useSchemaPath } from '../DesignableSchemaField';
|
||||
import { getSchemaPath, useDesignable, useSchemaPath } from '../';
|
||||
import './style.less';
|
||||
|
||||
interface TableRowProps {
|
||||
|
@ -29,8 +29,8 @@ group:
|
||||
import React from 'react';
|
||||
import { Button } from 'antd'
|
||||
import { UploadOutlined, InboxOutlined } from '@ant-design/icons'
|
||||
import { SchemaRenderer } from '../';
|
||||
import Upload from './';
|
||||
import { SchemaRenderer, registerComponents } from '../';
|
||||
|
||||
const NormalUpload = (props) => {
|
||||
return (
|
||||
@ -46,10 +46,6 @@ const NormalUpload = (props) => {
|
||||
)
|
||||
}
|
||||
|
||||
registerComponents({
|
||||
NormalUpload,
|
||||
});
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@ -79,7 +75,7 @@ const schema = {
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaRenderer schema={schema} />
|
||||
<SchemaRenderer components={{ NormalUpload }} schema={schema} />
|
||||
);
|
||||
};
|
||||
```
|
||||
|
@ -12661,6 +12661,11 @@ moment-timezone@^0.5.31:
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||
|
||||
monaco-editor@^0.25.2:
|
||||
version "0.25.2"
|
||||
resolved "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.25.2.tgz#119e2b15bbd968a1a99c03cac9c329316d7c37e9"
|
||||
integrity sha512-5iylzSJevCnzJn9UVsW8yOZ3yHjmAs4TfvH3zsbftKiFKmHG0xirGN6DK9Kk04VSWxYCZZAIafYJoNJJMAU1KA==
|
||||
|
||||
moo@^0.5.0:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4"
|
||||
|
Loading…
Reference in New Issue
Block a user