@_tc/template-core 0.0.1-bate.37 → 0.0.1-bate.39

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 (164) hide show
  1. package/cjs/bundler/utils.js +13 -5
  2. package/cjs/packages/core/index.js +1 -1
  3. package/cjs/packages/core/loader/config.js +4 -2
  4. package/cjs/packages/core/loader/controller.js +2 -3
  5. package/cjs/packages/core/loader/extend.js +1 -2
  6. package/cjs/packages/core/loader/middleware.js +2 -3
  7. package/cjs/packages/core/loader/model.js +7 -3
  8. package/cjs/packages/core/loader/router-schema.js +4 -2
  9. package/cjs/packages/core/loader/router.js +10 -6
  10. package/cjs/packages/core/loader/service.js +2 -2
  11. package/cjs/packages/utils/runFileFn.js +46 -1
  12. package/esm/bundler/utils.js +13 -5
  13. package/esm/packages/core/index.js +1 -2
  14. package/esm/packages/core/loader/config.js +4 -3
  15. package/esm/packages/core/loader/controller.js +2 -4
  16. package/esm/packages/core/loader/extend.js +1 -3
  17. package/esm/packages/core/loader/middleware.js +2 -4
  18. package/esm/packages/core/loader/model.js +7 -4
  19. package/esm/packages/core/loader/router-schema.js +4 -3
  20. package/esm/packages/core/loader/router.js +10 -7
  21. package/esm/packages/core/loader/service.js +2 -3
  22. package/esm/packages/utils/runFileFn.js +47 -1
  23. package/fe/frontend/dash/Dashboard.js +11 -1
  24. package/fe/frontend/dash/dash.entry.js +19 -1
  25. package/fe/frontend/main.js +2 -0
  26. package/fe/frontend/widgets/common/CRUD/CRUD.js +1 -0
  27. package/fe/frontend/widgets/common/importComponent.js +1 -0
  28. package/fe/frontend/widgets/common/language.js +1 -0
  29. package/fe/frontend/widgets/common/menu.d.ts +12 -0
  30. package/fe/frontend/widgets/common/menu.js +21 -0
  31. package/fe/frontend/widgets/common/request.d.ts +3 -0
  32. package/fe/frontend/widgets/common/request.js +6 -0
  33. package/fe/frontend/widgets/components/BasePage/HeaderView.js +3 -1
  34. package/fe/frontend/widgets/defaultPages/Schema/components/CallCom/PopFrom.js +15 -0
  35. package/fe/frontend/widgets/defaultPages/Schema/components/SchemaSearch/index.js +5 -0
  36. package/fe/frontend/widgets/defaultPages/Schema/components/SchemaTable/index.js +13 -1
  37. package/fe/frontend/widgets/defaultPages/Schema/data/eventInfo.js +4 -4
  38. package/fe/frontend/widgets/defaultPages/Schema/index.js +7 -0
  39. package/fe/frontend/widgets/defaultPages/Schema/schemaType.d.ts +9 -0
  40. package/fe/frontend/widgets/defaultPages/Schema/stores/schemaEventBus.d.ts +19 -0
  41. package/fe/frontend/widgets/defaultPages/Schema/stores/schemaEventBus.js +4 -0
  42. package/fe/frontend/widgets/defaultPages/Schema/stores/schemaStore.d.ts +14 -0
  43. package/fe/frontend/widgets/defaultPages/Schema/stores/schemaStore.js +2 -0
  44. package/fe/frontend/widgets/defaultPages/Schema/utils/schemaConversion.js +43 -0
  45. package/fe/frontend/widgets/defaultPages/Schema/utils/validator.d.ts +3 -0
  46. package/fe/frontend/widgets/defaultPages/Schema/utils/validator.js +5 -0
  47. package/fe/frontend/widgets/defaultPages/SidebarSlotPage/SidebarSlotContainer.js +7 -0
  48. package/fe/frontend/widgets/defaultPages/SidebarSlotPage/index.js +1 -0
  49. package/fe/frontend/widgets/defaultPages/SlotPage/index.js +2 -0
  50. package/fe/frontend/widgets/hooks/useCurrentMenuData.d.ts +8 -0
  51. package/fe/frontend/widgets/hooks/useCurrentMenuData.js +8 -0
  52. package/fe/frontend/widgets/store/mode.d.ts +3 -0
  53. package/fe/frontend/widgets/store/mode.js +1 -0
  54. package/fe/model/types/data/button.d.ts +9 -0
  55. package/fe/model/types/data/button.js +15 -0
  56. package/fe/model/types/data/component.d.ts +24 -0
  57. package/fe/model/types/data/component.js +10 -0
  58. package/fe/model/types/data/fetchInfo.d.ts +12 -0
  59. package/fe/model/types/data/schema.d.ts +51 -0
  60. package/fe/model/types/menuType.d.ts +29 -0
  61. package/fe/model/types/model.d.ts +13 -0
  62. package/fe/packages/common/i18n/default.d.ts +5 -0
  63. package/fe/packages/common/i18n/default.js +5 -0
  64. package/fe/packages/common/i18n/en-US.d.ts +5 -0
  65. package/fe/packages/common/i18n/en-US.js +5 -0
  66. package/fe/packages/common/i18n/index.d.ts +24 -0
  67. package/fe/packages/common/i18n/index.js +31 -0
  68. package/fe/packages/common/i18n/types.d.ts +24 -0
  69. package/fe/packages/ui/react/components/Button/Button.d.ts +33 -0
  70. package/fe/packages/ui/react/components/Button/Button.js +3 -0
  71. package/fe/packages/ui/react/components/Button/SumbitButton.d.ts +4 -0
  72. package/fe/packages/ui/react/components/Button/SumbitButton.js +4 -0
  73. package/fe/packages/ui/react/components/ConfirmDialog/ConfirmDialog.d.ts +8 -0
  74. package/fe/packages/ui/react/components/DataTable/index.d.ts +19 -0
  75. package/fe/packages/ui/react/components/DataTable/index.js +4 -0
  76. package/fe/packages/ui/react/components/Date/Calendar.d.ts +13 -0
  77. package/fe/packages/ui/react/components/Date/Calendar.js +10 -1
  78. package/fe/packages/ui/react/components/Date/Date.d.ts +11 -0
  79. package/fe/packages/ui/react/components/Date/Date.js +19 -0
  80. package/fe/packages/ui/react/components/Date/LocaleContext.d.ts +4 -0
  81. package/fe/packages/ui/react/components/Date/LocaleContext.js +4 -0
  82. package/fe/packages/ui/react/components/Date/LocaleProvider.d.ts +11 -0
  83. package/fe/packages/ui/react/components/Date/LocaleProvider.js +11 -0
  84. package/fe/packages/ui/react/components/Date/TimePicker.js +1 -0
  85. package/fe/packages/ui/react/components/Date/dateLocaleStore.d.ts +6 -0
  86. package/fe/packages/ui/react/components/Date/locales.d.ts +19 -0
  87. package/fe/packages/ui/react/components/Date/locales.js +9 -0
  88. package/fe/packages/ui/react/components/Drawer/Drawer.d.ts +6 -0
  89. package/fe/packages/ui/react/components/Dropdown/Dropdown.d.ts +1 -0
  90. package/fe/packages/ui/react/components/Form/Form.d.ts +6 -0
  91. package/fe/packages/ui/react/components/Form/FormItem.d.ts +21 -0
  92. package/fe/packages/ui/react/components/Form/FormItem.js +8 -1
  93. package/fe/packages/ui/react/components/Form/SchemaForm/data.js +1 -0
  94. package/fe/packages/ui/react/components/Form/SchemaForm/index.d.ts +93 -0
  95. package/fe/packages/ui/react/components/Form/SchemaForm/index.js +5 -1
  96. package/fe/packages/ui/react/components/ImagePreview/ImagePreview.js +8 -0
  97. package/fe/packages/ui/react/components/ImagePreview/PreviewImage.d.ts +3 -0
  98. package/fe/packages/ui/react/components/Input/Input.d.ts +22 -0
  99. package/fe/packages/ui/react/components/Input/Input.js +3 -0
  100. package/fe/packages/ui/react/components/InputNumber/InputNumber.d.ts +2 -0
  101. package/fe/packages/ui/react/components/Label/Label.d.ts +29 -0
  102. package/fe/packages/ui/react/components/Label/Label.js +2 -0
  103. package/fe/packages/ui/react/components/Menu/Menu.js +4 -0
  104. package/fe/packages/ui/react/components/Menu/SubMenu.d.ts +7 -0
  105. package/fe/packages/ui/react/components/Menu/SubMenu.js +46 -1
  106. package/fe/packages/ui/react/components/Menu/menuTypes.d.ts +1 -0
  107. package/fe/packages/ui/react/components/Message/Message.d.ts +7 -0
  108. package/fe/packages/ui/react/components/Message/Message.js +3 -0
  109. package/fe/packages/ui/react/components/Message/MessageManager.js +8 -0
  110. package/fe/packages/ui/react/components/Modal/Modal.d.ts +6 -0
  111. package/fe/packages/ui/react/components/Modal/Modal.js +1 -0
  112. package/fe/packages/ui/react/components/Modal/ModalManager.d.ts +12 -0
  113. package/fe/packages/ui/react/components/Modal/ModalManager.js +4 -1
  114. package/fe/packages/ui/react/components/Overlay/Overlay.d.ts +3 -0
  115. package/fe/packages/ui/react/components/Pagination/Pagination.d.ts +7 -0
  116. package/fe/packages/ui/react/components/Pagination/Pagination.js +8 -1
  117. package/fe/packages/ui/react/components/Popup/Popup.js +14 -2
  118. package/fe/packages/ui/react/components/Search/Search.d.ts +3 -0
  119. package/fe/packages/ui/react/components/Select/Select.d.ts +5 -0
  120. package/fe/packages/ui/react/components/Select/Select.js +4 -0
  121. package/fe/packages/ui/react/components/Skeleton/Skeleton.d.ts +15 -0
  122. package/fe/packages/ui/react/components/Skeleton/Skeleton.js +1 -1
  123. package/fe/packages/ui/react/components/TableSearch/TableSearch.d.ts +37 -0
  124. package/fe/packages/ui/react/components/TableSearch/TableSearch.js +4 -1
  125. package/fe/packages/ui/react/components/Textarea/Textarea.d.ts +46 -0
  126. package/fe/packages/ui/react/components/Textarea/Textarea.js +1 -0
  127. package/fe/packages/ui/react/components/Tooltip/Tooltip.d.ts +16 -0
  128. package/fe/packages/ui/react/components/Tooltip/Tooltip.js +8 -0
  129. package/fe/packages/ui/react/components/TreeSelect/TreeSelect.d.ts +6 -0
  130. package/fe/packages/ui/react/components/TreeSelect/TreeSelect.js +6 -0
  131. package/fe/packages/ui/react/components/Upload/Upload.d.ts +27 -0
  132. package/fe/packages/ui/react/components/breadcrumb/breadcrumb.js +9 -0
  133. package/fe/packages/ui/react/components/hooks/useDropdownPositioning.d.ts +6 -0
  134. package/fe/packages/ui/react/components/hooks/useDropdownPositioning.js +14 -0
  135. package/fe/packages/ui/react/components/hooks/useInputController.d.ts +3 -0
  136. package/fe/packages/ui/react/components/hooks/useInputController.js +7 -0
  137. package/fe/packages/ui/react/components/testPage/MenuTestPage.js +3 -0
  138. package/fe/packages/ui/react/components/testPage/index.js +26 -0
  139. package/fe/packages/ui/react/hooks/useExecuteOnce.d.ts +19 -1
  140. package/fe/packages/ui/react/hooks/useExecuteOnce.js +22 -1
  141. package/fe/packages/ui/react/hooks/useRefState.d.ts +12 -0
  142. package/fe/packages/ui/react/hooks/useRefState.js +1 -0
  143. package/fe/packages/ui/react/hooks/useWatch.d.ts +8 -0
  144. package/fe/packages/ui/react/i18n/I18nProvider.d.ts +18 -0
  145. package/fe/packages/ui/react/i18n/useI18n.d.ts +4 -0
  146. package/fe/packages/ui/react/i18n/useI18n.js +4 -0
  147. package/fe/packages/ui/react/index.js +2 -0
  148. package/fe/packages/ui/react/lib/export.d.ts +44 -0
  149. package/fe/packages/ui/react/lib/export.js +40 -0
  150. package/fe/packages/ui/react/lib/utils.d.ts +24 -0
  151. package/fe/packages/ui/react/lib/utils.js +25 -0
  152. package/fe/packages/ui/react/stores/breadcrumb.js +2 -0
  153. package/model/index.d.ts +2 -0
  154. package/model/types/data/button.d.ts +32 -0
  155. package/model/types/data/component.d.ts +61 -0
  156. package/model/types/data/fetchInfo.d.ts +20 -0
  157. package/model/types/data/schema.d.ts +98 -0
  158. package/model/types/data/search.d.ts +7 -0
  159. package/model/types/index.d.ts +2 -0
  160. package/model/types/menuType.d.ts +73 -0
  161. package/model/types/model.d.ts +33 -0
  162. package/model/types/test.d.ts +2 -0
  163. package/package.json +10 -7
  164. package/types/packages/utils/runFileFn.d.ts +5 -3
