@fe-free/core 2.6.0 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @fe-free/core
2
2
 
3
+ ## 2.6.2
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: crud
8
+ - @fe-free/tool@2.6.2
9
+
10
+ ## 2.6.1
11
+
12
+ ### Patch Changes
13
+
14
+ - feat: page layout tabs
15
+ - @fe-free/tool@2.6.1
16
+
3
17
  ## 2.6.0
4
18
 
5
19
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/core",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -41,7 +41,7 @@
41
41
  "remark-gfm": "^4.0.1",
42
42
  "vanilla-jsoneditor": "^0.23.1",
43
43
  "zustand": "^4.5.4",
44
- "@fe-free/tool": "2.6.0"
44
+ "@fe-free/tool": "2.6.2"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@ant-design/pro-components": "2.8.9",
@@ -51,7 +51,7 @@ export const Basic: Story = {
51
51
 
52
52
  return (
53
53
  <CRUDOfPure
54
- actions={['delete']}
54
+ actions={['create', 'delete']}
55
55
  tableProps={{
56
56
  columns,
57
57
  request: fakeRequest,
@@ -201,3 +201,57 @@ export const NoSearch: Story = {
201
201
  );
202
202
  },
203
203
  };
204
+
205
+ export const SpecialToolbar: Story = {
206
+ render: () => {
207
+ const columns = [
208
+ {
209
+ title: 'id',
210
+ dataIndex: 'id',
211
+ search: true,
212
+ },
213
+ {
214
+ title: '名字(省略)',
215
+ dataIndex: 'name',
216
+ search: true,
217
+ ellipsis: true,
218
+ },
219
+ {
220
+ title: 'city',
221
+ dataIndex: 'city',
222
+ },
223
+ {
224
+ title: 'area',
225
+ dataIndex: 'area',
226
+ },
227
+ ];
228
+
229
+ return (
230
+ <CRUDOfPure
231
+ actions={['create', 'delete']}
232
+ tableProps={{
233
+ columns,
234
+ request: fakeRequest,
235
+ pagination: false,
236
+ }}
237
+ requestDeleteByRecord={fakeDeleteByRecord}
238
+ deleteProps={{
239
+ nameIndex: 'id',
240
+ }}
241
+ detailForm={() => (
242
+ <>
243
+ <ProFormText
244
+ name="name"
245
+ label="名字"
246
+ required
247
+ rules={[{ required: true }]}
248
+ extra="extra extra extra extra"
249
+ />
250
+ </>
251
+ )}
252
+ requestCreateByValues={fakeCreate}
253
+ specialToolbar
254
+ />
255
+ );
256
+ },
257
+ };
@@ -9,7 +9,8 @@ interface CRUDOfPureProps<
9
9
  DataSource extends Record<string, any> = any,
10
10
  Key extends string | number = string,
11
11
  > extends CRUDProps<DataSource, Key> {
12
- // nothing
12
+ /** 特殊位置的 toolbar */
13
+ specialToolbar?: boolean;
13
14
  }
14
15
 
15
16
  function CRUDOfPureComponent(props: CRUDOfPureProps, ref: React.ForwardedRef<CRUDMethods>) {
@@ -43,6 +44,7 @@ function CRUDOfPureComponent(props: CRUDOfPureProps, ref: React.ForwardedRef<CRU
43
44
  'fec-crud-of-pure-no-search': noSearch,
44
45
  // 先这样实现
45
46
  'fec-crud-of-pure-no-toolbar': !props.actions.includes('create'),
47
+ 'fec-crud-of-pure-special-toolbar': props.specialToolbar,
46
48
  })}
47
49
  >
48
50
  <CRUD
@@ -54,4 +54,15 @@
54
54
  padding-block: 0;
55
55
  }
56
56
  }
57
+
58
+ &.fec-crud-of-pure-special-toolbar {
59
+ .ant-pro-table-list-toolbar {
60
+ margin-top: -48px;
61
+ pointer-events: none;
62
+
63
+ .ant-pro-table-list-toolbar-right > div {
64
+ pointer-events: auto;
65
+ }
66
+ }
67
+ }
57
68
  }
package/src/index.ts CHANGED
@@ -41,7 +41,8 @@ export { downloadInterceptor } from './global/interceptors';
41
41
  export { InfiniteList } from './infinite_list';
42
42
  export type { InfiniteListProps } from './infinite_list';
43
43
  export { Markdown } from './markdown';
44
- export { PageLayout } from './page_layout';
44
+ export { PageLayout, PageLayoutTabs } from './page_layout';
45
+ export type { PageLayoutProps, PageLayoutTabsProps } from './page_layout';
45
46
  export { routeTool } from './route';
46
47
  export { NumberSlider, PercentageSlider } from './slider';
47
48
  export type { NumberSliderProps, PercentageSliderProps } from './slider';
@@ -1,4 +1,8 @@
1
1
  import cn from 'classnames';
2
+ import { Fragment, useMemo } from 'react';
3
+ import { useSearchParams } from 'react-router-dom';
4
+ import type { TabsProps } from '../tabs';
5
+ import { Tabs } from '../tabs';
2
6
 
