@fe-free/core 4.1.40 → 4.1.42

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,21 @@
1
1
  # @fe-free/core
2
2
 
3
+ ## 4.1.42
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add valueType CustomMarkdownModal
8
+ - @fe-free/icons@4.1.42
9
+ - @fe-free/tool@4.1.42
10
+
11
+ ## 4.1.41
12
+
13
+ ### Patch Changes
14
+
15
+ - feat: some
16
+ - @fe-free/icons@4.1.41
17
+ - @fe-free/tool@4.1.41
18
+
3
19
  ## 4.1.40
4
20
 
5
21
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/core",
3
- "version": "4.1.40",
3
+ "version": "4.1.42",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -10,6 +10,8 @@
10
10
  "registry": "https://registry.npmjs.org/"
11
11
  },
12
12
  "dependencies": {
13
+ "@ant-design/x-markdown": "^2.1.3",
14
+ "@ant-design/x": "^2.1.3",
13
15
  "@codemirror/lang-html": "^6.4.9",
14
16
  "@codemirror/lang-javascript": "^6.2.4",
15
17
  "@codemirror/lang-json": "^6.0.1",
@@ -50,8 +52,8 @@
50
52
  "i18next-icu": "^2.4.1",
51
53
  "react": "^19.2.0",
52
54
  "react-i18next": "^16.4.0",
53
- "@fe-free/icons": "4.1.40",
54
- "@fe-free/tool": "4.1.40"
55
+ "@fe-free/icons": "4.1.42",
56
+ "@fe-free/tool": "4.1.42"
55
57
  },
56
58
  "scripts": {
57
59
  "i18n-extract": "rm -rf ./src/locales/zh-CN && npx i18next-cli extract"
package/src/crud/crud.tsx CHANGED
@@ -129,6 +129,7 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
129
129
  if (fullPage) {
130
130
  return {
131
131
  ...tableProps,
132
+ rowKey: tableProps.rowKey || 'id',
132
133
  scroll: {
133
134
  ...getTableScroll(newColumns),
134
135
  y: '100%',
@@ -136,7 +137,10 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
136
137
  };
137
138
  }
138
139
 
139
- return tableProps;
140
+ return {
141
+ ...tableProps,
142
+ rowKey: tableProps.rowKey || 'id',
143
+ };
140
144
  }, [fullPage, tableProps, newColumns]);
141
145
 
142
146
  return (
@@ -150,7 +154,6 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
150
154
  )}
151
155
  >
152
156
  <Table<DataSource>
153
- rowKey="id"
154
157
  {...newTableProps}
155
158
  actionRef={actionRef}
156
159
  toolBarRender={toolBarRender}
