@nocobase/client-v2 2.2.0-alpha.7 → 2.2.0-beta.10

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.
Files changed (50) hide show
  1. package/es/BaseApplication.d.ts +1 -1
  2. package/es/components/form/TypedVariableInput.d.ts +5 -31
  3. package/es/components/form/filter/CollectionFilter.d.ts +0 -2
  4. package/es/components/form/filter/CollectionFilterItem.d.ts +1 -11
  5. package/es/components/form/filter/CollectionFilterPanel.d.ts +0 -2
  6. package/es/components/form/filter/index.d.ts +0 -2
  7. package/es/components/form/filter/useFilterActionProps.d.ts +0 -2
  8. package/es/components/index.d.ts +0 -1
  9. package/es/flow/components/FieldAssignExactDatePicker.d.ts +0 -1
  10. package/es/flow/components/FieldAssignValueInput.d.ts +0 -3
  11. package/es/flow/components/RunJSValueEditor.d.ts +0 -1
  12. package/es/flow/index.d.ts +0 -1
  13. package/es/index.d.ts +0 -4
  14. package/es/index.mjs +99 -133
  15. package/es/utils/index.d.ts +0 -1
  16. package/lib/index.js +106 -140
  17. package/package.json +7 -8
  18. package/src/BaseApplication.tsx +6 -6
  19. package/src/__tests__/app.test.tsx +0 -26
  20. package/src/__tests__/browserChecker.test.ts +0 -61
  21. package/src/components/README.md +1 -7
  22. package/src/components/README.zh-CN.md +1 -6
  23. package/src/components/form/JsonTextArea.tsx +0 -4
  24. package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +2 -145
  25. package/src/components/form/ScanInput/useCodeScanner.ts +2 -154
  26. package/src/components/form/TypedVariableInput.tsx +98 -445
  27. package/src/components/form/__tests__/TypedVariableInput.test.tsx +9 -320
  28. package/src/components/form/filter/CollectionFilter.tsx +0 -4
  29. package/src/components/form/filter/CollectionFilterItem.tsx +7 -32
  30. package/src/components/form/filter/CollectionFilterPanel.tsx +0 -4
  31. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +0 -38
  32. package/src/components/form/filter/index.ts +0 -2
  33. package/src/components/form/filter/useFilterActionProps.ts +6 -37
  34. package/src/components/index.ts +0 -1
  35. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +1 -0
  36. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +6 -253
  37. package/src/flow/components/FieldAssignExactDatePicker.tsx +11 -25
  38. package/src/flow/components/FieldAssignValueInput.tsx +9 -55
  39. package/src/flow/components/RunJSValueEditor.tsx +1 -9
  40. package/src/flow/index.ts +0 -1
  41. package/src/index.ts +0 -4
  42. package/src/utils/index.tsx +0 -1
  43. package/es/components/category-tabs/SortableCategoryTabs.d.ts +0 -55
  44. package/es/components/category-tabs/index.d.ts +0 -9
  45. package/es/utils/getRouteRuntimeVersion.d.ts +0 -23
  46. package/src/__tests__/getRouteRuntimeVersion.test.ts +0 -68
  47. package/src/components/category-tabs/SortableCategoryTabs.tsx +0 -210
  48. package/src/components/category-tabs/index.ts +0 -10
  49. package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +0 -95
  50. package/src/utils/getRouteRuntimeVersion.ts +0 -185
@@ -11,58 +11,23 @@ import { FlowEngine, FlowEngineProvider } from '@nocobase/flow-engine';
11
11
  import { act, render, screen, waitFor } from '@testing-library/react';
12
12
  import React, { useEffect } from 'react';
13
13
  import { createMemoryRouter, RouterProvider, useParams } from 'react-router-dom';
14
- import { afterEach, describe, expect, it, vi } from 'vitest';
15
- import { NocoBaseDesktopRouteType, type NocoBaseDesktopRoute } from '../../../../flow-compat';
14
+ import { describe, expect, it, vi } from 'vitest';
16
15
  import type { LayoutDefinition } from '../../../../layout-manager/types';
