pureList
This commit is contained in:
parent
dfe01079ea
commit
0a5c5de102
|
|
@ -9,6 +9,12 @@
|
||||||
"lib/**/*"
|
"lib/**/*"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ant-design/cssinjs": "^1.6.1",
|
||||||
|
"@ant-design/icons": "^5.0.1",
|
||||||
|
"@icon-park/react": "^1.4.2",
|
||||||
|
"antd": "^5.3.0",
|
||||||
|
"antd-mobile": "^5.28.1",
|
||||||
|
"antd-mobile-icons": "^0.3.0",
|
||||||
"debounce": "^1.2.1",
|
"debounce": "^1.2.1",
|
||||||
"format-message-parse": "^6.2.4",
|
"format-message-parse": "^6.2.4",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
|
|
@ -16,6 +22,7 @@
|
||||||
"oak-common-aspect": "file:../oak-common-aspect",
|
"oak-common-aspect": "file:../oak-common-aspect",
|
||||||
"oak-domain": "file:../oak-domain",
|
"oak-domain": "file:../oak-domain",
|
||||||
"oak-memory-tree-store": "file:../oak-memory-tree-store",
|
"oak-memory-tree-store": "file:../oak-memory-tree-store",
|
||||||
|
"react-scripts": "^5.0.1",
|
||||||
"rmc-pull-to-refresh": "^1.0.13",
|
"rmc-pull-to-refresh": "^1.0.13",
|
||||||
"url": "^0.11.0",
|
"url": "^0.11.0",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"l-dialog": "../../miniprogram_npm/lin-ui/dialog/index",
|
||||||
|
"l-button": "../../miniprogram_npm/lin-ui/button/index",
|
||||||
|
"popover": "../../miniprogram_npm/popover/popover",
|
||||||
|
"popover-item": "../../miniprogram_npm/popover/popover-item"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
.panel-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20rpx 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #000;
|
||||||
|
padding: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
export default OakComponent({
|
||||||
|
properties: {
|
||||||
|
entity: String,
|
||||||
|
actions: {
|
||||||
|
type: Array,
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
value: 'cell',
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
type: Number,
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
},
|
||||||
|
lifetimes: {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<block wx:if="{{ newItems && newItems.length > 0 }}">
|
||||||
|
<view class="panel-container">
|
||||||
|
<block wx:if="{{ moreItems && moreItems.length > 0 }}">
|
||||||
|
<view id='more' class="more" catchtap="handleMoreClick">
|
||||||
|
更多
|
||||||
|
</view>
|
||||||
|
<popover id='popover'>
|
||||||
|
<block wx:for="{{ moreItems }}" wx:key="index">
|
||||||
|
<popover-item hasline catchtap='handleClick' data-type="popover" data-item="{{ item }}">{{ item.text }}</popover-item>
|
||||||
|
</block>
|
||||||
|
</popover>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="btn-container">
|
||||||
|
|
||||||
|
<block wx:for="{{ newItems }}" wx:key="index">
|
||||||
|
<l-button plain="{{true}}" shape="{{ item.buttonProps.shape || 'square' }}" catchtap="handleClick" data-item="{{ item }}">
|
||||||
|
{{item.text}}
|
||||||
|
</l-button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<l-dialog id="my-action-btn-dialog" bind:linconfirm="linconfirm" bind:lincancel="lincancel" />
|
||||||
|
|
||||||
|
</block>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
.panelContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #000;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,253 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Space,
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
ButtonProps,
|
||||||
|
SpaceProps,
|
||||||
|
Dropdown,
|
||||||
|
Typography,
|
||||||
|
} from 'antd';
|
||||||
|
import { WebComponentProps } from '../../types/Page';
|
||||||
|
import { EntityDict } from 'oak-domain/lib/types/Entity';
|
||||||
|
import Style from './web.module.less';
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
type Item = {
|
||||||
|
icon?: string | React.ReactNode;
|
||||||
|
label?: string;
|
||||||
|
action?: string;
|
||||||
|
auth: boolean;
|
||||||
|
type?: 'a' | 'button';
|
||||||
|
index?: number;
|
||||||
|
alerted?: boolean;
|
||||||
|
alertTitle?: string;
|
||||||
|
alertContent?: string;
|
||||||
|
confirmText?: string;
|
||||||
|
cancelText?: string;
|
||||||
|
render?: React.ReactNode;
|
||||||
|
beforeAction?: (item: Item) => boolean | Promise<boolean>;
|
||||||
|
afterAction?: (item: Item) => void;
|
||||||
|
onClick?: (item: Item) => void | Promise<void>;
|
||||||
|
buttonProps?: Omit<ButtonProps, 'onClick'>;
|
||||||
|
filter?: () => boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function ItemComponent(
|
||||||
|
props: Item & {
|
||||||
|
onClick: () => void | Promise<void>;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const { type, buttonProps, render, onClick, text } = props;
|
||||||
|
|
||||||
|
if (type === 'button') {
|
||||||
|
return (
|
||||||
|
<Button {...buttonProps} onClick={onClick}>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (render) {
|
||||||
|
return <div onClick={onClick}>{render}</div>;
|
||||||
|
}
|
||||||
|
return <a onClick={onClick}>{text}</a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Render(
|
||||||
|
props: WebComponentProps<
|
||||||
|
EntityDict,
|
||||||
|
keyof EntityDict,
|
||||||
|
false,
|
||||||
|
{
|
||||||
|
entity: string;
|
||||||
|
actions: string[];
|
||||||
|
items: Item[];
|
||||||
|
spaceProps: SpaceProps;
|
||||||
|
mode: 'cell' | 'table-cell';
|
||||||
|
column: 3;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
getActionName: (action?: string) => string;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
const { methods, data } = props;
|
||||||
|
const { t, getActionName } = methods;
|
||||||
|
const {
|
||||||
|
items,
|
||||||
|
oakLegalActions,
|
||||||
|
spaceProps,
|
||||||
|
entity,
|
||||||
|
mode = 'cell',
|
||||||
|
column,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
const getItems = () => {
|
||||||
|
const items2 = items
|
||||||
|
.filter((ele) => {
|
||||||
|
const { action, filter } = ele;
|
||||||
|
const authResult =
|
||||||
|
!action ||
|
||||||
|
(action &&
|
||||||
|
oakLegalActions?.includes(
|
||||||
|
action as EntityDict[keyof EntityDict]['Action']
|
||||||
|
));
|
||||||
|
const filterResult =
|
||||||
|
ele.hasOwnProperty('filter') && filter ? filter() : true;
|
||||||
|
return authResult && filterResult;
|
||||||
|
})
|
||||||
|
.map((ele, index: number) => {
|
||||||
|
const { label, action } = ele;
|
||||||
|
let text: string = '';
|
||||||
|
if (label) {
|
||||||
|
text = label;
|
||||||
|
} else {
|
||||||
|
text = getActionName(action);
|
||||||
|
}
|
||||||
|
let onClick = async () => {
|
||||||
|
if (ele.onClick) {
|
||||||
|
ele.onClick(ele);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ele.beforeAction) {
|
||||||
|
const r = await ele.beforeAction(ele);
|
||||||
|
if (!r) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await methods.execute(
|
||||||
|
action as EntityDict[keyof EntityDict]['Action']
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ele.afterAction) {
|
||||||
|
ele.afterAction(ele);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (ele.alerted) {
|
||||||
|
onClick = async () => {
|
||||||
|
let content = '';
|
||||||
|
if (action) {
|
||||||
|
const text = getActionName(action);
|
||||||
|
content = `确认${text}该数据`;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: ele.alertTitle,
|
||||||
|
content: ele.alertContent || content,
|
||||||
|
okText: ele.confirmText || '确定',
|
||||||
|
cancelText: ele.cancelText || '取消',
|
||||||
|
onOk: async () => {
|
||||||
|
if (ele.onClick) {
|
||||||
|
ele.onClick(ele);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ele.beforeAction) {
|
||||||
|
const r = await ele.beforeAction(ele);
|
||||||
|
if (!r) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await methods.execute(
|
||||||
|
ele.action as EntityDict[keyof EntityDict]['Action']
|
||||||
|
);
|
||||||
|
if (ele.afterAction) {
|
||||||
|
ele.afterAction(ele);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return Object.assign(ele, {
|
||||||
|
text: text,
|
||||||
|
onClick2: onClick,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let newItems = items2;
|
||||||
|
let moreItems: Item[] = [];
|
||||||
|
if (column && items2.length > column) {
|
||||||
|
newItems = [...items2].splice(0, column);
|
||||||
|
moreItems = [...items2].splice(column, items2.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
newItems,
|
||||||
|
moreItems,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const { newItems, moreItems } = getItems();
|
||||||
|
|
||||||
|
if (!newItems || newItems.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'table-cell') {
|
||||||
|
return (
|
||||||
|
<Space {...spaceProps}>
|
||||||
|
{newItems?.map((ele, index: number) => {
|
||||||
|
return (
|
||||||
|
<ItemComponent
|
||||||
|
{...ele}
|
||||||
|
onClick={ele.onClick2}
|
||||||
|
text={ele.text}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{moreItems && moreItems.length > 0 && (
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items: moreItems.map((ele: any, index) => ({
|
||||||
|
label: ele.text as string,
|
||||||
|
key: index,
|
||||||
|
})),
|
||||||
|
onClick: (e: any) => {
|
||||||
|
const item = moreItems[e.key] as any;
|
||||||
|
item.onClick2();
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
placement="top"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<a onClick={(e) => e.preventDefault()}>更多</a>
|
||||||
|
</Dropdown>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={Style.panelContainer}>
|
||||||
|
{moreItems && moreItems.length > 0 && (
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items: moreItems.map((ele: any, index) => ({
|
||||||
|
label: ele.text,
|
||||||
|
key: index,
|
||||||
|
})),
|
||||||
|
onClick: (e: any) => {
|
||||||
|
const item = moreItems[e.key] as any;
|
||||||
|
item.onClick2();
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<Typography className={Style.more}>更多</Typography>
|
||||||
|
</Dropdown>
|
||||||
|
)}
|
||||||
|
<Space {...spaceProps}>
|
||||||
|
{newItems?.map((ele, index: number) => {
|
||||||
|
return (
|
||||||
|
<ItemComponent
|
||||||
|
type="button"
|
||||||
|
{...ele}
|
||||||
|
onClick={ele.onClick2}
|
||||||
|
text={ele.text}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Table, Tag, TableProps } from 'antd';
|
||||||
|
import type { ColumnsType, ColumnType, ColumnGroupType } from 'antd/es/table';
|
||||||
|
import assert from 'assert';
|
||||||
|
import {useFeatures} from '../../platforms/web/features/index';
|
||||||
|
import { getAttributes } from '../../utils/usefulFn';
|
||||||
|
import { get } from 'oak-domain/lib/utils/lodash';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { ActionBtnPanelProps } from '@oak-general-business/types/actionBtnPanel';
|
||||||
|
import ActionBtnPanel from '@oak-general-business/components/func/actionBtnPanel';
|
||||||
|
|
||||||
|
type SelfColumn = {
|
||||||
|
path?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Column = SelfColumn & ColumnType<any>;
|
||||||
|
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
entity: string;
|
||||||
|
data: any[];
|
||||||
|
columns: (Column | string)[];
|
||||||
|
actionBtnProps?: (row: any) => ActionBtnPanelProps;
|
||||||
|
tableProps?: TableProps<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderCellProps = {
|
||||||
|
content: any;
|
||||||
|
entity: string;
|
||||||
|
path: string;
|
||||||
|
attr: string;
|
||||||
|
attrType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeTitle(entity: string, attr: string) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
if (attr === ('$$createAt$$' || '$$updateAt$$')) {
|
||||||
|
return t(`common:${attr}`)
|
||||||
|
}
|
||||||
|
return t(`${entity}:attr.${attr}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析路径, 获取属性类型、属性值、以及实体名称
|
||||||
|
function Fn(entity: string, path: string) {
|
||||||
|
let _entity = entity;
|
||||||
|
let attr: string;
|
||||||
|
assert(!path.includes('['), '数组索引不需要携带[],请使用arr.0.value')
|
||||||
|
const features = useFeatures();
|
||||||
|
const dataSchema = features.cache.getSchema();
|
||||||
|
if (!path.includes('.')) {
|
||||||
|
attr = path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const strs = path.split('.');
|
||||||
|
// 最后一个肯定是属性
|
||||||
|
attr = strs.pop()!;
|
||||||
|
// 倒数第二个可能是类名可能是索引
|
||||||
|
_entity = strs.pop()!;
|
||||||
|
// 判断是否是数组索引
|
||||||
|
if (!Number.isNaN(Number(_entity))) {
|
||||||
|
_entity = strs.pop()!.split('$')[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const attributes = getAttributes(dataSchema[_entity as keyof typeof dataSchema].attributes);
|
||||||
|
const attribute = attributes[attr];
|
||||||
|
return {
|
||||||
|
entity: _entity,
|
||||||
|
attr,
|
||||||
|
attribute,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function RenderCell(props: RenderCellProps) {
|
||||||
|
const { content, entity, path, attr, attrType } = props;
|
||||||
|
const value = get(content, path);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const feature = useFeatures();
|
||||||
|
const colorDict = feature.style.getColorDict();
|
||||||
|
if (!value) {
|
||||||
|
return (<div>--</div>);
|
||||||
|
}
|
||||||
|
// 属性类型是enum要使用标签
|
||||||
|
else if (attrType === 'enum') {
|
||||||
|
return (
|
||||||
|
<Tag color={colorDict[entity][attr][String(value)]} >
|
||||||
|
{t(`${entity}:v.${attr}.${value}`)}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (attrType === 'datetime') {
|
||||||
|
return <div>{dayjs(value).format('YYYY-MM-DD HH:mm')}</div>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>{value}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function List(props: Props) {
|
||||||
|
const { data, columns, entity, actionBtnProps, tableProps } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const tableColumns: ColumnsType<any> = columns.map((ele) => {
|
||||||
|
let title: string = '';
|
||||||
|
let render: (value: any, row: any) => React.ReactNode = () => <></>;
|
||||||
|
let path: string | undefined;
|
||||||
|
if (typeof ele === 'string') {
|
||||||
|
path = ele;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
path = ele.path;
|
||||||
|
}
|
||||||
|
const { entity: useEntity, attr, attribute } = Fn(entity, path!) || {};
|
||||||
|
title = decodeTitle(useEntity, attr);
|
||||||
|
render = (value, row) => (
|
||||||
|
<RenderCell entity={entity} content={row} path={path!} attr={attr} attrType={attribute.type} />
|
||||||
|
);
|
||||||
|
const column = {
|
||||||
|
align: 'center',
|
||||||
|
title,
|
||||||
|
dataIndex: typeof ele === 'string' ? ele : ele.dataIndex,
|
||||||
|
render,
|
||||||
|
};
|
||||||
|
// 类型如果是枚举类型,那么它的宽度一般不超过160
|
||||||
|
// if (attribute?.type === 'enum') {
|
||||||
|
// Object.assign(column, {width: 160})
|
||||||
|
// }
|
||||||
|
return Object.assign(column, typeof ele !== 'string' && ele);
|
||||||
|
}) as ColumnsType<any>;
|
||||||
|
if (tableColumns && tableColumns) {
|
||||||
|
tableColumns.unshift({title: '序号', width: 100, render(value, record, index) {
|
||||||
|
return index + 1;
|
||||||
|
},})
|
||||||
|
}
|
||||||
|
if (actionBtnProps) {
|
||||||
|
tableColumns.push({
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'right',
|
||||||
|
title: '操作',
|
||||||
|
key: 'operation',
|
||||||
|
width: 100,
|
||||||
|
render: (value, row) => (
|
||||||
|
<ActionBtnPanel {...actionBtnProps(row)} />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Table dataSource={data} scroll={{ x: 2200 }} columns={tableColumns} ></Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default List;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
export function getAttributes(attributes: Record<string, any>) {
|
||||||
|
return Object.assign({}, attributes, {
|
||||||
|
id: {
|
||||||
|
type: 'char',
|
||||||
|
},
|
||||||
|
$$createAt$$: {
|
||||||
|
type: 'datetime',
|
||||||
|
},
|
||||||
|
$$updateAt$$: {
|
||||||
|
type: 'datetime',
|
||||||
|
},
|
||||||
|
$$deleteAt$$: {
|
||||||
|
type: 'datetime',
|
||||||
|
},
|
||||||
|
$$seq$$: {
|
||||||
|
type: 'datetime',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import {
|
||||||
|
MakeOakComponent,
|
||||||
|
} from '../src/types/Page';
|
||||||
|
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||||
|
import { EntityDict, Aspect } from 'oak-domain/lib/types';
|
||||||
|
import { Feature } from '../src/types/Feature';
|
||||||
|
import { AsyncContext } from "oak-domain/lib/store/AsyncRowStore";
|
||||||
|
import { SyncContext } from "oak-domain/lib/store/SyncRowStore";
|
||||||
|
type ED = EntityDict & BaseEntityDict;
|
||||||
|
type Cxt = AsyncContext<ED>;
|
||||||
|
type FrontCxt = SyncContext<ED>;
|
||||||
|
type AD = Record<string, Aspect<ED, Cxt>>;
|
||||||
|
type FD = Record<string, Feature>
|
||||||
|
declare global {
|
||||||
|
const OakComponent: MakeOakComponent<
|
||||||
|
ED,
|
||||||
|
Cxt,
|
||||||
|
FrontCxt,
|
||||||
|
AD,
|
||||||
|
FD
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/// <reference types="react-scripts" />
|
||||||
|
|
||||||
|
declare module '*.module.less' {
|
||||||
|
const classes: {
|
||||||
|
readonly [key: string]: string;
|
||||||
|
};
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue