@coding-flow/flow-design 0.1.2 → 0.1.4
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/README.md +7 -183
- package/dist/components/design-editor/node-components/strategy/advice.js +19 -0
- package/dist/components/design-editor/nodes/start/index.js +1 -2
- package/dist/components/design-panel/manager/form.js +2 -1
- package/dist/components/design-panel/tabs/setting.js +41 -4
- package/dist/components/design-panel/types.d.ts +1 -0
- package/dist/script-components/components/form-data/index.js +7 -3
- package/dist/script-components/components/form-data/store.d.ts +8 -2
- package/dist/script-components/components/form-data/store.js +6 -6
- package/dist/script-components/components/sub-process/index.js +1 -1
- package/dist/script-components/components/sub-process/presenters/sub-process-presenter.d.ts +13 -0
- package/dist/script-components/components/sub-process/presenters/sub-process-presenter.js +8 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/uuid.d.ts +7 -0
- package/dist/utils/uuid.js +16 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# @coding-flow/flow-
|
|
1
|
+
# @coding-flow/flow-design
|
|
2
2
|
|
|
3
|
-
Flow Engine
|
|
3
|
+
Flow Engine 流程设计器组件库,提供可视化流程设计、节点配置、属性面板、脚本配置等功能。
|
|
4
4
|
|
|
5
5
|
## 简介
|
|
6
6
|
|
|
7
|
-
`flow-
|
|
7
|
+
`flow-design` 是 Flow Engine 的流程设计器组件库,提供:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- 节点配置面板(
|
|
9
|
+
- 流程设计器(基于 @flowgram.ai 的可视化流程设计)
|
|
10
|
+
- 节点配置面板(19 种节点类型配置)
|
|
11
11
|
- 属性面板(节点属性编辑)
|
|
12
12
|
- 脚本配置器(Groovy 脚本编辑)
|
|
13
13
|
- 变量选择器
|
|
@@ -15,7 +15,7 @@ Flow Engine PC 端流程设计器组件库,提供节点配置、属性面板
|
|
|
15
15
|
|
|
16
16
|
### 依赖关系
|
|
17
17
|
|
|
18
|
-
- **依赖**: `@coding-flow/flow-core
|
|
18
|
+
- **依赖**: `@coding-flow/flow-core`、`@coding-flow/flow-types`、`@coding-flow/flow-icons`、`@coding-flow/flow-pc-ui`、`@flowgram.ai/fixed-layout-editor`、`@coding-script/script-engine`
|
|
19
19
|
|
|
20
20
|
## Setup
|
|
21
21
|
|
|
@@ -33,182 +33,6 @@ pnpm install
|
|
|
33
33
|
pnpm run build
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
监听模式构建:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
pnpm run dev
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## 核心功能
|
|
43
|
-
|
|
44
|
-
### 流程设计器
|
|
45
|
-
|
|
46
|
-
可视化流程设计器,支持:
|
|
47
|
-
|
|
48
|
-
- 节点拖拽添加
|
|
49
|
-
- 节点连线
|
|
50
|
-
- 节点配置
|
|
51
|
-
- 流程预览
|
|
52
|
-
- 流程校验
|
|
53
|
-
- 流程导入/导出
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { WorkflowDesigner } from '@coding-flow/flow-pc-design';
|
|
57
|
-
|
|
58
|
-
<WorkflowDesigner
|
|
59
|
-
workflow={workflow}
|
|
60
|
-
onChange={handleWorkflowChange}
|
|
61
|
-
onValidate={handleValidate}
|
|
62
|
-
/>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 节点配置
|
|
66
|
-
|
|
67
|
-
支持 15 种节点类型的配置:
|
|
68
|
-
|
|
69
|
-
**基础节点 (9 种)**:
|
|
70
|
-
- `StartNode` - 开始节点
|
|
71
|
-
- `EndNode` - 结束节点
|
|
72
|
-
- `ApprovalNode` - 审批节点
|
|
73
|
-
- `HandleNode` - 办理节点
|
|
74
|
-
- `NotifyNode` - 通知节点
|
|
75
|
-
- `RouterNode` - 路由节点
|
|
76
|
-
- `SubProcessNode` - 子流程节点
|
|
77
|
-
- `DelayNode` - 延迟节点
|
|
78
|
-
- `TriggerNode` - 触发节点
|
|
79
|
-
|
|
80
|
-
**块节点 (3 种)**:
|
|
81
|
-
- `ConditionNode` - 条件节点
|
|
82
|
-
- `ParallelNode` - 并行节点
|
|
83
|
-
- `InclusiveNode` - 包容节点
|
|
84
|
-
|
|
85
|
-
**分支节点 (3 种)**:
|
|
86
|
-
- `ConditionBranchNode` - 条件分支
|
|
87
|
-
- `ParallelBranchNode` - 并行分支
|
|
88
|
-
- `InclusiveBranchNode` - 包容分支
|
|
89
|
-
|
|
90
|
-
### 属性面板
|
|
91
|
-
|
|
92
|
-
节点属性编辑:
|
|
93
|
-
|
|
94
|
-
- 基本信息配置
|
|
95
|
-
- 审批人配置
|
|
96
|
-
- 表单权限配置
|
|
97
|
-
- 通知配置
|
|
98
|
-
- 超时策略配置
|
|
99
|
-
|
|
100
|
-
### 脚本配置器
|
|
101
|
-
|
|
102
|
-
Groovy 脚本编辑支持:
|
|
103
|
-
|
|
104
|
-
- 语法高亮
|
|
105
|
-
- 代码补全
|
|
106
|
-
- 语法检查
|
|
107
|
-
- 变量提示
|
|
108
|
-
- TypeScript/Groovy 转换
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
import { ScriptEditor } from '@coding-flow/flow-pc-design';
|
|
112
|
-
|
|
113
|
-
<ScriptEditor
|
|
114
|
-
value={script}
|
|
115
|
-
onChange={handleScriptChange}
|
|
116
|
-
scriptType="CONDITION"
|
|
117
|
-
variables={availableVariables}
|
|
118
|
-
/>
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### 变量选择器
|
|
122
|
-
|
|
123
|
-
流程变量选择:
|
|
124
|
-
|
|
125
|
-
- 表单字段变量
|
|
126
|
-
- 流程实例变量
|
|
127
|
-
- 系统内置变量
|
|
128
|
-
- 自定义变量
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
import { VariablePicker } from '@coding-flow/flow-pc-design';
|
|
132
|
-
|
|
133
|
-
<VariablePicker
|
|
134
|
-
variables={variables}
|
|
135
|
-
onSelect={handleVariableSelect}
|
|
136
|
-
filterTypes={['FORM_FIELD', 'INSTANCE']}
|
|
137
|
-
/>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### 策略配置
|
|
141
|
-
|
|
142
|
-
节点策略配置:
|
|
143
|
-
|
|
144
|
-
- 多人审批策略(会签/或签)
|
|
145
|
-
- 超时策略
|
|
146
|
-
- 通知策略
|
|
147
|
-
- 权限策略
|
|
148
|
-
|
|
149
|
-
## 模块结构
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
flow-pc-design/
|
|
153
|
-
├── src/
|
|
154
|
-
│ ├── designer/ # 流程设计器
|
|
155
|
-
│ ├── node-config/ # 节点配置组件
|
|
156
|
-
│ ├── property-panel/ # 属性面板
|
|
157
|
-
│ ├── script/ # 脚本编辑器
|
|
158
|
-
│ ├── variable/ # 变量选择器
|
|
159
|
-
│ ├── strategy/ # 策略配置
|
|
160
|
-
│ ├── components/ # 公共组件
|
|
161
|
-
│ └── index.ts # 统一导出
|
|
162
|
-
└── README.md
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## 使用示例
|
|
166
|
-
|
|
167
|
-
### 流程设计器
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
import { WorkflowDesigner } from '@coding-flow/flow-pc-design';
|
|
171
|
-
import type { Workflow } from '@coding-flow/flow-types';
|
|
172
|
-
|
|
173
|
-
const MyWorkflowDesigner = () => {
|
|
174
|
-
const [workflow, setWorkflow] = useState<Workflow>({ ... });
|
|
175
|
-
|
|
176
|
-
return (
|
|
177
|
-
<WorkflowDesigner
|
|
178
|
-
workflow={workflow}
|
|
179
|
-
onChange={setWorkflow}
|
|
180
|
-
onSave={handleSave}
|
|
181
|
-
onPreview={handlePreview}
|
|
182
|
-
/>
|
|
183
|
-
);
|
|
184
|
-
};
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### 脚本编辑器
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
import { ScriptEditor } from '@coding-flow/flow-pc-design';
|
|
191
|
-
import type { ScriptType } from '@coding-flow/flow-pc-design';
|
|
192
|
-
|
|
193
|
-
const MyScriptEditor = () => {
|
|
194
|
-
const [script, setScript] = useState('');
|
|
195
|
-
|
|
196
|
-
return (
|
|
197
|
-
<ScriptEditor
|
|
198
|
-
value={script}
|
|
199
|
-
onChange={setScript}
|
|
200
|
-
scriptType="CONDITION"
|
|
201
|
-
variables={variables}
|
|
202
|
-
onInsertVariable={(variable) => {
|
|
203
|
-
setScript(prev => prev + variable);
|
|
204
|
-
}}
|
|
205
|
-
/>
|
|
206
|
-
);
|
|
207
|
-
};
|
|
208
|
-
```
|
|
209
|
-
|
|
210
36
|
## Learn more
|
|
211
37
|
|
|
212
|
-
- [
|
|
213
|
-
- [Flow Engine Docs](https://github.com/codingapi/flow-engine) - 完整文档
|
|
214
|
-
- [CLAUDE.md](../../CLAUDE.md) - 开发指南
|
|
38
|
+
- [Flow Engine Docs](https://github.com/codingapi/flow-engine) - 完整文档
|
|
@@ -49,6 +49,25 @@ const AdviceStrategy = ()=>{
|
|
|
49
49
|
})
|
|
50
50
|
})
|
|
51
51
|
})
|
|
52
|
+
}),
|
|
53
|
+
/*#__PURE__*/ jsx(Form.Item, {
|
|
54
|
+
label: /*#__PURE__*/ jsx(FieldTip, {
|
|
55
|
+
label: "隐藏审批意见",
|
|
56
|
+
description: "开启后,审批时不展示审批意见输入框,仅弹框确认。"
|
|
57
|
+
}),
|
|
58
|
+
name: [
|
|
59
|
+
"AdviceStrategy",
|
|
60
|
+
"adviceHidden"
|
|
61
|
+
],
|
|
62
|
+
children: /*#__PURE__*/ jsx(Field, {
|
|
63
|
+
name: "AdviceStrategy.adviceHidden",
|
|
64
|
+
render: ({ field: { value, onChange } })=>/*#__PURE__*/ jsx(Fragment, {
|
|
65
|
+
children: /*#__PURE__*/ jsx(Switch, {
|
|
66
|
+
value: value,
|
|
67
|
+
onChange: onChange
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
})
|
|
52
71
|
})
|
|
53
72
|
]
|
|
54
73
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { generateUUID } from "../../../utils/uuid.js";
|
|
1
2
|
class WorkflowFormManager {
|
|
2
3
|
form;
|
|
3
4
|
formList;
|
|
@@ -45,7 +46,7 @@ class WorkflowFormManager {
|
|
|
45
46
|
} else list.push(field);
|
|
46
47
|
if (!exist) list.push({
|
|
47
48
|
...values,
|
|
48
|
-
id:
|
|
49
|
+
id: generateUUID()
|
|
49
50
|
});
|
|
50
51
|
const mainCode = this.form.code;
|
|
51
52
|
if (code === mainCode) return {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import react from "react";
|
|
3
|
+
import { InputNumber } from "antd";
|
|
3
4
|
import { CardForm, Panel } from "@coding-flow/flow-pc-ui";
|
|
5
|
+
import { FieldTip } from "../../field-tip/index.js";
|
|
4
6
|
import { InterferePanel } from "../panels/workflow/interfere.js";
|
|
5
7
|
import { UrgePanel } from "../panels/workflow/urge.js";
|
|
6
8
|
import { useDesignContext } from "../hooks/use-design-context.js";
|
|
@@ -12,22 +14,37 @@ const TabSetting = ()=>{
|
|
|
12
14
|
const workflowStrategyManager = new WorkflowStrategyManager();
|
|
13
15
|
const resetFieldsValue = ()=>{
|
|
14
16
|
const formData = workflowStrategyManager.toRender(state.workflow.strategies);
|
|
15
|
-
form.setFieldsValue(
|
|
17
|
+
form.setFieldsValue({
|
|
18
|
+
...formData,
|
|
19
|
+
maxNestDepth: state.workflow.maxNestDepth ?? 10
|
|
20
|
+
});
|
|
16
21
|
};
|
|
17
22
|
react.useEffect(()=>{
|
|
18
23
|
resetFieldsValue();
|
|
19
24
|
}, [
|
|
20
|
-
state.workflow.strategies
|
|
25
|
+
state.workflow.strategies,
|
|
26
|
+
state.workflow.maxNestDepth
|
|
21
27
|
]);
|
|
22
28
|
react.useEffect(()=>{
|
|
23
29
|
form.resetFields();
|
|
24
30
|
resetFieldsValue();
|
|
25
31
|
formActionContext.addAction({
|
|
26
|
-
save: ()=>
|
|
32
|
+
save: ()=>{
|
|
33
|
+
const formValues = form.getFieldsValue();
|
|
34
|
+
const strategyData = workflowStrategyManager.toData(formValues);
|
|
35
|
+
return {
|
|
36
|
+
...strategyData || {},
|
|
37
|
+
maxNestDepth: formValues.maxNestDepth
|
|
38
|
+
};
|
|
39
|
+
},
|
|
27
40
|
key: ()=>'setting',
|
|
28
41
|
validate: ()=>new Promise((resolve, reject)=>{
|
|
29
42
|
form.validateFields().then((values)=>{
|
|
30
|
-
|
|
43
|
+
const strategyData = workflowStrategyManager.toData(values);
|
|
44
|
+
resolve({
|
|
45
|
+
...strategyData || {},
|
|
46
|
+
maxNestDepth: values.maxNestDepth
|
|
47
|
+
});
|
|
31
48
|
}).catch(reject);
|
|
32
49
|
})
|
|
33
50
|
});
|
|
@@ -42,6 +59,26 @@ const TabSetting = ()=>{
|
|
|
42
59
|
}),
|
|
43
60
|
/*#__PURE__*/ jsx(UrgePanel, {
|
|
44
61
|
form: form
|
|
62
|
+
}),
|
|
63
|
+
/*#__PURE__*/ jsx(CardForm, {
|
|
64
|
+
form: form,
|
|
65
|
+
title: "循环防护配置",
|
|
66
|
+
children: /*#__PURE__*/ jsx(CardForm.Item, {
|
|
67
|
+
name: [
|
|
68
|
+
"maxNestDepth"
|
|
69
|
+
],
|
|
70
|
+
label: /*#__PURE__*/ jsx(FieldTip, {
|
|
71
|
+
label: "最大嵌套深度",
|
|
72
|
+
description: "子流程嵌套层数上限(默认 10)。运行期创建子流程时沿父链统计嵌套层数,超过该值将拒绝创建,用于兜底防护子流程创建自身/祖先流程等循环配置导致的无限递归。"
|
|
73
|
+
}),
|
|
74
|
+
children: /*#__PURE__*/ jsx(InputNumber, {
|
|
75
|
+
min: 1,
|
|
76
|
+
max: 100,
|
|
77
|
+
style: {
|
|
78
|
+
width: '100%'
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
})
|
|
45
82
|
})
|
|
46
83
|
]
|
|
47
84
|
});
|
|
@@ -2,7 +2,7 @@ import { Fragment, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import react from "react";
|
|
3
3
|
import { FormDataList } from "./components/list.js";
|
|
4
4
|
import { Provider } from "react-redux";
|
|
5
|
-
import {
|
|
5
|
+
import { createFormDataStore } from "./store.js";
|
|
6
6
|
import { FormDataContext } from "./context/index.js";
|
|
7
7
|
import { createFormDataContext, useFormDataContext } from "./hooks/use-form-data-context.js";
|
|
8
8
|
const FormDataContent = (props)=>{
|
|
@@ -28,12 +28,16 @@ const FormDataContextContent = (props)=>{
|
|
|
28
28
|
})
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
|
-
const FormDataReduxContent = (props)
|
|
32
|
-
|
|
31
|
+
const FormDataReduxContent = (props)=>{
|
|
32
|
+
const storeRef = react.useRef(void 0);
|
|
33
|
+
if (!storeRef.current) storeRef.current = createFormDataStore();
|
|
34
|
+
return /*#__PURE__*/ jsx(Provider, {
|
|
35
|
+
store: storeRef.current,
|
|
33
36
|
children: /*#__PURE__*/ jsx(FormDataContextContent, {
|
|
34
37
|
...props
|
|
35
38
|
})
|
|
36
39
|
});
|
|
40
|
+
};
|
|
37
41
|
const FormDataView = (props)=>{
|
|
38
42
|
const form = props.form;
|
|
39
43
|
if (form) return /*#__PURE__*/ jsx(FormDataReduxContent, {
|
|
@@ -5,11 +5,17 @@ export type FormDataStoreAction = {
|
|
|
5
5
|
};
|
|
6
6
|
export declare const formDataSlice: import("@reduxjs/toolkit").Slice<FormDataState, FormDataStoreAction, "formData", "formData", {}>;
|
|
7
7
|
export declare const updateState: import("@reduxjs/toolkit").ActionCreatorWithPayload<Partial<FormDataState> | ((prev: FormDataState) => Partial<FormDataState>), "formData/updateState">;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* 按实例创建表单数据 store。
|
|
10
|
+
* 每个 FormDataView 使用独立的 store,避免多个子流程配置项共享模块级单例 store
|
|
11
|
+
* 导致表单数据互相覆盖、输入时被刷新。
|
|
12
|
+
*/
|
|
13
|
+
export declare const createFormDataStore: () => import("@reduxjs/toolkit").EnhancedStore<{
|
|
9
14
|
formData: FormDataState;
|
|
10
15
|
}, import("redux").UnknownAction, import("@reduxjs/toolkit").Tuple<[import("redux").StoreEnhancer<{
|
|
11
16
|
dispatch: import("redux-thunk").ThunkDispatch<{
|
|
12
17
|
formData: FormDataState;
|
|
13
18
|
}, undefined, import("redux").UnknownAction>;
|
|
14
19
|
}>, import("redux").StoreEnhancer]>>;
|
|
15
|
-
export type
|
|
20
|
+
export type FormDataStore = ReturnType<typeof createFormDataStore>;
|
|
21
|
+
export type FormDataReduxState = ReturnType<FormDataStore['getState']>;
|
|
@@ -13,9 +13,9 @@ const formDataSlice = createSlice({
|
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
15
|
const { updateState } = formDataSlice.actions;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
});
|
|
21
|
-
export {
|
|
16
|
+
const createFormDataStore = ()=>configureStore({
|
|
17
|
+
reducer: {
|
|
18
|
+
formData: formDataSlice.reducer
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export { createFormDataStore, formDataSlice, updateState };
|
|
@@ -102,7 +102,7 @@ const SubProcessView = (props)=>{
|
|
|
102
102
|
const [form] = Form.useForm();
|
|
103
103
|
const subProcessPresenter = useSubProcessPresenter(props);
|
|
104
104
|
react.useEffect(()=>{
|
|
105
|
-
if (props.value) {
|
|
105
|
+
if (subProcessPresenter.isExternalChange(props.value)) {
|
|
106
106
|
const data = subProcessPresenter.parserScript(props.value);
|
|
107
107
|
form.resetFields();
|
|
108
108
|
form.setFieldsValue({
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { SubProcessFormValues, SubProcessViewProps } from "../typings";
|
|
2
2
|
export declare class SubProcessPresenter {
|
|
3
3
|
private readonly props;
|
|
4
|
+
/**
|
|
5
|
+
* 自身最后一次生成的脚本。
|
|
6
|
+
* 用于区分"自身编辑触发的脚本变更"与"外部脚本变更",
|
|
7
|
+
* 避免编辑回填表单后再次重置表单,导致输入时表单自动刷新。
|
|
8
|
+
*/
|
|
9
|
+
private lastEmittedScript?;
|
|
4
10
|
constructor(props: SubProcessViewProps);
|
|
11
|
+
/**
|
|
12
|
+
* 判断脚本变更是否来自外部(非自身编辑产生)。
|
|
13
|
+
* 仅外部变更才需要将脚本解析结果回填到表单。
|
|
14
|
+
*
|
|
15
|
+
* @param value 当前脚本内容
|
|
16
|
+
*/
|
|
17
|
+
isExternalChange(value: string | undefined): boolean;
|
|
5
18
|
parserScript(value: string): SubProcessFormValues;
|
|
6
19
|
updateScript(values: SubProcessFormValues): void;
|
|
7
20
|
private toFormData;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { GroovyScriptConvertorUtil } from "@coding-flow/flow-core";
|
|
2
2
|
class SubProcessPresenter {
|
|
3
3
|
props;
|
|
4
|
+
lastEmittedScript;
|
|
4
5
|
constructor(props){
|
|
5
6
|
this.props = props;
|
|
6
7
|
}
|
|
8
|
+
isExternalChange(value) {
|
|
9
|
+
if (!value) return false;
|
|
10
|
+
return value !== this.lastEmittedScript;
|
|
11
|
+
}
|
|
7
12
|
parserScript(value) {
|
|
8
13
|
const meta = GroovyScriptConvertorUtil.getScriptMeta(value);
|
|
9
14
|
if (!meta) return {
|
|
@@ -25,7 +30,9 @@ class SubProcessPresenter {
|
|
|
25
30
|
};
|
|
26
31
|
}
|
|
27
32
|
updateScript(values) {
|
|
28
|
-
this.
|
|
33
|
+
const script = this.toScript(values);
|
|
34
|
+
this.lastEmittedScript = script;
|
|
35
|
+
this.props.onChange(script);
|
|
29
36
|
}
|
|
30
37
|
toFormData(config) {
|
|
31
38
|
if (config.formData) {
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const generateUUID = ()=>{
|
|
2
|
+
if ("u" > typeof crypto && 'function' == typeof crypto.randomUUID) return crypto.randomUUID();
|
|
3
|
+
if ("u" > typeof crypto && 'function' == typeof crypto.getRandomValues) {
|
|
4
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
5
|
+
bytes[6] = 0x0f & bytes[6] | 0x40;
|
|
6
|
+
bytes[8] = 0x3f & bytes[8] | 0x80;
|
|
7
|
+
const hex = Array.from(bytes, (b)=>b.toString(16).padStart(2, '0')).join('');
|
|
8
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
9
|
+
}
|
|
10
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c)=>{
|
|
11
|
+
const r = 16 * Math.random() | 0;
|
|
12
|
+
const v = 'x' === c ? r : 0x3 & r | 0x8;
|
|
13
|
+
return v.toString(16);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
export { generateUUID };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coding-flow/flow-design",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "flow-engine design components ",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -54,16 +54,16 @@
|
|
|
54
54
|
"nanoid": "^5.1.6",
|
|
55
55
|
"react-redux": "^9.2.0",
|
|
56
56
|
"styled-components": "^5.3.11",
|
|
57
|
-
"@coding-flow/flow-
|
|
58
|
-
"@coding-flow/flow-
|
|
59
|
-
"@coding-flow/flow-
|
|
60
|
-
"@coding-flow/flow-
|
|
57
|
+
"@coding-flow/flow-types": "0.1.4",
|
|
58
|
+
"@coding-flow/flow-pc-ui": "0.1.4",
|
|
59
|
+
"@coding-flow/flow-core": "0.1.4",
|
|
60
|
+
"@coding-flow/flow-icons": "0.1.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/lodash-es": "^4.17.12",
|
|
64
64
|
"@types/styled-components": "^5.1.36",
|
|
65
|
-
"@coding-flow/flow-
|
|
66
|
-
"@coding-flow/flow-
|
|
65
|
+
"@coding-flow/flow-types": "0.1.4",
|
|
66
|
+
"@coding-flow/flow-core": "0.1.4"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"build": "rslib build",
|