suanmei
5 years ago
committed by
拾邑
18 changed files with 278 additions and 76 deletions
@ -0,0 +1,94 @@ |
|||
/** @jsx jsx */ |
|||
import { jsx, css } from '@emotion/core'; |
|||
import styled from '@emotion/styled'; |
|||
import { Row, Col, Tooltip, Input, Checkbox, Select } from 'antd'; |
|||
import { useTranslation } from 'react-i18next'; |
|||
import { useUIState, useSetUIState } from '../store/ui'; |
|||
import { |
|||
CaretDownIcon, |
|||
CaretRightIcon, |
|||
EditIcon, |
|||
SettingIcon, |
|||
PlusIcon, |
|||
} from '../utils/styles/common'; |
|||
|
|||
const { Option } = Select; |
|||
|
|||
const FieldInput = styled(Input)` |
|||
.ant-input-group-addon { |
|||
background: transparent; |
|||
border: none; |
|||
} |
|||
`;
|
|||
|
|||
function EditorHead(): JSX.Element { |
|||
const { t } = useTranslation(); |
|||
const uiState = useUIState(); |
|||
const setUIState = useSetUIState(); |
|||
const { formVisible } = uiState; |
|||
|
|||
const toggleFormVisible = (): void => { |
|||
setUIState((prev) => ({ ...prev, formVisible: !formVisible })); |
|||
}; |
|||
|
|||
return ( |
|||
<Row |
|||
css={css` |
|||
margin-top: 10px; |
|||
`}
|
|||
> |
|||
<Col span="24"> |
|||
<Row align="middle"> |
|||
<Col span="8"> |
|||
<Row align="middle"> |
|||
<Col span="2"> |
|||
{formVisible ? ( |
|||
<CaretDownIcon onClick={toggleFormVisible} /> |
|||
) : ( |
|||
<CaretRightIcon onClick={toggleFormVisible} /> |
|||
)} |
|||
</Col> |
|||
<Col span="22"> |
|||
<FieldInput |
|||
disabled |
|||
value="root" |
|||
addonAfter={ |
|||
<Tooltip placement="top" title={t('select_all')}> |
|||
<Checkbox |
|||
checked={false} |
|||
onChange={(): void => { |
|||
// code
|
|||
}} |
|||
/> |
|||
</Tooltip> |
|||
} |
|||
/> |
|||
</Col> |
|||
</Row> |
|||
</Col> |
|||
<Col span="3"> |
|||
<Select value="object" disabled> |
|||
<Option value="object">object</Option> |
|||
</Select> |
|||
</Col> |
|||
<Col span="5"> |
|||
<Input value="" placeholder="Title" addonAfter={<EditIcon />} /> |
|||
</Col> |
|||
<Col span="5"> |
|||
<Input value="" placeholder="Description" addonAfter={<EditIcon />} /> |
|||
</Col> |
|||
<Col span="3"> |
|||
<Tooltip placement="top" title={t('setting')}> |
|||
<SettingIcon /> |
|||
</Tooltip> |
|||
<Tooltip placement="top" title={t('add_child_node')}> |
|||
<PlusIcon /> |
|||
</Tooltip> |
|||
</Col> |
|||
</Row> |
|||
</Col> |
|||
</Row> |
|||
); |
|||
} |
|||
|
|||
export default EditorHead; |
@ -0,0 +1,28 @@ |
|||
/** @jsx jsx */ |
|||
import { jsx, css } from '@emotion/core'; |
|||
import { Button } from 'antd'; |
|||
import { useTranslation } from 'react-i18next'; |
|||
import EditorHead from './editor-head'; |
|||
import SchemaForm from './schema-form'; |
|||
import { useUIState } from '../store/ui'; |
|||
|
|||
function Layout(): JSX.Element { |
|||
const { t } = useTranslation(); |
|||
const uiState = useUIState(); |
|||
const { formVisible } = uiState; |
|||
|
|||
return ( |
|||
<div |
|||
className="json-schema-editor" |
|||
css={css` |
|||
padding: 5px; |
|||
`}
|
|||
> |
|||
<Button type="primary">{t('import_json')}</Button> |
|||
<EditorHead /> |
|||
{formVisible && <SchemaForm />} |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default Layout; |
@ -0,0 +1,22 @@ |
|||
/** @jsx jsx */ |
|||
import { useEffect, memo, useRef } from 'react'; |
|||
import { jsx } from '@emotion/core'; |
|||
import { useUIState } from '../store/ui'; |
|||
|
|||
function SchemaForm(): JSX.Element { |
|||
const uiState = useUIState(); |
|||
const { formVisible } = uiState; |
|||
const renders = useRef(1); |
|||
useEffect(() => { |
|||
console.log(11111); |
|||
}); |
|||
renders.current += 1; |
|||
return ( |
|||
<div> |
|||
{formVisible ? 3 : 0} |
|||
(renders:{renders.current}) |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default memo(SchemaForm); |
@ -0,0 +1,20 @@ |
|||
import * as React from 'react'; |
|||
import { createContext, useContext, useReducer } from 'react'; |
|||
import uiReducer from '../reducer/ui'; |
|||
import { UIContext } from '../model'; |
|||
|
|||
interface ProviderProps { |
|||
children: React.ReactChild; |
|||
} |
|||
|
|||
const initialData = { formVisible: true, aaa: true }; |
|||
|
|||
const Context = createContext({ uiState: initialData } as UIContext); |
|||
|
|||
export const UIProvider = ({ children }: ProviderProps): JSX.Element => { |
|||
const [uiState, uiDispatch] = useReducer(uiReducer, initialData); |
|||
|
|||
return <Context.Provider value={{ uiState, uiDispatch }}>{children}</Context.Provider>; |
|||
}; |
|||
|
|||
export const useUI = (): UIContext => useContext(Context); |
@ -1,6 +1,8 @@ |
|||
{ |
|||
"translation": { |
|||
"import_json": "Import JSON", |
|||
"select_all": "Select All" |
|||
"select_all": "Select All", |
|||
"setting": "Advanced Setting", |
|||
"add_child_node": "Add child node" |
|||
} |
|||
} |
|||
|
@ -1,6 +1,8 @@ |
|||
{ |
|||
"translation": { |
|||
"import_json": "导入 JSON", |
|||
"select_all": "全选" |
|||
"select_all": "全选", |
|||
"setting": "高级设置", |
|||
"add_child_node": "添加子节点" |
|||
} |
|||
} |
|||
|
@ -0,0 +1 @@ |
|||
export * from './ui'; |
@ -0,0 +1,13 @@ |
|||
export interface UIState { |
|||
formVisible: boolean; |
|||
aaa: boolean; |
|||
} |
|||
|
|||
export interface UIAction { |
|||
type: string; |
|||
} |
|||
|
|||
export interface UIContext { |
|||
uiState: UIState; |
|||
uiDispatch: React.Dispatch<UIAction>; |
|||
} |
@ -0,0 +1,16 @@ |
|||
import { UIState, UIAction } from '../model'; |
|||
|
|||
const reducer = (state: UIState, action: UIAction): UIState => { |
|||
switch (action.type) { |
|||
case 'TOGGLE_FORM_VISIBLE': |
|||
return { formVisible: state.formVisible, aaa: false }; |
|||
case 'increment': |
|||
return state; |
|||
case 'decrement': |
|||
return state; |
|||
default: |
|||
return state; |
|||
} |
|||
}; |
|||
|
|||
export default reducer; |
@ -0,0 +1,16 @@ |
|||
import { useState, Dispatch, SetStateAction } from 'react'; |
|||
import { createContainer } from 'react-tracked'; |
|||
|
|||
export type State = { |
|||
formVisible: boolean; |
|||
}; |
|||
|
|||
const initialData = { formVisible: true }; |
|||
|
|||
const useValue = (): [State, Dispatch<SetStateAction<State>>] => useState<State>(initialData); |
|||
|
|||
export const { |
|||
Provider: UIProvider, |
|||
useTrackedState: useUIState, |
|||
useUpdate: useSetUIState, |
|||
} = createContainer(useValue); |
@ -0,0 +1,44 @@ |
|||
import { css } from '@emotion/core'; |
|||
import styled from '@emotion/styled'; |
|||
import { |
|||
CaretDownOutlined, |
|||
CaretRightOutlined, |
|||
EditOutlined, |
|||
SettingOutlined, |
|||
PlusOutlined, |
|||
} from '@ant-design/icons'; |
|||
|
|||
const cursorStyle = css` |
|||
cursor: pointer; |
|||
`;
|
|||
|
|||
const IconStyle = css` |
|||
margin: 0 5px; |
|||
svg { |
|||
font-size: 14px; |
|||
} |
|||
`;
|
|||
|
|||
export const CaretDownIcon = styled(CaretDownOutlined)` |
|||
${cursorStyle} |
|||
`;
|
|||
|
|||
export const CaretRightIcon = styled(CaretRightOutlined)` |
|||
${cursorStyle} |
|||
`;
|
|||
|
|||
export const EditIcon = styled(EditOutlined)` |
|||
${cursorStyle} |
|||
`;
|
|||
|
|||
export const SettingIcon = styled(SettingOutlined)` |
|||
color: #00a854; |
|||
${cursorStyle} |
|||
${IconStyle} |
|||
`;
|
|||
|
|||
export const PlusIcon = styled(PlusOutlined)` |
|||
color: #2395f1; |
|||
${cursorStyle} |
|||
${IconStyle} |
|||
`;
|
Loading…
Reference in new issue