@@ -10,19 +10,52 @@ export type { FieldProps, SchemaFormComponentPropsMap, SchemaFormFieldType, Sche
10
10
  export type FormFieldType = SchemaFormAllFieldType;
11
11
  type BaseField<T> = {
12
12
  [K in keyof T]: {
13
+ /**
14
+ * 字段名
15
+ */
13
16
  key: K | number | (K | number)[];
17
+ /**
18
+ * 标签文本
19
+ */
14
20
  label?: ReactNode;
21
+ /**
22
+ * 验证规则
23
+ */
15
24
  rules?: Rule[];
25
+ /**
26
+ * 是否必填(仅用于显示,实际验证通过 rules 配置)
27
+ */
16
28
  required?: boolean;
29
+ /**
30
+ * 表单项类名
31
+ */
17
32
  className?: string;
33
+ /**
34
+ * 标签类名
35
+ */
18
36
  labelClassName?: string;
37
+ /**
38
+ * 错误信息类名
39
+ */
19
40
  errorClassName?: string;
41
+ /**
42
+ * 是否显示错误信息
43
+ */
20
44
  showError?: boolean;
45
+ /**
46
+ * 自定义渲染函数
47
+ */
21
48
  render?: (value: T[K], onChange: (value: T[K]) => void, meta: {
22
49
  errors: string[];
23
50
  warnings: string[];
24
51
  }) => ReactNode;
52
+ /**
53
+ * field label 布局方向
54
+ */
25
55
  layout?: Required<LabelLayout>['layout'];
56
+ /**
57
+ * 插入到控件后边
58
+ */
26
59
  affterNode?: ReactNode;
27
60
  };
28
61
  }[keyof T];
@@ -34,22 +67,82 @@ type GroupField<T> = {
34
67
  type NotGroupField<T> = FieldProps & BaseField<T>;
35
68
  export type FormFieldSchema<T> = GroupField<T> | NotGroupField<T>;
36
69
  export interface SchemaFormProps<T = object> extends MOmit<FormProps<T>, 'initialValues' | 'children' | 'preserve'> {
70
+ /**
71
+ * 表单实例
72
+ */
37
73
  form?: FormInstance<T>;
74
+ /**
75
+ * 获取当前使用的form实例 只有挂载后会调用一次
76
+ */
38
77
  getForm?: (formInstance: FormInstance<T>) => void;
78
+ /**
79
+ * 表单配置方案
80
+ */
39
81
  schemas: FormFieldSchema<T>[];
82
+ /**
83
+ * 表单类名
84
+ */
40
85
  className?: string;
86
+ /**
87
+ * 提交回调
88
+ */
41
89
  onFinish?: (values: T) => void;
90
+ /**
91
+ * 提交失败回调
92
+ */
42
93
  onFinishFailed?: (errorInfo: any) => void;
94
+ /**
95
+ * 初始值
96
+ */
43
97
  initialValues?: T;
98
+ /**
99
+ * form 布局方向
100
+ *
101
+ * tips: horizontal 需自行实现提交按钮
102
+ */
44
103
  layout?: Required<LabelLayout>['layout'];
104
+ /**
105
+ * 统一配置 field layout
106
+ */
45
107
  fieldLayout?: Required<LabelLayout>['layout'];
108
+ /**
109
+ * - 是否显示提交和取消按钮
110
+ * - 或自定义按钮
111
+ * - tips button type submit 可直接触发提交
112
+ * @default true
113
+ */
46
114
  footerButtons?: boolean | ReactNode;
115
+ /**
116
+ * 提交按钮文本
117
+ * @default '提交'
118
+ */
47
119
  submitText?: ReactNode;
120
+ /**
121
+ * 取消按钮文本
122
+ * @default '取消'
123
+ */
48
124
  cancelText?: ReactNode;
125
+ /**
126
+ * 取消按钮回调
127
+ */
49
128
  onCancel?: () => void;
129
+ /**
130
+ * 按钮容器类名
131
+ */
50
132
  buttonClassName?: string;
133
+ /**
134
+ * 提交按钮属性
135
+ */
51
136
  submitButtonProps?: Omit<ButtonElementProps, 'type' | 'onClick' | 'children'>;
137
+ /**
138
+ * 取消按钮属性
139
+ */
52
140
  cancelButtonProps?: Omit<ButtonElementProps, 'onClick' | 'children'>;
141
+ /**
142
+ * 移除字段时保留值
143
+ *
144
+ * @default false
145
+ */
53
146
  preserve?: boolean;
54
147
  }
55
148
  export declare const SchemaForm: {
@@ -8,6 +8,7 @@ import { Skeleton } from '../../Skeleton';
8
8
  import { componentsMap } from './data';
9
9
  const renderField = (schema) => {
10
10
  return (value, onChange, meta) => {
11
+ // 如果提供了自定义渲染函数,优先使用
11
12
  if (schema.render) {
12
13
  return schema.render(value, onChange, meta);
13
14
  }
@@ -22,7 +23,9 @@ const renderField = (schema) => {
22
23
  return (_jsxs(Suspense, { fallback: _jsx(Skeleton, { mode: "componentsloading", rows: 2 }), children: [_jsx(ComponentRenderer, { value: value, onChange: onChange, ...fieldProps }), schema.affterNode] }));
23
24
  };
24
25
  };
25
- export const SchemaForm = ({ form, getForm, schemas, className, onFinish, onFinishFailed, initialValues, footerButtons = true, submitText, cancelText, onCancel, buttonClassName, submitButtonProps, layout = 'vertical', fieldLayout = 'vertical', cancelButtonProps, ...formProps }) => {
26
+ export const SchemaForm = ({ form, getForm, schemas, className, onFinish, onFinishFailed, initialValues, footerButtons = true, submitText, cancelText, onCancel, buttonClassName, submitButtonProps, layout = 'vertical', fieldLayout = 'vertical', cancelButtonProps,
27
+ // preserve = false,
28
+ ...formProps }) => {
26
29
  const t = useI18n();
27
30
  const [f] = useForm();
28
31
  const getFormRef = useRef(getForm);
@@ -36,6 +39,7 @@ export const SchemaForm = ({ form, getForm, schemas, className, onFinish, onFini
36
39
  onCancel();
37
40
  }
38
41
  else {
42
+ // 如果没有提供 onCancel,默认重置表单
39
43
  usedForm?.resetFields();
40
44
  }
41
45
  };
@@ -126,12 +126,20 @@ function PreviewCore({ images, initialIndex, onClose }) {
126
126
  if (!imgRef.current)
127
127
  return;
128
128
  const { naturalWidth, naturalHeight, clientWidth, clientHeight } = imgRef.current;
129
+ // 如果 lastScaleBeforeNatural 无值
130
+ // 第一次点击
131
+ // 将 scaleRef 复制给 lastScaleBeforeNatural
132
+ // 正常赋值
133
+ // 如果 lastScaleBeforeNatural 有值
134
+ // 则使用 lastScaleBeforeNatural
135
+ // 再清除 lastScaleBeforeNatural
129
136
  if (lastScaleBeforeNatural.current === null) {
130
137
  const scaleToNatural = Math.max(naturalWidth / Math.max(clientWidth, 1), naturalHeight / Math.max(clientHeight, 1), 1);
131
138
  lastScaleBeforeNatural.current = scaleRef.current;
132
139
  setScale(scaleToNatural);
133
140
  }
134
141
  else {
142
+ //
135
143
  setScale(lastScaleBeforeNatural.current);
136
144
  lastScaleBeforeNatural.current = null;
137
145
  }
@@ -1,6 +1,9 @@
1
1
  import type { MOmit } from '../../types';
2
2
  import { type ImagePreviewControllerProps } from './ImagePreview';
3
3
  export type PreviewImageProps = MOmit<ImagePreviewControllerProps, 'open' | 'onClose'> & Pick<Partial<ImagePreviewControllerProps>, 'onClose'> & {
4
+ /**
5
+ * 缩略图边长,默认 80px
6
+ */
4
7
  thumbSize?: number | string;
5
8
  direction?: 'horizontal' | 'vertical';
6
9
  };
@@ -1,22 +1,44 @@
1
1
  import type { ChangeEvent, InputHTMLAttributes, ReactNode } from 'react';
2
2
  export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'defaultValue'> & {
3
3
  value?: string;
4
+ /**
5
+ *
6
+ * @param v input value
7
+ * @param e changeEvent
8
+ */
4
9
  onChange?: (v: string, e: ChangeEvent<HTMLInputElement>) => void;
10
+ /**
11
+ * 只有初始化时会使用
12
+ * 如果会改变请使用value
13
+ */
5
14
  defaultValue?: string;
6
15
  allowClear?: boolean | {
7
16
  clearIcon: ReactNode;
8
17
  };
18
+ /** 输入框内部右侧按钮 */
9
19
  addonAfter?: ReactNode;
20
+ /** 原生 input 节点的自定义 className */
10
21
  inputClassName?: string;
11
22
  };
12
23
  declare const Input: import("react").ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue" | "onChange"> & {
13
24
  value?: string;
25
+ /**
26
+ *
27
+ * @param v input value
28
+ * @param e changeEvent
29
+ */
14
30
  onChange?: (v: string, e: ChangeEvent<HTMLInputElement>) => void;
31
+ /**
32
+ * 只有初始化时会使用
33
+ * 如果会改变请使用value
34
+ */
15
35
  defaultValue?: string;
16
36
  allowClear?: boolean | {
17
37
  clearIcon: ReactNode;
18
38
  };
39
+ /** 输入框内部右侧按钮 */
19
40
  addonAfter?: ReactNode;
41
+ /** 原生 input 节点的自定义 className */
20
42
  inputClassName?: string;
21
43
  } & import("react").RefAttributes<HTMLInputElement>>;
22
44
  export { Input };
@@ -10,6 +10,8 @@ const Input = forwardRef(({ className, inputClassName, type, value: controlledVa
10
10
  ref,
11
11
  });
12
12
  const isFileInput = type === 'file';
13
+ // 在change恒定时 不重复生成 fn
14
+ // isControlledRef setInternalValue 都是不会变的值
13
15
  const handleChange = useCallback((e) => {
14
16
  const newValue = e.target.value;
15
17
  if (!isFileInput && !isControlledRef.current) {
@@ -20,6 +22,7 @@ const Input = forwardRef(({ className, inputClassName, type, value: controlledVa
20
22
  const handleClear = useCallback((e) => {
21
23
  e.preventDefault();
22
24
  e.stopPropagation();
25
+ // 非受控时更新内部状态
23
26
  if (!isControlledRef.current) {
24
27
  setInternalValue('');
25
28
  }
@@ -9,6 +9,7 @@ export type InputNumberProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'defa
9
9
  };
10
10
  addonAfter?: ReactNode;
11
11
  allowStep?: boolean;
12
+ /** 原生 input 节点的自定义 className */
12
13
  inputClassName?: string;
13
14
  };
14
15
  declare const InputNumber: import("react").ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "type" | "defaultValue" | "onChange" | "step"> & InputNumberConstraints & {
@@ -20,6 +21,7 @@ declare const InputNumber: import("react").ForwardRefExoticComponent<Omit<InputH
20
21
  };
21
22
  addonAfter?: ReactNode;
22
23
  allowStep?: boolean;
24
+ /** 原生 input 节点的自定义 className */
23
25
  inputClassName?: string;
24
26
  } & import("react").RefAttributes<HTMLInputElement>>;
25
27
  export { InputNumber };
@@ -4,17 +4,46 @@ type VerticalLayout = {
4
4
  };
5
5
  type HorizontalLayout = {
6
6
  layout?: 'horizontal';
7
+ /**
8
+ * 标签宽度
9
+ * @default 'auto'
10
+ */
7
11
  labelWidth?: string | number;
12
+ /**
13
+ * 标签对齐方式
14
+ * @default 'left'
15
+ */
8
16
  labelAlign?: 'left' | 'right' | 'center';
9
17
  };
10
18
  export type LabelLayout = HorizontalLayout | VerticalLayout;
11
19
  export type LabelProps = {
20
+ /**
21
+ * 标签文本
22
+ */
12
23
  label: ReactNode;
24
+ /**
25
+ * 标签内容
26
+ */
13
27
  children: ReactNode;
28
+ /**
29
+ * 是否必填(显示红色星号)
30
+ */
14
31
  required?: boolean;
32
+ /**
33
+ * 标签的 htmlFor 属性
34
+ */
15
35
  htmlFor?: string;
36
+ /**
37
+ * 容器类名
38
+ */
16
39
  className?: string;
40
+ /**
41
+ * 标签类名
42
+ */
17
43
  labelClassName?: string;
44
+ /**
45
+ * 内容区域类名
46
+ */
18
47
  contentClassName?: string;
19
48
  } & LabelLayout;
20
49
  declare const Label: import("react").ForwardRefExoticComponent<LabelProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from '../../lib/utils';
3
3
  import { forwardRef, useMemo } from 'react';
4
+ // 标签对齐样式
4
5
  const labelAlignStyles = {
5
6
  left: 'text-left',
6
7
  right: 'text-right',
@@ -9,6 +10,7 @@ const labelAlignStyles = {
9
10
  const Label = forwardRef((props, ref) => {
10
11
  const { label, children, layout = 'vertical', required = false, htmlFor, className, labelClassName, contentClassName, } = props;
11
12
  const isVertical = layout === 'vertical';
13
+ // 标签样式
12
14
  const labelStyles = cn('text-sm font-medium text-foreground', required && "before:content-['*'] before:pt-1 before:mr-0.5 before:text-destructive", labelClassName);
13
15
  const { usedClassName, labelWidth } = useMemo(() => {
14
16
  let usedLabelWidth;
@@ -19,6 +19,10 @@ export const CollapseToggle = forwardRef(({ className }, ref) => {
19
19
  const onCollapse = useMenuStore((s) => s.onCollapse);
20
20
  const propsCollapsed = useMenuStore((s) => s.propsCollapsed);
21
21
  const shouldShowCollapseToggle = () => {
22
+ /**
23
+ * 传入 collapsed 且没有 onCollapse 时,表示折叠状态完全由外部控制。
24
+ * 内部控制器无法改变状态,因此不渲染。
25
+ */
22
26
  if (typeof propsCollapsed !== "undefined" &&
23
27
  typeof onCollapse === "undefined") {
24
28
  return false;
@@ -1,3 +1,10 @@
1
1
  import type { SubMenuProps } from "./menuTypes";
2
+ /**
3
+ * 渲染带子菜单的 Menu 项。
4
+ *
5
+ * 根据当前 menu mode、收起状态、是否在弹出层内,决定子菜单是内嵌展开还是 Popup 弹出。
6
+ *
7
+ * @returns SubMenu 完整节点,包含触发区域和子菜单内容。
8
+ */
2
9
  export declare function SubMenu({ eventKey, label, icon, disabled, popup: forcePopup, parentKey, children, }: SubMenuProps): import("react/jsx-runtime").JSX.Element;
3
10
  //# sourceMappingURL=SubMenu.d.ts.map
@@ -7,6 +7,11 @@ import { CollapsedContext, useMenuStore } from "./MenuContext";
7
7
  import { getFirstChar } from "./utils";
8
8
  const SUBMENU_POPUP_OFFSET = 12;
9
9
  const SubMenuLevelContext = createContext(0);
10
+ /**
11
+ * 计算 top 模式下,二级及更深层 submenu 的弹出位置。
12
+ *
13
+ * @returns 优先放在右侧;右侧空间不够时,改放到左侧。
14
+ */
10
15
  const getTopNestedSubMenuPosition = ({ anchorRect, contentRect, viewportWidth, offset, matchAnchorWidth, }) => {
11
16
  const width = contentRect?.width ?? 0;
12
17
  const rightLeft = anchorRect.right + offset;
@@ -19,11 +24,25 @@ const getTopNestedSubMenuPosition = ({ anchorRect, contentRect, viewportWidth, o
19
24
  width: matchAnchorWidth ? anchorRect.width : undefined,
20
25
  };
21
26
  };
27
+ /**
28
+ * 判断当前 SubMenu 的子节点里,有没有选中的菜单项。
29
+ *
30
+ * @param children SubMenu 下面渲染出来的菜单节点。
31
+ * @param targetKey 当前选中的 key。
32
+ * @returns 子孙节点里命中选中 key 时返回 true。
33
+ */
22
34
  function hasDescendantSelected(children, targetKey) {
23
35
  if (!targetKey)
24
36
  return false;
25
37
  return walkReactChildren(children, targetKey);
26
38
  }
39
+ /**
40
+ * 递归遍历 React children,查找指定 eventKey。
41
+ *
42
+ * @param node 当前要检查的 React 节点。
43
+ * @param targetKey 要查找的 eventKey。
44
+ * @returns 当前节点或子孙节点命中时返回 true。
45
+ */
27
46
  function walkReactChildren(node, targetKey) {
28
47
  if (!node)
29
48
  return false;
@@ -38,6 +57,11 @@ function walkReactChildren(node, targetKey) {
38
57
  }
39
58
  return false;
40
59
  }
60
+ /**
61
+ * 渲染 SubMenu 的触发区域,也就是能点击/hover 的那一行。
62
+ *
63
+ * @returns SubMenu trigger 节点。
64
+ */
41
65
  function SubMenuItem({ triggerRef, onClick, icon, label, disabled, collapsed, descendantSelected, ArrowIcon, showArrow, setPopupContentRef, mode, }) {
42
66
  const collapsedLabelTooltip = useMenuStore((s) => s.collapsedLabelTooltip);
43
67
  return (_jsxs("div", { ref: triggerRef, onClick: onClick, className: cn("subMenuItem group relative flex items-center rounded-lg text-sm transition-all", "select-none", mode === "top" &&
@@ -50,6 +74,13 @@ function SubMenuItem({ triggerRef, onClick, icon, label, disabled, collapsed, de
50
74
  ? "bg-theme/10 text-theme"
51
75
  : "text-muted-foreground group-hover:text-foreground"), children: icon })), !collapsed && _jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), collapsed && !icon && collapsedLabelTooltip && (_jsx("span", { className: "absolute left-0 right-0 top-0 flex h-full items-center justify-center text-[10px]", children: getFirstChar(label) })), !collapsed && showArrow && (_jsx(ArrowIcon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground transition-transform group-hover:text-foreground" })), _jsx("div", { ref: setPopupContentRef })] }));
52
76
  }
77
+ /**
78
+ * 渲染带子菜单的 Menu 项。
79
+ *
80
+ * 根据当前 menu mode、收起状态、是否在弹出层内,决定子菜单是内嵌展开还是 Popup 弹出。
81
+ *
82
+ * @returns SubMenu 完整节点,包含触发区域和子菜单内容。
83
+ */
53
84
  export function SubMenu({ eventKey, label, icon, disabled, popup: forcePopup, parentKey, children, }) {
54
85
  const mode = useMenuStore((s) => s.mode);
55
86
  const expandTrigger = useMenuStore((s) => s.expandTrigger);
@@ -64,7 +95,9 @@ export function SubMenu({ eventKey, label, icon, disabled, popup: forcePopup, pa
64
95
  const popupContentRef = useRef(null);
65
96
  const [popupContainer, setPopupContainer] = useState(undefined);
66
97
  const [popupOpen, setPopupOpen] = useState(false);
98
+ // 处于弹出层内:store 已收起但 context 被覆盖为 false
67
99
  const isInsidePopup = storeCollapsed && !collapsed;
100
+ // mode=top always popup; left+collapsed always popup; inside popup -> popup; else check popup flag
68
101
  const usePopup = mode === "top" ||
69
102
  (mode === "left" && collapsed) ||
70
103
  isInsidePopup ||
@@ -119,6 +152,18 @@ export function SubMenu({ eventKey, label, icon, disabled, popup: forcePopup, pa
119
152
  const popupPlacement = mode === "top" && level === 0 ? "bottom-start" : "right-start";
120
153
  const popupStrategy = mode === "top" && level > 0 ? getTopNestedSubMenuPosition : undefined;
121
154
  const hoverBridgePlacement = mode === "top" && level > 0 ? "horizontal" : "auto";
122
- const subMenuContent = (_jsx("div", { className: cn(" rounded-xl bg-muted p-2 shadow-[0_18px_44px_rgba(15,23,42,0.14),0_4px_12px_rgba(15,23,42,0.08)]"), children: _jsx(SubMenuLevelContext.Provider, { value: level + 1, children: _jsx("div", { className: "flex flex-col gap-1", children: children }) }) }));
155
+ const subMenuContent = (_jsx("div", { className: cn(
156
+ // "min-w-[180px]",
157
+ " rounded-xl bg-muted p-2 shadow-[0_18px_44px_rgba(15,23,42,0.14),0_4px_12px_rgba(15,23,42,0.08)]"), children: _jsx(SubMenuLevelContext.Provider, { value: level + 1, children: _jsx("div", { className: "flex flex-col gap-1", children: children }) }) }));
158
+ /**
159
+ *
160
+ * submenu 生成的节点是 1 menuItem
161
+ * submenu「
162
+ * 1-1
163
+ * 1-2
164
+ * 」
165
+ *
166
+ * 所以判断鼠标是否在区域内应该是 监听 submenu 的根节点
167
+ */
123
168
  return (_jsxs("div", { className: "submenu", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [_jsx(SubMenuItem, { triggerRef: triggerRef, onClick: handleTriggerClick, icon: icon, label: label, disabled: disabled, collapsed: collapsed, descendantSelected: descendantSelected, ArrowIcon: ArrowIcon, showArrow: showArrow, setPopupContentRef: setPopupContentRef, mode: mode }), usePopup ? (_jsx(Popup, { open: popupOpen, anchorRef: triggerRef, placement: popupPlacement, offset: SUBMENU_POPUP_OFFSET, hoverBridge: SUBMENU_POPUP_OFFSET, onOpenChange: setPopupOpen, container: popupContainer, strategy: popupStrategy, hoverBridgePlacement: hoverBridgePlacement, className: "border-0 bg-transparent p-0 shadow-none", children: _jsx(CollapsedContext.Provider, { value: false, children: subMenuContent }) })) : (isOpen && (_jsx("div", { className: "ml-4 pl-2 pt-1", children: _jsx(SubMenuLevelContext.Provider, { value: level + 1, children: _jsx("div", { className: "flex flex-col gap-1", children: children }) }) })))] }));
124
169
  }
@@ -28,6 +28,7 @@ export interface MenuProps {
28
28
  defaultCollapsed?: boolean;
29
29
  onCollapse?: (collapsed: boolean) => void;
30
30
  collapsedWidth?: number;
31
+ /** 收起时无 icon 的项是否通过 tooltip 显示完整名称,默认 true */
31
32
  collapsedLabelTooltip?: boolean;
32
33
  }
33
34
  export interface SubMenuProps {
@@ -4,8 +4,15 @@ export type MessageProps = {
4
4
  type?: MessageType;
5
5
  content?: ReactNode;
6
6
  children?: ReactNode;
7
+ /**
8
+ * 存在时间
9
+ * @default 3000ms
10
+ */
7
11
  duration?: number;
8
12
  onClose?: () => void;
13
+ /**
14
+ * 可手动关闭
15
+ */
9
16
  closable?: boolean;
10
17
  className?: string;
11
18
  };
@@ -33,10 +33,12 @@ export function Message({ type = 'info', content, children, duration = DEFAULT_D
33
33
  const iconColor = typeConfig[type].color;
34
34
  const handleClose = () => {
35
35
  setVisible(false);
36
+ // 等待动画完成后再调用 onClose
36
37
  setTimeout(() => {
37
38
  onClose?.();
38
39
  }, 200);
39
40
  };
41
+ // 自动关闭
40
42
  useEffect(() => {
41
43
  if (duration > 0) {
42
44
  timerRef.current = setTimeout(() => {
@@ -48,6 +50,7 @@ export function Message({ type = 'info', content, children, duration = DEFAULT_D
48
50
  clearTimeout(timerRef.current);
49
51
  }
50
52
  };
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
51
54
  }, [duration]);
52
55
  if (!visible)
53
56
  return null;
@@ -12,17 +12,20 @@ class MessageManagerClass {
12
12
  init() {
13
13
  if (typeof document === 'undefined' || this.container)
14
14
  return;
15
+ // 可见消息容器
15
16
  this.container = document.createElement('div');
16
17
  this.container.id = 'message-container';
17
18
  this.container.className = 'fixed top-4 left-1/2 z-[10000] flex flex-col items-center gap-2 pointer-events-none';
18
19
  this.container.style.transform = 'translateX(-50%)';
19
20
  document.body.appendChild(this.container);
21
+ // 屏幕外消息容器 保留回调触发
20
22
  this.offScreenContainer = document.createElement('div');
21
23
  this.offScreenContainer.id = 'message-offscreen-container';
22
24
  this.offScreenContainer.className =
23
25
  'fixed -left-[9999px] top-0 z-[10000] flex flex-col items-center gap-2 pointer-events-none';
24
26
  this.offScreenContainer.setAttribute('aria-hidden', 'true');
25
27
  document.body.appendChild(this.offScreenContainer);
28
+ // 创建 React 根节点
26
29
  this.root = createRoot(this.container);
27
30
  this.offScreenRoot = createRoot(this.offScreenContainer);
28
31
  this.render();
@@ -32,13 +35,17 @@ class MessageManagerClass {
32
35
  return;
33
36
  const messages = Array.from(this.messages.values());
34
37
  const totalCount = messages.length;
38
+ // 可见消息:最后 maxCount 条
35
39
  const displayMessages = totalCount > this.maxCount ? messages.slice(-this.maxCount) : messages;
40
+ // 屏幕外消息:除了最后 maxCount 条之外的所有消息
36
41
  const offScreenMessages = totalCount > this.maxCount ? messages.slice(0, -this.maxCount) : [];
37
42
  const now = Date.now();
43
+ // 渲染可见消息
38
44
  this.root.render(_jsx(_Fragment, { children: displayMessages.map((message) => (_jsx(Message, { ...message, duration: message.expirationTime - now, content: message.content, onClose: () => {
39
45
  message.onClose?.();
40
46
  this.close(message.id);
41
47
  } }, message.id))) }));
48
+ // 渲染屏幕外消息
42
49
  this.offScreenRoot.render(_jsx(_Fragment, { children: offScreenMessages.map((message) => (_jsx(Message, { ...message, duration: message.expirationTime - now, content: message.content, onClose: () => {
43
50
  message.onClose?.();
44
51
  this.close(message.id);
@@ -70,6 +77,7 @@ class MessageManagerClass {
70
77
  this.maxCount = count;
71
78
  }
72
79
  }
80
+ // 单例模式
73
81
  export const messageManager = new MessageManagerClass();
74
82
  export const message = {
75
83
  success: (content, config) => messageManager.show({ content, ...config }, 'success'),
@@ -14,7 +14,13 @@ export type ModalProps = {
14
14
  width?: number | string;
15
15
  centered?: boolean;
16
16
  zIndex?: number;
17
+ /**
18
+ * @default document.body
19
+ */
17
20
  renderNode?: HTMLElement | (() => HTMLElement);
21
+ /**
22
+ * 是否支持键盘关闭 默认开启
23
+ */
18
24
  keyboard?: boolean;
19
25
  };
20
26
  export declare function Modal({ open, onClose, title, children, footer, className, contentClassName, mask, maskClosable, lockScroll, closable, width, centered, renderNode, keyboard, zIndex, }: ModalProps): import("react/jsx-runtime").JSX.Element;
@@ -6,6 +6,7 @@ import { Button } from '../Button';
6
6
  import { Overlay } from '../Overlay';
7
7
  export function Modal({ open = false, onClose, title, children, footer, className, contentClassName, mask = true, maskClosable = true, lockScroll = true, closable = true, width = 520, centered = true, renderNode, keyboard = true, zIndex = 1000, }) {
8
8
  const t = useI18n();
9
+ // 点击内容区域阻止冒泡
9
10
  const handleContentClick = (e) => {
10
11
  e.stopPropagation();
11
12
  };
@@ -22,22 +22,34 @@ declare class ModalManagerClass {
22
22
  }
23
23
  type OpenModalConfig = Omit<ModalConfig, 'id'>;
24
24
  export declare const openConfirmModal: (pConfig: Pick<OpenModalConfig, "content"> & {
25
+ /** 标题 */
25
26
  title?: ReactNode;
27
+ /** 内容 */
26
28
  content: ReactNode;
29
+ /** 确认按钮文本 */
27
30
  okText?: string;
31
+ /** 取消按钮文本 */
28
32
  cancelText?: string;
33
+ /** 确认回调 */
29
34
  onOk?: SumbitButtonProps["onClick"];
35
+ /** 取消回调 */
30
36
  onCancel?: () => void;
31
37
  }) => string;
32
38
  export declare const modalManager: ModalManagerClass;
33
39
  export declare const modal: {
34
40
  open: (config: OpenModalConfig) => string;
35
41
  confirm: (pConfig: Pick<OpenModalConfig, "content"> & {
42
+ /** 标题 */
36
43
  title?: ReactNode;
44
+ /** 内容 */
37
45
  content: ReactNode;
46
+ /** 确认按钮文本 */
38
47
  okText?: string;
48
+ /** 取消按钮文本 */
39
49
  cancelText?: string;
50
+ /** 确认回调 */
40
51
  onOk?: SumbitButtonProps["onClick"];
52
+ /** 取消回调 */
41
53
  onCancel?: () => void;
42
54
  }) => string;
43
55
  close: (id: string) => void;
@@ -14,6 +14,7 @@ class ModalManagerClass {
14
14
  this.container = document.createElement('div');
15
15
  this.container.id = 'modal-container';
16
16
  document.body.appendChild(this.container);
17
+ // 创建 React 根节点
17
18
  this.root = createRoot(this.container);
18
19
  this.render();
19
20
  }
@@ -28,7 +29,7 @@ class ModalManagerClass {
28
29
  };
29
30
  }
30
31
  open(config) {
31
- this.init();
32
+ this.init(); // 确保已初始化
32
33
  const id = `modal-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
33
34
  const modalConfig = {
34
35
  ...config,
@@ -78,7 +79,9 @@ export const openConfirmModal = (pConfig) => {
78
79
  const currentModalId = modalManager.open(config);
79
80
  return currentModalId;
80
81
  };
82
+ // 单例模式
81
83
  export const modalManager = new ModalManagerClass();
84
+ // 函数式 API
82
85
  export const modal = {
83
86
  open: (config) => modalManager.open(config),
84
87
  confirm: openConfirmModal,
@@ -14,6 +14,9 @@ export type OverlayProps = {
14
14
  closable?: boolean;
15
15
  onClose?: () => void;
16
16
  onClick?: (e: MouseEvent<HTMLDivElement>) => void;
17
+ /**
18
+ * @default document.body
19
+ */
17
20
  renderNode?: HTMLElement | (() => HTMLElement);
18
21
  };
19
22
  export declare function Overlay({ open, visible, children, className, style, zIndex, mask, maskClosable, lockScroll, keyboard, closable, onClose, onClick, renderNode, }: OverlayProps): import("react").ReactPortal | null;