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": { |
"translation": { |
||||
"import_json": "Import JSON", |
"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": { |
"translation": { |
||||
"import_json": "导入 JSON", |
"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