Skip to content
This repository has been archived by the owner on Sep 10, 2020. It is now read-only.

Latest commit

 

History

History
243 lines (179 loc) · 7.71 KB

README_en-US.md

File metadata and controls

243 lines (179 loc) · 7.71 KB
title path group
Design
component/design
Domain-specific

Example

https://xjh22222228.github.io/micro-design-editor/

Install

npm i micro-design-editor -S

Design

H5 page editor, build your H5 pages in a WYSIWYG way.

API

Property Description Type Default Required
components All available components in Design array [] Yes
value Current value array [] Yes
onChange Callback when value changes func(value: array): void Yes
settings Design settings, will be passed to every Design component object No
onSettingsChange Callback to change settings func No
defaultSelectedIndex Default selected index in value array number -1 No
preview Custom Preview component Component DesingPreview No
previewFooter Custom footer after preview section node No
confirmUnsavedLeave Show a confirm dialog if there're unsaved changes boolean true No
cache Cache unsaved changes to localStorage boolean false No
cacheId Cache id, must be used with cache string Yes if cache is true, No otherwise
cacheRestoreMessage Message to restore cache from localStorage node 提示:在浏览器中发现未提交的内容,是否使用该内容替换当前内容? No
disabled Is Design disabled boolean false No
globalConfig Global config across Design object No
children Additional children inside Design node No
scrollTopOffset Top scroll offset number | func No
scrollLeftOffset Left scroll offset number | func No
className Custom class name string No

components is an array, all available componets should be included in this array. Each item in this array is a component description, here are the possible options.

type Component = {
  // Component type, must be unique
  type: string | string[],
  
  // Default component type
  // If `type` is an array, `defaultType` can be a number
  // If `defaultType` is a function, it will be called with `type` as the sole argument
  defaultType?: number | (string[] | string) => string

  // Component to render preview
  preview: ReactComponent,

  // Component responsible for editing
  editor: ReactComponent,

  // Preview component container 
  previewItem?: ReactComponent,

  // Preview controller, responsible for dnd, select and so on
  previewController?: ReactComponent,

  // Editor component container
  editorItem?: ReactComponent,

  // Is this component dragable?
  dragable?: boolean,

  // Should this component appear in the component list?
  appendable?: boolean,

  // Is this component configurable(add/delete on the bottom right corner)?
  configurable?: boolean,
  
  // show delete button
  canDelete?: boolean,

  // show add button
  canInsert?: boolean,

  // Is this component editable? Only editable components are selectable
  editable?: boolean,

  // Highlight preview when selected
  highlightWhenSelect?: boolean,

  // Maximum number of instances this component can have
  // Zero is no limit
  // If passing a function, return false to stop adding more
  limit?: number | (count: number) => boolean,
  
  // Tooltip when a component reaches its limit
  // If limit is a number, limitMessage has a default value.
  limitMessage?: node | (count: number) => node,
  
  // Callback when adding a new instance for component
  // Add only if Promise resolves.
  shouldCreate?: (comp: Component) => Promise,

  // Additional props passed to editor
  editorProps: (value: object) => object | object,

  // Addtional props passed to preview
  previewProps: (value: object) => object | object
}

Each item in value array must have a type property, Design uses this property to determine why component in component array should be used to render this value.

Design.group

Declaration:group(name: string): object

Design supports component grouping in add component area, all you have to do is insert Desgin.group(groupName) to the right place in your components array.

[
  config,

  Design.group('group1'),
  componentA,
  componentB,

  Design.group('group2'),
  componentC,
  componentD
]

settings and onSettingsChange

You can pass in a settings object and a corresponding onSettingsChange callback. This two props will be pass to every Design component.

There's a predefined setting called previewBackground, Design will use this value as the preview background.

Design Instance Methods

  • design.validate(): Promise, trigger a validation, resolves only if there's no erro.
  • design.markAsSaved(), tell Desgin data has been saved.

How to Implement new Design Component?

Each Desgin component are divided in two parts: Preview and Editor.

Preview is just a component which accepts { value: any, globalConfig: any, design: object } as props and renders a UI with these props.

It is a little bit complex about Editor component. You are recommended to extend the @youzan/design/lib/base/editor/DesignEditor base class, this class has some useful methods you can use(e.g. onChange event handlers).

Editor has these props:

{ value: any, onChange: func, showError: boolean, validation: object, design object }

  • validate(value): Promise You should resolve an error object if there're errors
  • reorder<T>(array: T[], fromIndex: number, toIndex: number): T[] Reorder array after drag
  • props.design There're some useful methods on this prop

A editor component must have these static properties:

designType, designDescription, getInitialValue, validate

You can use react-beautiful-dnd to implement drag-and-drop inside an editor, implement these two functions in your editor: shouldHandleDragEnd(type: string): boolean and onDragEnd(result). Check react-beautiful-dnd's documentation for detailed instructions. There's also a demo in components/image-ad.

Example

// Preview
import React, { PureComponent } from 'react';

export default class NoticePreview extends PureComponent {
  render() {
    const { value } = this.props;

    return (
      <div className="rc-design-component-notice-preview">{value}</div>
    );
  }
}

// Editor
import React from 'react';
import { Input } from 'zent';

import { DesignEditor, ControlGroup } from '@youzan/design/base/editor/DesignEditor';

export const PLACEHOLDER = '请填写内容,如果过长,将会在手机上滚动显示';

export default class NoticeEditor extends DesignEditor {
  render() {
    const { value, showError, validation } = this.props;

    return (
      <div className="rc-design-component-notice-editor">
        <ControlGroup
          label="公告:"
          required
          showError={showError || this.getMetaProperty('content', 'touched')}
          error={validation.content}
        >
          <Input
            name="content"
            placeholder={PLACEHOLDER}
            value={value.content}
            onChange={this.onInputChange}
            onBlur={this.onInputBlur}
          />
        </ControlGroup>
      </div>
    );
  }

  static designType = 'notice';
  static designDescription = '公告';
  static getInitialValue(settings, globalConfig) {
    return {
      content: '',
      scrollable: false
    };
  }

  static validate(value) {
    return new Promise(resolve => {
      const errors = {};
      const { content } = value;
      if (!content || !content.trim()) {
        errors.content = '请填写公告内容';
      }

      resolve(errors);
    });
  }
}

Example code

Example

License

MIT