@@ -15,7 +15,7 @@ function OperateBtn({
15
15
  }) {
16
16
  if (disabled) {
17
17
  if (operateText) {
18
- return <span className="cursor-not-allowed text-lg text-03">{operateText || icon}</span>;
18
+ return <span className="cursor-not-allowed text-03">{operateText}</span>;
19
19
  } else {
20
20
  return (
21
21
  <Tooltip title={title}>
@@ -27,7 +27,7 @@ function OperateBtn({
27
27
 
28
28
  if (operateText) {
29
29
  return (
30
- <span className="cursor-pointer text-lg text-primary" onClick={onClick}>
30
+ <span className="cursor-pointer text-primary" onClick={onClick}>
31
31
  {operateText}
32
32
  </span>
33
33
  );
@@ -36,7 +36,7 @@ function OperateBtn({
36
36
  return (
37
37
  <Tooltip title={title}>
38
38
  <span className="cursor-pointer text-lg text-primary" onClick={onClick}>
39
- {operateText || icon}
39
+ {icon}
40
40
  </span>
41
41
  </Tooltip>
42
42
  );
@@ -4,8 +4,13 @@ import classNames from 'classnames';
4
4
  import { useMemo } from 'react';
5
5
  import './style.scss';
6
6
 
7
- interface TableProps<DataSource = any, Params = any, ValueType = 'text'>
8
- extends ProTableProps<DataSource, Params, ValueType> {
7
+ interface TableProps<DataSource = any, Params = any, ValueType = 'text'> extends ProTableProps<
8
+ DataSource,
9
+ Params,
10
+ ValueType
11
+ > {
12
+ // 要求 rowKey 必须存在
13
+ rowKey: string;
9
14
  /** 区别 ProTable columns,默认 search: false */
10
15
  columns?: ProTableProps<DataSource, Params, ValueType>['columns'];
11
16
  }
@@ -224,7 +224,7 @@ function useOperate(props, detailProps, actionRef) {
224
224
  }
225
225
 
226
226
  return (
227
- <div className="fec-crud-operate-column flex justify-center gap-4">
227
+ <div className="fec-crud-operate-column flex items-center justify-center gap-4">
228
228
  {operateColumnProps?.moreOperator && operateColumnProps.moreOperator(record)}
229
229
  {btns}
230
230
  {operateColumnProps?.moreOperatorAfter && operateColumnProps.moreOperatorAfter(record)}
@@ -56,6 +56,7 @@ export const Basic: Story = {
56
56
  <CRUDOfPure
57
57
  actions={['create', 'delete']}
58
58
  tableProps={{
59
+ rowKey: 'id',
59
60
  columns,
60
61
  request: fakeRequest,
61
62
  search: {
@@ -118,6 +119,7 @@ export const WithCreate: Story = {
118
119
  <CRUDOfPure
119
120
  actions={['create', 'delete']}
120
121
  tableProps={{
122
+ rowKey: 'id',
121
123
  columns,
122
124
  request: fakeRequest,
123
125
  pagination: false,
@@ -179,6 +181,7 @@ export const NoSearch: Story = {
179
181
  <CRUDOfPure
180
182
  actions={['create', 'delete']}
181
183
  tableProps={{
184
+ rowKey: 'id',
182
185
  columns,
183
186
  request: fakeRequest,
184
187
  pagination: false,
@@ -233,6 +236,7 @@ export const SpecialToolbar: Story = {
233
236
  specialToolbar
234
237
  actions={['create', 'delete']}
235
238
  tableProps={{
239
+ rowKey: 'id',
236
240
  columns,
237
241
  request: fakeRequest,
238
242
  pagination: false,
@@ -258,7 +262,7 @@ export const SpecialToolbar: Story = {
258
262
  },
259
263
  };
260
264
 
261
- export const SpecialToolbar2: Story = {
265
+ export const SpecialToolbarWithToolBarRender: Story = {
262
266
  render: () => {
263
267
  const columns = [
264
268
  {
@@ -287,6 +291,7 @@ export const SpecialToolbar2: Story = {
287
291
  specialToolbar
288
292
  actions={['delete']}
289
293
  tableProps={{
294
+ rowKey: 'id',
290
295
  columns,
291
296
  request: fakeRequest,
292
297
  pagination: false,
@@ -346,6 +351,7 @@ export const FullPage: Story = {
346
351
  specialToolbar
347
352
  actions={['create', 'delete']}
348
353
  tableProps={{
354
+ rowKey: 'id',
349
355
  columns,
350
356
  request: fakeRequest,
351
357
  search: {
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { useMemo } from 'react';
2
+ import { useEffect, useId, useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import type { CRUDProps } from '../crud';
5
5
  import { CRUD } from '../crud';
@@ -14,11 +14,60 @@ interface CRUDOfPureProps<
14
14
  specialToolbar?: boolean;
15
15
  }
16
16
 
17
+ function useSpecialToolbar({ specialToolbar, id }: { specialToolbar?: boolean; id: string }) {
18
+ useEffect(() => {
19
+ if (!specialToolbar) return;
20
+
21
+ const container = document.querySelector(
22
+ `.fec-crud-of-pure-${id}.fec-crud-of-pure-special-toolbar`,
23
+ );
24
+ if (!container) return;
25
+
26
+ const connect = () => {
27
+ const toolbarRightDiv = container.querySelector('.ant-pro-table-list-toolbar-right > div');
28
+ const queryFilter = container.querySelector('.ant-pro-query-filter') as HTMLElement | null;
29
+ if (!toolbarRightDiv || !queryFilter) return null;
30
+
31
+ const applyPadding = (width: number) => {
32
+ // 16 是原本的 padding-right。 20 是预留间隔
33
+ queryFilter.style.paddingRight = `${width + 16 + 20}px`;
34
+ };
35
+
36
+ const ro = new ResizeObserver((entries) => {
37
+ for (const entry of entries) {
38
+ applyPadding(entry.contentRect.width);
39
+ }
40
+ });
41
+ ro.observe(toolbarRightDiv);
42
+
43
+ applyPadding((toolbarRightDiv as HTMLElement).getBoundingClientRect().width);
44
+ return () => ro.disconnect();
45
+ };
46
+
47
+ let disconnect: (() => void) | null = connect();
48
+ if (!disconnect) {
49
+ const mo = new MutationObserver(() => {
50
+ disconnect = connect();
51
+ if (disconnect) mo.disconnect();
52
+ });
53
+ mo.observe(container, { childList: true, subtree: true });
54
+ return () => {
55
+ mo.disconnect();
56
+ disconnect?.();
57
+ };
58
+ }
59
+ return disconnect;
60
+ }, [id, specialToolbar]);
61
+ }
62
+
17
63
  function CRUDOfPure<
18
64
  DataSource extends Record<string, any> = any,
19
65
  Key extends string | number = string,
20
66
  >(props: CRUDOfPureProps<DataSource, Key>) {
67
+ const id = useId();
68
+
21
69
  const { t } = useTranslation();
70
+ useSpecialToolbar({ specialToolbar: props.specialToolbar, id });
22
71
  const newColumns = props.tableProps.columns?.map((column) => {
23
72
  if (column.search) {
24
73
  return {
@@ -54,6 +103,7 @@ function CRUDOfPure<
54
103
  {...props}
55
104
  className={classNames(
56
105
  'fec-crud-of-pure',
106
+ `fec-crud-of-pure-${id}`,
57
107
  {
58
108
  'fec-crud-of-pure-no-search': noSearch,
59
109
  'fec-crud-of-pure-special-toolbar': props.specialToolbar,
@@ -70,7 +120,7 @@ function CRUDOfPure<
70
120
  if (typeof props.tableProps.toolBarRender === 'function') {
71
121
  originRender = props.tableProps.toolBarRender(...args);
72
122
  }
73
- return [...originRender, <div key="fake" style={{ height: '32px' }} />];
123
+ return [...originRender];
74
124
  },
75
125
  }}
76
126
  />
@@ -69,6 +69,10 @@
69
69
  z-index: 10;
70
70
  pointer-events: none;
71
71
 
72
+ .ant-pro-table-list-toolbar-left {
73
+ margin-block-end: 0;
74
+ }
75
+
72
76
  .ant-pro-table-list-toolbar-right > div {
73
77
  pointer-events: auto;
74
78
  }
package/src/index.ts CHANGED
@@ -52,7 +52,8 @@ export { RequestError, initErrorHandle } from './global/error';
52
52
  export { downloadInterceptor } from './global/interceptors';
53
53
  export { InfiniteList } from './infinite_list';
54
54
  export type { InfiniteListProps } from './infinite_list';
55
- export { Markdown } from './markdown';
55
+ export { CustomMarkdown, Markdown } from './markdown';
56
+ export type { CustomMarkdownProps, MarkdownProps } from './markdown';
56
57
  export { PageLayout, PageLayoutTabs } from './page_layout';
57
58
  export type { PageLayoutProps, PageLayoutTabsProps } from './page_layout';
58
59
  export { Record, RecordArray } from './record';
@@ -32,7 +32,7 @@ interface ChartConfig extends ChartConfigBase, ChartConfigLine {}
32
32
  function ChartError(props: { children?: React.ReactNode }) {
33
33
  const { children } = props;
34
34
  return (
35
- <div className="markdown-body-block-chart">
35
+ <div className="fea-markdown-body-block-chart">
36
36
  <div style={{ textAlign: 'center', padding: '20px' }}>{children || '图表发生错误'}</div>
37
37
  </div>
38
38
  );
@@ -62,8 +62,8 @@ class ErrorBoundary extends React.Component {
62
62
  function ChartContainer(props: { title: string; children: React.ReactNode }) {
63
63
  const { title, children } = props;
64
64
  return (
65
- <div className="markdown-body-block-chart">
66
- <div className="markdown-body-block-chart-title">{title}</div>
65
+ <div className="fea-markdown-body-block-chart">
66
+ <div className="fea-markdown-body-block-chart-title">{title}</div>
67
67
  {children}
68
68
  </div>
69
69
  );
@@ -1,42 +1,29 @@
1
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
2
- import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
1
+ import { CodeHighlighter, Mermaid } from '@ant-design/x';
2
+ import type { ComponentProps } from '@ant-design/x-markdown';
3
+ import { memo } from 'react';
3
4
  import { ChartBlock } from './chart';
4
5
  import { HMChartBlock } from './hm_chart';
5
6
 
6
- function CodeBlock(props: any) {
7
- const { children, className, ...rest } = props;
8
- const match = /language-(\w+)/.exec(props.className || '');
7
+ const CodeComponent = memo((props: ComponentProps) => {
8
+ const { className, children } = props;
9
9
 
10
- // 如果是 chart 类型的代码块,使用 ChartBlock 组件
11
- if (match && match[1] === 'chart') {
10
+ const lang = className?.match(/language-(\w+)/)?.[1] || '';
11
+
12
+ if (typeof children !== 'string') return null;
13
+
14
+ if (lang === 'mermaid') {
15
+ return <Mermaid>{children}</Mermaid>;
16
+ }
17
+
18
+ if (lang === 'chart') {
12
19
  return <ChartBlock>{children}</ChartBlock>;
13
20
  }
14
21
 
15
- // 如果是 hmchart 类型的代码块,使用 HMChartBlock 组件
16
- if (match && match[1] === 'hmchart') {
22
+ if (lang === 'hmchart') {
17
23
  return <HMChartBlock>{children}</HMChartBlock>;
18
24
  }
19
25
 
20
- return (
21
- <div className="markdown-body-block-code">
22
- {match ? (
23
- <SyntaxHighlighter
24
- {...rest}
25
- style={vscDarkPlus}
26
- language={match?.[1]}
27
- showLineNumbers
28
- PreTag="div"
29
- wrapLongLines
30
- >
31
- {children}
32
- </SyntaxHighlighter>
33
- ) : (
34
- <code {...rest} className={className}>
35
- {children}
36
- </code>
37
- )}
38
- </div>
39
- );
40
- }
41
-
42
- export { CodeBlock };
26
+ return <CodeHighlighter lang={lang}>{children}</CodeHighlighter>;
27
+ });
28
+
29
+ export { CodeComponent };