17
16
  import { AdminLayoutComponent } from '../AdminLayoutComponent';
18
17
  import { AdminLayoutModel } from '../AdminLayoutModel';
19
- import { AdminLayoutMenuItemModel } from '../AdminLayoutMenuModels';
20
18
  import { AdminLayoutContent } from '../AdminLayoutSlotModels';
21
19
 
22
- const proLayoutLifecycle = vi.hoisted(() => ({
23
- events: [] as string[],
24
- routes: [] as Array<{ children?: Array<{ name?: React.ReactNode }> }>,
25
- }));
26
-
27
20
  vi.mock('@ant-design/pro-layout', async () => {
28
21
  const ReactModule = await import('react');
29
22
  const RouteContext = ReactModule.createContext({ isMobile: false });
30
- const ProLayoutMock = (props: {
31
- children?: React.ReactNode;
32
- route?: { children?: Array<{ name?: React.ReactNode }> };
33
- }) => {
34
- ReactModule.useEffect(() => {
35
- proLayoutLifecycle.events.push('pro-layout:mount');
36
- return () => {
37
- proLayoutLifecycle.events.push('pro-layout:unmount');
38
- };
39
- }, []);
40
- proLayoutLifecycle.routes.push(props.route || {});
41
23
 
42
- return ReactModule.createElement(
43
- RouteContext.Provider,
44
- { value: { isMobile: false } },
24
+ return {
25
+ default: (props: { children?: React.ReactNode }) =>
45
26
  ReactModule.createElement(
46
- 'div',
47
- { 'data-testid': 'pro-layout' },
48
- ReactModule.createElement(
49
- 'nav',
50
- { 'data-testid': 'pro-layout-menu' },
51
- (props.route?.children || []).map((item) =>
52
- ReactModule.createElement(
53
- 'span',
54
- { key: String(item.name), 'data-testid': 'pro-layout-menu-item' },
55
- item.name,
56
- ),
57
- ),
58
- ),
59
- props.children,
27
+ RouteContext.Provider,
28
+ { value: { isMobile: false } },
29
+ ReactModule.createElement('div', { 'data-testid': 'pro-layout' }, props.children),
60
30
  ),
61
- );
62
- };
63
-
64
- return {
65
- default: ProLayoutMock,
66
31
  RouteContext,
67
32
  };
68
33
  });
@@ -88,10 +53,6 @@ vi.mock('../AppListRender', () => ({
88
53
  useAppListRender: () => undefined,
89
54
  }));
90
55
 
91
- afterEach(() => {
92
- delete (window as Window & { __nocobase_modern_client_prefix__?: string }).__nocobase_modern_client_prefix__;
93
- });
94
-
95
56
  describe('AdminLayoutComponent', () => {
96
57
  it('keeps custom admin layout pages alive by layout route name', async () => {
97
58
  const layout: LayoutDefinition = {
@@ -224,212 +185,4 @@ describe('AdminLayoutComponent', () => {
224
185
 
225
186
  expect(deactivateLayout).toHaveBeenCalledTimes(1);
226
187
  });
227
-
228
- it('keeps layout content mounted when the menu route tree refreshes', async () => {
229
- proLayoutLifecycle.events = [];
230
- proLayoutLifecycle.routes = [];
231
- const layout: LayoutDefinition = {
232
- routeName: 'admin',
233
- routePath: '/admin',
234
- rootRouteName: 'admin',
235
- uid: 'admin-layout-model',
236
- layoutModelClass: 'AdminLayoutModel',
237
- rootPageModelClass: 'RootPageModel',
238
- childPageModelClass: 'ChildPageModel',
239
- authCheck: true,
240
- };
241
- const events: string[] = [];
242
- const engine = new FlowEngine();
243
- engine.context.defineProperty('routeRepository', {
244
- value: {
245
- activateLayout: vi.fn(() => vi.fn()),
246
- ensureAccessibleLoaded: vi.fn(async () => []),
247
- listAccessible: () => [],
248
- subscribe: vi.fn(),
249
- unsubscribe: vi.fn(),
250
- },
251
- });
252
- engine.context.defineProperty('t', {
253
- value: (key: string) => key,
254
- });
255
- const model = engine.createModel<AdminLayoutModel>({
256
- uid: layout.uid,
257
- use: AdminLayoutModel,
258
- props: {
259
- layout,
260
- },
261
- });
262
-
263
- const Page = () => {
264
- useEffect(() => {
265
- events.push('page:mount');
266
- return () => {
267
- events.push('page:unmount');
268
- };
269
- }, []);
270
-
271
- return <div data-testid="custom-admin-route">Workflow tasks</div>;
272
- };
273
-
274
- const router = createMemoryRouter(
275
- [
276
- {
277
- id: layout.routeName,
278
- path: layout.routePath,
279
- element: <AdminLayoutComponent model={model} />,
280
- children: [
281
- {
282
- id: 'admin.workflow.tasks',
283
- path: 'workflow/tasks/:taskType?/:status?/:popupId?',
284
- element: <Page />,
285
- },
286
- ],
287
- },
288
- ],
289
- {
290
- initialEntries: ['/admin/workflow/tasks/approval-apply/pending'],
291
- },
292
- );
293
-
294
- render(
295
- <FlowEngineProvider engine={engine}>
296
- <RouterProvider router={router} />
297
- </FlowEngineProvider>,
298
- );
299
-
300
- expect(await screen.findByTestId('custom-admin-route')).toBeInTheDocument();
301
- expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
302
-
303
- act(() => {
304
- model.refreshMenuRouteTree();
305
- });
306
-
307
- await act(async () => {
308
- await router.navigate('/admin/workflow/tasks/approval-apply/pending/1');
309
- });
310
-
311
- expect(screen.getByTestId('custom-admin-route')).toBeInTheDocument();
312
- expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
313
- expect(events).toEqual(['page:mount']);
314
- });
315
-
316
- it('updates ProLayout menu routes after accessible routes change without remounting the layout', async () => {
317
- proLayoutLifecycle.events = [];
318
- proLayoutLifecycle.routes = [];
319
- (window as Window & { __nocobase_modern_client_prefix__?: string }).__nocobase_modern_client_prefix__ = 'v2';
320
- const layout: LayoutDefinition = {
321
- routeName: 'admin',
322
- routePath: '/admin',
323
- rootRouteName: 'admin',
324
- uid: 'admin-layout-model',
325
- layoutModelClass: 'AdminLayoutModel',
326
- rootPageModelClass: 'RootPageModel',
327
- childPageModelClass: 'ChildPageModel',
328
- authCheck: true,
329
- };
330
- let accessibleRoutes: NocoBaseDesktopRoute[] = [
331
- {
332
- id: 1,
333
- title: 'Visible page',
334
- schemaUid: 'visible-page',
335
- type: NocoBaseDesktopRouteType.flowPage,
336
- },
337
- ];
338
- let routeRepositorySubscriber: (() => void) | undefined;
339
- const events: string[] = [];
340
- const engine = new FlowEngine();
341
- engine.registerModels({
342
- AdminLayoutMenuItemModel,
343
- });
344
- engine.context.defineProperty('routeRepository', {
345
- value: {
346
- activateLayout: vi.fn(() => vi.fn()),
347
- ensureAccessibleLoaded: vi.fn(async () => accessibleRoutes),
348
- listAccessible: () => accessibleRoutes,
349
- subscribe: vi.fn((subscriber: () => void) => {
350
- routeRepositorySubscriber = subscriber;
351
- }),
352
- unsubscribe: vi.fn(),
353
- },
354
- });
355
- engine.context.defineProperty('app', {
356
- value: {
357
- getPublicPath: () => '/v/',
358
- router: {
359
- getBasename: () => '/v',
360
- },
361
- },
362
- });
363
- engine.context.defineProperty('t', {
364
- value: (key: string) => key,
365
- });
366
- const model = engine.createModel<AdminLayoutModel>({
367
- uid: layout.uid,
368
- use: AdminLayoutModel,
369
- props: {
370
- layout,
371
- },
372
- });
373
-
374
- const Page = () => {
375
- useEffect(() => {
376
- events.push('page:mount');
377
- return () => {
378
- events.push('page:unmount');
379
- };
380
- }, []);
381
-
382
- return <div data-testid="custom-admin-route">Workflow tasks</div>;
383
- };
384
-
385
- const router = createMemoryRouter(
386
- [
387
- {
388
- id: layout.routeName,
389
- path: layout.routePath,
390
- element: <AdminLayoutComponent model={model} />,
391
- children: [
392
- {
393
- id: 'admin.workflow.tasks',
394
- path: 'workflow/tasks/:taskType?/:status?/:popupId?',
395
- element: <Page />,
396
- },
397
- ],
398
- },
399
- ],
400
- {
401
- initialEntries: ['/admin/workflow/tasks/approval-apply/pending'],
402
- },
403
- );
404
-
405
- render(
406
- <FlowEngineProvider engine={engine}>
407
- <RouterProvider router={router} />
408
- </FlowEngineProvider>,
409
- );
410
-
411
- expect(await screen.findByText('Visible page')).toBeInTheDocument();
412
- expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
413
-
414
- act(() => {
415
- accessibleRoutes = [];
416
- routeRepositorySubscriber?.();
417
- });
418
-
419
- await waitFor(() => {
420
- expect(screen.queryByText('Visible page')).not.toBeInTheDocument();
421
- });
422
-
423
- await act(async () => {
424
- await router.navigate('/admin/workflow/tasks/approval-apply/pending/1');
425
- });
426
-
427
- expect(screen.getByTestId('custom-admin-route')).toBeInTheDocument();
428
- expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
429
- expect(events).toEqual(['page:mount']);
430
- expect(
431
- proLayoutLifecycle.routes.some((route) => route.children?.some((item) => item.name === 'Visible page')),
432
- ).toBe(true);
433
- expect(proLayoutLifecycle.routes.at(-1)?.children?.some((item) => item.name === 'Visible page')).toBe(false);
434
- });
435
188
  });
@@ -7,7 +7,7 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- import React, { useCallback, useMemo, useState } from 'react';
10
+ import React, { useMemo, useState } from 'react';
11
11
  import { DatePicker, Select, Space } from 'antd';
12
12
  import { inferPickerType } from '../../flow-compat';
13
13
  import { dayjs, getDateTimeFormat, getPickerFormat } from '@nocobase/utils/client';
@@ -29,7 +29,6 @@ export interface FieldAssignExactDatePickerProps {
29
29
  isRange?: boolean;
30
30
  onChange?: (value: ExactDatePickerValue) => void;
31
31
  style?: React.CSSProperties;
32
- disabled?: boolean;
33
32
  }
34
33
 
35
34
  function getRawSingleValue(value: unknown, isRange: boolean): unknown {
@@ -115,7 +114,7 @@ function parseRangeValue(value: unknown, format: string): [dayjs.Dayjs, dayjs.Da
115
114
  }
116
115
 
117
116
  export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProps> = (props) => {
118
- const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style, disabled } = props;
117
+ const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style } = props;
119
118
  const flowCtx = useFlowContext();
120
119
  const t = flowCtx.model.translate.bind(flowCtx.model);
121
120
 
@@ -125,16 +124,16 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
125
124
  return inferPickerFromRawValue(rawSingleValue, picker);
126
125
  });
127
126
 
128
- const getResolvedFormat = useCallback(
129
- (nextPicker: ExactDatePickerMode) => {
130
- const baseFormat = nextPicker === picker && format ? format : getPickerFormat(nextPicker);
131
- const dateFormat = nextPicker === 'date' ? stripTimeFromFormat(baseFormat) : baseFormat;
132
- return getDateTimeFormat(nextPicker, dateFormat, showTime, timeFormat);
133
- },
134
- [format, picker, showTime, timeFormat],
135
- );
127
+ const getResolvedFormat = (nextPicker: ExactDatePickerMode) => {
128
+ const baseFormat = nextPicker === picker && format ? format : getPickerFormat(nextPicker);
129
+ const dateFormat = nextPicker === 'date' ? stripTimeFromFormat(baseFormat) : baseFormat;
130
+ return getDateTimeFormat(nextPicker, dateFormat, showTime, timeFormat);
131
+ };
136
132
 
137
- const resolvedFormat = useMemo(() => getResolvedFormat(targetPicker), [getResolvedFormat, targetPicker]);
133
+ const resolvedFormat = useMemo(
134
+ () => getResolvedFormat(targetPicker),
135
+ [targetPicker, format, picker, showTime, timeFormat],
136
+ );
138
137
 
139
138
  const singleValue = useMemo(() => {
140
139
  if (isRange) return null;
@@ -157,10 +156,6 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
157
156
  );
158
157
 
159
158
  const handlePickerTypeChange = (nextPicker: ExactDatePickerMode) => {
160
- if (disabled) {
161
- return;
162
- }
163
-
164
159
  setTargetPicker(nextPicker);
165
160
 
166
161
  if (!onChange) {
@@ -187,11 +182,7 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
187
182
  inputReadOnly: flowCtx.isMobileLayout,
188
183
  showTime: showTime ? { defaultValue: dayjs('00:00:00', 'HH:mm:ss') } : false,
189
184
  value: singleValue,
190
- disabled,
191
185
  onChange: (nextDate: dayjs.Dayjs | null) => {
192
- if (disabled) {
193
- return;
194
- }
195
186
  if (nextDate && dayjs.isDayjs(nextDate)) {
196
187
  onChange?.(nextDate);
197
188
  return;
@@ -209,11 +200,7 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
209
200
  inputReadOnly: flowCtx.isMobileLayout,
210
201
  showTime: showTime ? { defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')] } : false,
211
202
  value: rangeValue,
212
- disabled,
213
203
  onChange: (nextDates: [dayjs.Dayjs | null, dayjs.Dayjs | null] | null) => {
214
- if (disabled) {
215
- return;
216
- }
217
204
  if (Array.isArray(nextDates) && nextDates[0] && nextDates[1]) {
218
205
  onChange?.([nextDates[0], nextDates[1]]);
219
206
  return;
@@ -231,7 +218,6 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
231
218
  value={targetPicker}
232
219
  options={pickerOptions}
233
220
  onChange={handlePickerTypeChange}
234
- disabled={disabled}
235
221
  />
236
222
  {isRange ? <DatePicker.RangePicker {...rangePickerProps} /> : <DatePicker {...singlePickerProps} />}
237
223
  </Space.Compact>
@@ -341,10 +341,7 @@ interface Props {
341
341
  * 默认 false,保持历史行为。
342
342
  */
343
343
  enableDateVariableAsConstant?: boolean;
344
- /** 是否允许在变量选择器中使用 RunJS。默认 true,保持历史行为。 */
345
- allowRunJS?: boolean;
346
344
  maxAssociationFieldDepth?: number;
347
- disabled?: boolean;
348
345
  }
349
346
 
350
347
  type ResolvedFieldContext = {
@@ -715,9 +712,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
715
712
  preferFormItemFieldModel,
716
713
  associationFieldNamesOverride,
717
714
  enableDateVariableAsConstant = false,
718
- allowRunJS = true,
719
715
  maxAssociationFieldDepth = 2,
720
- disabled = false,
721
716
  }) => {
722
717
  const flowCtx = useFlowContext<FlowModelContext>();
723
718
  const normalizeEventValue = React.useCallback((eventOrValue: unknown) => {
@@ -1082,7 +1077,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1082
1077
  fm.setStepParams('selectSettings', 'fieldNames', { label: overrideLabel });
1083
1078
  }
1084
1079
  fm?.setProps?.({
1085
- disabled,
1080
+ disabled: false,
1086
1081
  readPretty: false,
1087
1082
  pattern: 'editable',
1088
1083
  updateAssociation: false,
@@ -1145,7 +1140,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1145
1140
  preferFormItemFieldModel,
1146
1141
  associationFieldNamesOverride?.label,
1147
1142
  associationFieldNamesOverride?.value,
1148
- disabled,
1149
1143
  ]);
1150
1144
 
1151
1145
  // 当传入 operator / operatorMetaList 时,按 operator schema 适配临时字段的输入组件与 props。
@@ -1198,9 +1192,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1198
1192
  React.useEffect(() => {
1199
1193
  const coercedValue = coerceEmptyValueForRenderer(inputProps?.value);
1200
1194
  const handleChange = (ev: any) => {
1201
- if (inputProps?.disabled) {
1202
- return;
1203
- }
1204
1195
  const nextRaw = normalizeEventValue(ev);
1205
1196
  const normalizedForStore = operator ? normalizeFilterValueByOperator(operator, nextRaw) : nextRaw;
1206
1197
  const nextValue = coerceEmptyValueForRenderer(normalizedForStore);
@@ -1232,7 +1223,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1232
1223
  value={inputProps?.value}
1233
1224
  onChange={(e) => inputProps?.onChange?.(normalizeEventValue(e))}
1234
1225
  placeholder={placeholder}
1235
- disabled={inputProps?.disabled}
1236
1226
  style={withFullWidthStyle(wrapperStyle)}
1237
1227
  />
1238
1228
  );
@@ -1251,7 +1241,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1251
1241
  const C: React.FC<any> = (inputProps) => {
1252
1242
  const wrapperStyle = pickStyle(inputProps?.style);
1253
1243
  const raw = inputProps?.value;
1254
- const isDisabled = Boolean(inputProps?.disabled);
1255
1244
  const parsed = isCtxDateExpression(raw) ? parseCtxDateExpression(raw) : raw;
1256
1245
  const parsedValue = typeof parsed === 'undefined' ? undefined : parsed;
1257
1246
  const { token } = theme.useToken();
@@ -1276,9 +1265,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1276
1265
  });
1277
1266
 
1278
1267
  const handleSelect = (val: string) => {
1279
- if (isDisabled) {
1280
- return;
1281
- }
1282
1268
  setOpen(false);
1283
1269
  if (val === 'exact') {
1284
1270
  inputProps?.onChange?.('');
@@ -1293,16 +1279,10 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1293
1279
  };
1294
1280
 
1295
1281
  const handleExactSingleChange = (nextValue: any) => {
1296
- if (isDisabled) {
1297
- return;
1298
- }
1299
1282
  inputProps?.onChange?.(nextValue || '');
1300
1283
  };
1301
1284
 
1302
1285
  const handleExactRangeChange = (nextValue: any) => {
1303
- if (isDisabled) {
1304
- return;
1305
- }
1306
1286
  inputProps?.onChange?.(nextValue || '');
1307
1287
  };
1308
1288
 
@@ -1347,11 +1327,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1347
1327
  <Select
1348
1328
  options={options}
1349
1329
  open={open}
1350
- onDropdownVisibleChange={(nextOpen) => {
1351
- if (!isDisabled) {
1352
- setOpen(nextOpen);
1353
- }
1354
- }}
1330
+ onDropdownVisibleChange={setOpen}
1355
1331
  allowClear={false}
1356
1332
  style={{
1357
1333
  width: '100%',
@@ -1361,18 +1337,13 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1361
1337
  value={selectedType}
1362
1338
  onChange={handleSelect}
1363
1339
  dropdownRender={dropdownRender}
1364
- disabled={isDisabled}
1365
1340
  />
1366
1341
  {['past', 'next'].includes(selectedType) && [
1367
1342
  <InputNumber
1368
1343
  key="number"
1369
1344
  style={{ flex: 1 }}
1370
1345
  value={(parsedValue as any)?.number}
1371
- disabled={isDisabled}
1372
1346
  onChange={(nextNumber) => {
1373
- if (isDisabled) {
1374
- return;
1375
- }
1376
1347
  inputProps?.onChange?.({
1377
1348
  ...(parsedValue as any),
1378
1349
  type: selectedType,
@@ -1385,11 +1356,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1385
1356
  key="unit"
1386
1357
  value={(parsedValue as any)?.unit}
1387
1358
  style={{ minWidth: 130, maxWidth: 140 }}
1388
- disabled={isDisabled}
1389
1359
  onChange={(nextUnit) => {
1390
- if (isDisabled) {
1391
- return;
1392
- }
1393
1360
  inputProps?.onChange?.({
1394
1361
  ...(parsedValue as any),
1395
1362
  type: selectedType,
@@ -1412,7 +1379,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1412
1379
  isRange={isRange}
1413
1380
  value={isRange ? exactRangeValue : exactSingleValue}
1414
1381
  onChange={isRange ? handleExactRangeChange : handleExactSingleChange}
1415
- disabled={isDisabled}
1416
1382
  style={{ flex: 1 }}
1417
1383
  />
1418
1384
  )}
@@ -1432,12 +1398,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1432
1398
 
1433
1399
  const RunJSComponent = React.useMemo(() => {
1434
1400
  const C: React.FC<any> = (inputProps) => (
1435
- <RunJSValueEditor
1436
- t={flowCtx.t}
1437
- value={inputProps?.value}
1438
- onChange={inputProps?.onChange}
1439
- disabled={inputProps?.disabled}
1440
- />
1401
+ <RunJSValueEditor t={flowCtx.t} value={inputProps?.value} onChange={inputProps?.onChange} />
1441
1402
  );
1442
1403
  return C;
1443
1404
  }, [flowCtx]);
@@ -1460,13 +1421,11 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1460
1421
  render: ConstantEditor,
1461
1422
  },
1462
1423
  { title: tExpr('Null'), name: 'null', type: 'object', paths: ['null'], render: NullComponent },
1463
- ...(allowRunJS
1464
- ? [{ title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent }]
1465
- : []),
1424
+ { title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent },
1466
1425
  ...limitedBase,
1467
1426
  ];
1468
1427
  };
1469
- }, [flowCtx, ConstantEditor, NullComponent, RunJSComponent, allowRunJS, maxAssociationFieldDepth]);
1428
+ }, [flowCtx, ConstantEditor, NullComponent, RunJSComponent, maxAssociationFieldDepth]);
1470
1429
 
1471
1430
  const displayValue = React.useMemo(() => {
1472
1431
  if (!useDateVariableConstant) {
@@ -1483,10 +1442,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1483
1442
 
1484
1443
  const handleVariableInputChange = React.useCallback(
1485
1444
  (nextValue: any) => {
1486
- if (disabled) {
1487
- return;
1488
- }
1489
-
1490
1445
  if (!useDateVariableConstant) {
1491
1446
  onChange(nextValue);
1492
1447
  return;
@@ -1494,7 +1449,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1494
1449
 
1495
1450
  onChange(normalizeDateVariableOutput(nextValue, dateVariableComponentProps));
1496
1451
  },
1497
- [dateVariableComponentProps, disabled, onChange, useDateVariableConstant],
1452
+ [dateVariableComponentProps, onChange, useDateVariableConstant],
1498
1453
  );
1499
1454
 
1500
1455
  if (!fieldPath) {
@@ -1509,13 +1464,12 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1509
1464
  metaTree={metaTree}
1510
1465
  style={{ width: '100%' }}
1511
1466
  clearValue={''}
1512
- disabled={disabled}
1513
1467
  converters={{
1514
1468
  renderInputComponent: (meta) => {
1515
1469
  const firstPath = meta?.paths?.[0];
1516
1470
  if (firstPath === 'constant') return ConstantEditor;
1517
1471
  if (firstPath === 'null') return NullComponent;
1518
- if (allowRunJS && firstPath === 'runjs') return RunJSComponent;
1472
+ if (firstPath === 'runjs') return RunJSComponent;
1519
1473
  return null;
1520
1474
  },
1521
1475
  resolveValueFromPath: (item) => {
@@ -1524,12 +1478,12 @@ export const FieldAssignValueInput: React.FC<Props> = ({
1524
1478
  return useDateVariableConstant ? { type: 'today' } : '';
1525
1479
  }
1526
1480
  if (firstPath === 'null') return null;
1527
- if (allowRunJS && firstPath === 'runjs') return { code: '', version: 'v2' };
1481
+ if (firstPath === 'runjs') return { code: '', version: 'v2' };
1528
1482
  return undefined;
1529
1483
  },
1530
1484
  resolvePathFromValue: (currentValue) => {
1531
1485
  if (currentValue === null) return ['null'];
1532
- if (allowRunJS && isRunJSValue(currentValue)) return ['runjs'];
1486
+ if (isRunJSValue(currentValue)) return ['runjs'];
1533
1487
  if (useDateVariableConstant && isCtxDateExpression(currentValue)) {
1534
1488
  return ['constant'];
1535
1489
  }
@@ -15,7 +15,6 @@ export interface RunJSValueEditorProps {
15
15
  t?: (key: string) => string;
16
16
  value?: unknown;
17
17
  onChange?: (value: RunJSValue) => void;
18
- disabled?: boolean;
19
18
  height?: string;
20
19
  scene?: string;
21
20
  containerStyle?: React.CSSProperties;
@@ -26,7 +25,6 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
26
25
  t,
27
26
  value,
28
27
  onChange,
29
- disabled,
30
28
  height = '200px',
31
29
  scene = 'formValue',
32
30
  containerStyle = { flex: 1, minWidth: 0 },
@@ -40,15 +38,9 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
40
38
  <div style={containerStyle}>
41
39
  <CodeEditor
42
40
  value={current.code}
43
- onChange={(code) => {
44
- if (disabled) {
45
- return;
46
- }
47
- onChange?.({ ...current, code });
48
- }}
41
+ onChange={(code) => onChange?.({ ...current, code })}
49
42
  version={current.version}
50
43
  height={height}
51
- readonly={disabled}
52
44
  enableLinter
53
45
  placeholder={placeholderText}
54
46
  scene={scene}
package/src/flow/index.ts CHANGED
@@ -98,7 +98,6 @@ export * from './FlowPage';
98
98
  export * from './models';
99
99
  export * from './utils';
100
100
  export * from './actions';
101
- export { FieldAssignValueInput } from './components/FieldAssignValueInput';
102
101
  export * from './system-settings';
103
102
  export * from './admin-shell/admin-layout';
104
103
  export * from './admin-shell/BaseLayoutModel';
package/src/index.ts CHANGED
@@ -30,8 +30,6 @@ export * from './layout-manager';
30
30
  export * from './hooks';
31
31
  export { default as languageCodes } from './locale/languageCodes';
32
32
  export * from './nocobase-buildin-plugin';
33
- export { getRouteRuntimeVersion } from './utils/getRouteRuntimeVersion';
34
- export type { RouteRuntimeVersion } from './utils/getRouteRuntimeVersion';
35
33
  export * from './collection-field-interface/CollectionFieldInterface';
36
34
  export * from './collection-field-interface/CollectionFieldInterfaceManager';
37
35
  export * from './collection-manager/field-configure';
@@ -42,8 +40,6 @@ export * from './collection-manager/template-fields';
42
40
  export * from './data-source';
43
41
  export * from './entry-actions';
44
42
  export * from './flow';
45
- export { CodeEditorExtension } from './flow/components/code-editor/extension';
46
- export type { CodeEditorExtra, CodeEditorExtraRegistry, EditorRef } from './flow/components/code-editor/types';
47
43
  export {
48
44
  DEFAULT_DATA_SOURCE_KEY,
49
45
  IconPicker,
@@ -11,7 +11,6 @@ import React, { ComponentType, FC } from 'react';
11
11
  import { BlankComponent } from '../components';
12
12
 
13
13
  export * from './appVersionHTML';
14
- export * from './getRouteRuntimeVersion';
15
14
 
16
15
  export function normalizeContainer(container: Element | ShadowRoot | string): Element | null {
17
16
  if (!container) {