3
7
  interface PageLayoutProps {
4
8
  direction?: 'horizontal' | 'vertical';
@@ -24,7 +28,7 @@ function PageLayout({
24
28
  return (
25
29
  <div
26
30
  className={cn(
27
- 'flex w-full h-full',
31
+ 'flex h-full w-full',
28
32
  {
29
33
  'flex-row': direction === 'horizontal',
30
34
  'flex-col': direction === 'vertical',
@@ -39,4 +43,56 @@ function PageLayout({
39
43
  );
40
44
  }
41
45
 
42
- export { PageLayout };
46
+ interface PageLayoutTabsProps extends PageLayoutProps {
47
+ tabsProps: Omit<TabsProps, 'items' | 'withSearchParams'> & {
48
+ items: {
49
+ key: string;
50
+ label: React.ReactNode;
51
+ children: React.ReactNode;
52
+ }[];
53
+ };
54
+ }
55
+
56
+ function PageLayoutTabs(props: PageLayoutTabsProps) {
57
+ const { tabsProps, ...rest } = props;
58
+
59
+ const [searchParams] = useSearchParams();
60
+ const tab = searchParams.get(tabsProps.tabKey || 'tab') || undefined;
61
+
62
+ const { children, newItems } = useMemo(() => {
63
+ const items = props.tabsProps.items;
64
+
65
+ const item = items.find((item) => item.key === tab);
66
+ const children = item?.children || items[0]?.children;
67
+
68
+ const newItems = items.map((item) => ({
69
+ ...item,
70
+ children: undefined,
71
+ }));
72
+
73
+ return { children, newItems };
74
+ }, [props.tabsProps.items, tab]);
75
+
76
+ return (
77
+ <PageLayout
78
+ direction="vertical"
79
+ start={
80
+ <Tabs
81
+ tabBarExtraContent={{
82
+ left: <div className="w-4" />,
83
+ right: <div className="w-4" />,
84
+ }}
85
+ {...tabsProps}
86
+ items={newItems}
87
+ withSearchParams
88
+ />
89
+ }
90
+ {...rest}
91
+ >
92
+ <Fragment key={tab}>{children}</Fragment>
93
+ </PageLayout>
94
+ );
95
+ }
96
+
97
+ export { PageLayout, PageLayoutTabs };
98
+ export type { PageLayoutProps, PageLayoutTabsProps };
@@ -1,37 +1,46 @@
1
1
  import type { TabsProps as AntdTabsProps } from 'antd';
2
2
  import { Tabs as AntdTabs } from 'antd';
3
- import { useEffect } from 'react';
3
+ import classNames from 'classnames';
4
4
  import { useSearchParams } from 'react-router-dom';
5
+ import { routeTool } from '../route';
6
+ import './style.scss';
5
7
 
6
8
  interface TabsProps extends AntdTabsProps {
7
9
  /** 自动时设置和同步 searchParams tab */
8
10
  withSearchParams?: boolean;
11
+ /** 设置 searchParams 的类型,默认 set */
12
+ searchParamsType?: 'set' | 'change';
13
+ /** 默认 tab */
14
+ tabKey?: string;
9
15
  }
10
16
 
11
17
  function Tabs(props: TabsProps) {
12
- const { withSearchParams, activeKey, onChange, ...rest } = props;
13
- const [searchParams, setSearchParams] = useSearchParams();
14
- const tab = searchParams.get('tab') || undefined;
15
-
16
- useEffect(() => {
17
- if (withSearchParams) {
18
- if (!tab && props.items?.[0]?.key) {
19
- setSearchParams({ tab: props.items?.[0]?.key });
20
- }
21
- }
22
- // tab 清空的时候要重新设置第一个
23
- }, [tab]);
18
+ const {
19
+ withSearchParams,
20
+ searchParamsType = 'set',
21
+ tabKey = 'tab',
22
+ activeKey,
23
+ onChange,
24
+ className,
25
+ ...rest
26
+ } = props;
27
+ const [searchParams] = useSearchParams();
28
+ const tab = searchParams.get(tabKey) || undefined;
24
29
 
25
30
  return (
26
31
  <AntdTabs
27
32
  {...rest}
33
+ className={classNames('fec-tabs', className)}
28
34
  activeKey={withSearchParams ? tab : activeKey}
29
35
  onChange={(key) => {
30
36
  onChange?.(key);
31
- if (props.withSearchParams) {
32
- searchParams.set('tab', key);
33
37
 
34
- setSearchParams({ tab: key });
38
+ if (props.withSearchParams) {
39
+ if (searchParamsType === 'set') {
40
+ routeTool.setSearchParams({ [tabKey]: key });
41
+ } else {
42
+ routeTool.changeSearchParams({ [tabKey]: key });
43
+ }
35
44
  }
36
45
  }}
37
46
  />
@@ -0,0 +1,5 @@
1
+ .fec-tabs {
2
+ .ant-tabs-nav {
3
+ margin: 0;
4
+ }
5
+ }