@_tc/template-core 0.0.2 → 0.1.0

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 (177) hide show
  1. package/.skills/tc-generator/SKILL.md +62 -0
  2. package/.skills/tc-generator/reference/example.md +357 -0
  3. package/.skills/tc-generator/reference/model-schema.md +326 -0
  4. package/.skills/tc-generator/reference/project-template/app/controller/product.js +73 -0
  5. package/.skills/tc-generator/reference/project-template/app/router/product.js +9 -0
  6. package/.skills/tc-generator/reference/project-template/config/config.default.js +3 -0
  7. package/.skills/tc-generator/reference/project-template/index.js +17 -0
  8. package/.skills/tc-generator/reference/project-template/model/product/mode.js +179 -0
  9. package/.skills/tc-generator/reference/project-template/model/product/project/default.js +4 -0
  10. package/.skills/tc-generator/reference/project-template/package.json +10 -0
  11. package/README.md +239 -17
  12. package/cjs/_virtual/_rolldown/runtime.js +1 -1
  13. package/cjs/app/controller/base.js +1 -1
  14. package/cjs/app/controller/project.js +1 -1
  15. package/cjs/app/controller/view.js +1 -1
  16. package/cjs/app/extend/$fetch.js +1 -1
  17. package/cjs/app/extend/db.js +1 -1
  18. package/cjs/app/extend/generateErrorMessage.js +1 -1
  19. package/cjs/app/extend/logger.js +1 -1
  20. package/cjs/app/extend/parsingParamsOnUrl.js +1 -1
  21. package/cjs/app/middleware/api-sign-verify.js +1 -1
  22. package/cjs/app/middleware/error-handle.js +1 -1
  23. package/cjs/app/middleware/project-handler.js +1 -1
  24. package/cjs/app/middleware.js +1 -1
  25. package/cjs/app/router/project.js +1 -1
  26. package/cjs/app/router/view.js +1 -1
  27. package/cjs/app/router-schema/project.js +1 -1
  28. package/cjs/app/service/base.js +1 -1
  29. package/cjs/app/service/project.js +1 -1
  30. package/cjs/app/type.js +0 -1
  31. package/cjs/app/typings.js +0 -1
  32. package/cjs/app/view/entry.tpl +27 -28
  33. package/cjs/bundler/defaultAlias.js +1 -1
  34. package/cjs/bundler/dev.js +1 -1
  35. package/cjs/bundler/index.js +1 -1
  36. package/cjs/bundler/prod.js +1 -1
  37. package/cjs/bundler/state.js +1 -1
  38. package/cjs/config/config.default.js +1 -0
  39. package/cjs/index.js +1 -1
  40. package/cjs/packages/common/LRUCache.js +1 -1
  41. package/cjs/packages/common/array/index.js +1 -1
  42. package/cjs/packages/common/cache/LRUCache.js +1 -1
  43. package/cjs/packages/common/cache/index.js +1 -1
  44. package/cjs/packages/common/guards/index.js +1 -1
  45. package/cjs/packages/common/http/index.js +1 -1
  46. package/cjs/packages/common/i18n/default.js +1 -1
  47. package/cjs/packages/common/i18n/en-US.js +1 -1
  48. package/cjs/packages/common/i18n/index.js +1 -1
  49. package/cjs/packages/common/i18n/locales.js +1 -1
  50. package/cjs/packages/common/i18n/types.js +0 -1
  51. package/cjs/packages/common/index.js +1 -1
  52. package/cjs/packages/common/log/index.js +1 -1
  53. package/cjs/packages/common/number/index.js +1 -1
  54. package/cjs/packages/common/object/filterEmpty.js +1 -1
  55. package/cjs/packages/common/object/filtereEmpty.js +1 -1
  56. package/cjs/packages/common/object/index.js +1 -1
  57. package/cjs/packages/common/string/index.js +1 -1
  58. package/cjs/packages/common/types/index.js +0 -1
  59. package/cjs/packages/core/env.js +1 -1
  60. package/cjs/packages/core/index.js +1 -1
  61. package/cjs/packages/core/loader/config.js +1 -1
  62. package/cjs/packages/core/loader/controller.js +1 -1
  63. package/cjs/packages/core/loader/extend.js +1 -1
  64. package/cjs/packages/core/loader/middleware.js +1 -1
  65. package/cjs/packages/core/loader/router-schema.js +1 -1
  66. package/cjs/packages/core/loader/service.js +1 -1
  67. package/cjs/packages/core/paths.js +1 -1
  68. package/cjs/packages/core/types.js +0 -1
  69. package/cjs/packages/utils/getAllFnReturnValue.js +0 -1
  70. package/cjs/packages/utils/index.js +1 -1
  71. package/esm/_virtual/_rolldown/runtime.js +2 -15
  72. package/esm/app/controller/view.js +13 -11
  73. package/esm/app/middleware/api-sign-verify.js +9 -11
  74. package/esm/app/middleware.js +6 -6
  75. package/esm/app/view/entry.tpl +27 -28
  76. package/esm/config/config.default.js +9 -0
  77. package/esm/index.js +1 -1
  78. package/esm/packages/core/index.js +24 -26
  79. package/esm/packages/core/loader/config.js +11 -10
  80. package/esm/packages/core/loader/extend.js +13 -8
  81. package/fe/frontend/apps/dash/Dashboard.js +100 -1
  82. package/fe/frontend/apps/dash/dash.entry.js +2 -2
  83. package/fe/frontend/apps/ui-components/index.js +8 -0
  84. package/fe/frontend/apps/ui-components/ui-components.entry.d.ts +2 -0
  85. package/fe/frontend/src/api/baseInfo.d.ts +2 -2
  86. package/fe/frontend/src/common/fetchErrorShow.js +2 -1
  87. package/fe/frontend/src/common/generateMenuData.js +2 -1
  88. package/fe/frontend/src/common/importComponent.js +5 -2
  89. package/fe/frontend/src/common/language.d.ts +2 -1
  90. package/fe/frontend/src/common/language.js +7 -5
  91. package/fe/frontend/src/common/logFn/index.js +6 -4
  92. package/fe/frontend/src/common/request.js +6 -4
  93. package/fe/frontend/src/components/BasePage/HeaderView.d.ts +2 -1
  94. package/fe/frontend/src/components/BasePage/HeaderView.js +9 -4
  95. package/fe/frontend/src/defaultPages/Iframe/index.js +1 -7
  96. package/fe/frontend/src/defaultPages/NotFoundPage/index.d.ts +3 -0
  97. package/fe/frontend/src/defaultPages/NotFoundPage/index.js +7 -0
  98. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.js +3 -2
  99. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.js +8 -2
  100. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/index.js +4 -3
  101. package/fe/frontend/src/defaultPages/SchemaPage/index.css +0 -55
  102. package/fe/frontend/src/defaultPages/SchemaPage/index.js +3 -1
  103. package/fe/frontend/src/defaultPages/SchemaPage/utils/validator.d.ts +5 -1
  104. package/fe/frontend/src/defaultPages/SchemaPage/utils/validator.js +142 -7
  105. package/fe/frontend/src/defaultPages/SidebarSlotPage/index.js +2 -1
  106. package/fe/frontend/src/defaultPages/SidebarSlotPageTmp.js +1 -1
  107. package/fe/frontend/src/defaultPages/SlotPage/index.js +2 -1
  108. package/fe/frontend/src/hooks/useCurrentMenuData.js +1 -1
  109. package/fe/frontend/src/index.d.ts +4 -0
  110. package/fe/frontend/src/index.js +4 -0
  111. package/fe/frontend/src/language/en-US.d.ts +76 -0
  112. package/fe/frontend/src/language/en-US.js +75 -0
  113. package/fe/frontend/src/language/index.d.ts +66 -0
  114. package/fe/frontend/src/language/index.js +69 -0
  115. package/fe/frontend/src/language/zh-CN.d.ts +76 -0
  116. package/fe/frontend/src/language/zh-CN.js +75 -0
  117. package/fe/frontend/src/main.css +1 -1
  118. package/fe/frontend/src/typing/window.d.ts +2 -0
  119. package/fe/model/types/data/button.d.ts +2 -2
  120. package/fe/model/types/data/button.js +1 -1
  121. package/fe/model/types/model.d.ts +19 -12
  122. package/fe/packages/ui/react/components/Card/Card.d.ts +10 -0
  123. package/fe/packages/ui/react/components/Card/Card.js +8 -0
  124. package/fe/packages/ui/react/components/Card/index.d.ts +2 -0
  125. package/fe/packages/ui/react/components/Card/index.js +1 -0
  126. package/fe/packages/ui/react/components/DataTable/index.js +7 -3
  127. package/fe/packages/ui/react/components/ImagePreview/ImagePreview.js +3 -3
  128. package/fe/packages/ui/react/components/Layout/Layout.d.ts +11 -0
  129. package/fe/packages/ui/react/components/Layout/Layout.js +8 -0
  130. package/fe/packages/ui/react/components/Layout/index.d.ts +2 -0
  131. package/fe/packages/ui/react/components/Layout/index.js +1 -0
  132. package/fe/packages/ui/react/components/Loading/Loading.d.ts +9 -0
  133. package/fe/packages/ui/react/components/Loading/Loading.js +13 -0
  134. package/fe/packages/ui/react/components/Loading/index.d.ts +2 -0
  135. package/fe/packages/ui/react/components/Loading/index.js +1 -0
  136. package/fe/packages/ui/react/components/Menu/Menu.js +3 -2
  137. package/fe/packages/ui/react/components/Notification/Notification.d.ts +14 -0
  138. package/fe/packages/ui/react/components/Notification/Notification.js +29 -0
  139. package/fe/packages/ui/react/components/Notification/index.d.ts +2 -0
  140. package/fe/packages/ui/react/components/Notification/index.js +1 -0
  141. package/fe/packages/ui/react/components/Radio/Radio.d.ts +9 -0
  142. package/fe/packages/ui/react/components/Radio/Radio.js +20 -0
  143. package/fe/packages/ui/react/components/Radio/RadioGroup.d.ts +19 -0
  144. package/fe/packages/ui/react/components/Radio/RadioGroup.js +21 -0
  145. package/fe/packages/ui/react/components/Radio/index.d.ts +3 -0
  146. package/fe/packages/ui/react/components/Radio/index.js +2 -0
  147. package/fe/packages/ui/react/components/Search/Search.d.ts +1 -1
  148. package/fe/packages/ui/react/components/Search/Search.js +1 -5
  149. package/fe/packages/ui/react/components/Tabs/Tabs.d.ts +16 -0
  150. package/fe/packages/ui/react/components/Tabs/Tabs.js +19 -0
  151. package/fe/packages/ui/react/components/Tabs/index.d.ts +2 -0
  152. package/fe/packages/ui/react/components/Tabs/index.js +1 -0
  153. package/fe/packages/ui/react/components/hooks/useInputController.js +0 -1
  154. package/fe/packages/ui/react/components/index.d.ts +6 -0
  155. package/fe/packages/ui/react/components/index.js +6 -0
  156. package/fe/packages/ui/react/components/table/table.d.ts +3 -0
  157. package/fe/packages/ui/react/components/table/table.js +6 -6
  158. package/fe/packages/ui/react/components/testPage/index.js +54 -11
  159. package/fe/packages/ui/react/index.css +4 -0
  160. package/model/index.d.ts +1 -1
  161. package/model/types/data/button.d.ts +2 -2
  162. package/model/types/index.d.ts +1 -1
  163. package/model/types/model.d.ts +19 -12
  164. package/package.json +15 -16
  165. package/types/config/config.default.d.ts +2 -1
  166. package/types/index.d.ts +1 -1
  167. package/types/packages/core/index.d.ts +3 -3
  168. package/types/packages/core/loader/extend.d.ts +1 -1
  169. package/types/packages/core/paths.d.ts +4 -7
  170. package/types/packages/core/types.d.ts +31 -6
  171. package/cjs/app/data/signKey.js +0 -1
  172. package/esm/app/data/signKey.js +0 -8
  173. package/fe/frontend/apps/testPage/index.js +0 -6
  174. package/fe/frontend/apps/testPage/testPage.entry.d.ts +0 -2
  175. package/types/app/data/signKey.d.ts +0 -1
  176. /package/fe/frontend/apps/{testPage → ui-components}/index.d.ts +0 -0
  177. /package/fe/frontend/apps/{testPage/testPage.entry.js → ui-components/ui-components.entry.js} +0 -0
@@ -0,0 +1,75 @@
1
+ export const frontendZhCNResources = {
2
+ frontend: {
3
+ app: {
4
+ title: 'Template Core',
5
+ uiComponentsTitle: 'UI 组件',
6
+ uiComponentsButton: '点击我',
7
+ },
8
+ common: {
9
+ yes: '是',
10
+ no: '否',
11
+ noData: '暂无数据',
12
+ loading: '加载中',
13
+ operation: '操作',
14
+ },
15
+ feedback: {
16
+ confirmDelete: '确认删除?',
17
+ requiredInput: '请输入{label}',
18
+ unknownError: '未知错误',
19
+ requestTimedOut: '请求超时',
20
+ networkError: '网络错误',
21
+ },
22
+ notFound: {
23
+ title: '页面不存在',
24
+ description: '当前路径无效,或页面未在路由中注册。',
25
+ },
26
+ validator: {
27
+ value: '值',
28
+ required: '缺少必填字段: {field}',
29
+ type: '{path} 类型错误,期望 {type}',
30
+ typeString: '字符串',
31
+ typeNumber: '数字',
32
+ typeInteger: '整数',
33
+ typeBoolean: '布尔值',
34
+ typeArray: '数组',
35
+ typeObject: '对象',
36
+ typeNull: '空值',
37
+ format: '{path} 格式不正确',
38
+ minimum: '{path} 不能小于 {limit}',
39
+ maximum: '{path} 不能大于 {limit}',
40
+ exclusiveMinimum: '{path} 必须大于 {limit}',
41
+ exclusiveMaximum: '{path} 必须小于 {limit}',
42
+ multipleOf: '{path} 必须是 {multipleOf} 的倍数',
43
+ minLength: '{path} 长度不能少于 {limit} 个字符',
44
+ maxLength: '{path} 长度不能超过 {limit} 个字符',
45
+ pattern: '{path} 格式不符合要求',
46
+ minItems: '{path} 至少需要 {limit} 项',
47
+ maxItems: '{path} 不能超过 {limit} 项',
48
+ uniqueItems: '{path} 不能包含重复项',
49
+ minProperties: '{path} 至少需要 {limit} 个属性',
50
+ maxProperties: '{path} 不能超过 {limit} 个属性',
51
+ additionalProperties: '{path} 包含不允许的属性 {property}',
52
+ enum: '{path} 不在可选范围内',
53
+ const: '{path} 必须等于指定值',
54
+ oneOf: '{path} 只能匹配一个规则',
55
+ anyOf: '{path} 至少需要匹配一个规则',
56
+ allOf: '{path} 未满足全部规则',
57
+ not: '{path} 不能匹配该规则',
58
+ propertyNames: '{path} 属性名不符合要求',
59
+ dependencies: '{path} 缺少关联字段',
60
+ contains: '{path} 缺少符合要求的项',
61
+ if: '{path} 条件校验未通过',
62
+ fallback: '{path} 校验未通过',
63
+ },
64
+ log: {
65
+ pageNotFound: 'url有问题 或者 自定义页面未在路由器注册',
66
+ pageNotFoundEn: 'The URL is incorrect, or the custom page is not registered with the router.',
67
+ illegalComponentCallback: '非法的组件回调 - {comName}',
68
+ illegalComponentCallbackEn: 'Illegal component callback - {comName}',
69
+ subscriptionError: '不曾订阅过,请检查代码,关注函数与取消函数必须为同一个',
70
+ subscriptionErrorEn: "You haven't subscribed. Please check your code; the follow function and unsubscribe function must be the same.",
71
+ apiTamper: 'api属性不允许篡改',
72
+ apiTamperEn: 'API attributes cannot be tampered with',
73
+ },
74
+ },
75
+ };
@@ -1,4 +1,4 @@
1
- @import "../packages/ui/react/index.css";
1
+ @import '../../packages/ui/react/index.css';
2
2
 
3
3
  /* 内容扫描 */
4
4
  /* enhancedComponents */
@@ -2,6 +2,8 @@ export {};
2
2
  declare global {
3
3
  interface Window {
4
4
  _basePath: string;
5
+ _projKey: string;
6
+ _signKey: string;
5
7
  }
6
8
  }
7
9
  //# sourceMappingURL=window.d.ts.map
@@ -6,7 +6,7 @@ type ButtonTemplates = {
6
6
  */
7
7
  label?: string;
8
8
  } & ButtonProps;
9
- type ParamsValueData = 'schema::tableKey' | string | number;
9
+ type ParamsValueData = '$schema::tableKey' | string | number;
10
10
  type RemoveBtn = {
11
11
  eventKey: 'remove';
12
12
  /**
@@ -15,7 +15,7 @@ type RemoveBtn = {
15
15
  eventOption: {
16
16
  params: {
17
17
  /**
18
- * @example user_id: 'schema::tableKey' | '123' | 123
18
+ * @example user_id: '$schema::tableKey' | '123' | 123
19
19
  */
20
20
  [paramKey: string]: ParamsValueData;
21
21
  };
@@ -9,7 +9,7 @@ export {};
9
9
  // */
10
10
  // params: {
11
11
  // /**
12
- // * @example user_id: 'schema::tableKey' | '123' | 123
12
+ // * @example user_id: '$schema::tableKey' | '123' | 123
13
13
  // */
14
14
  // [paramKey: string]: ParamsValueData;
15
15
  // };
@@ -1,33 +1,40 @@
1
- import { TopMenuType, LeftMenuType } from "./menuType";
1
+ import { LeftMenuType, TopMenuType } from './menuType';
2
2
  type MTopMenuType = {
3
3
  /**
4
4
  * 默认为 left
5
5
  */
6
- menuLayout: "top";
6
+ menuLayout: 'top';
7
7
  menu: TopMenuType[];
8
8
  };
9
9
  type MLeftMenuType = {
10
10
  /**
11
11
  * 默认为 left
12
12
  */
13
- menuLayout?: "left";
13
+ menuLayout?: 'left';
14
14
  menu: LeftMenuType[];
15
15
  };
16
- export type ModeMenuType = MTopMenuType | MLeftMenuType;
17
- export type ModelDataType = {
16
+ export type MBMenuType = MTopMenuType | MLeftMenuType;
17
+ export interface ModelModeMap {
18
+ MB: MBMenuType;
19
+ }
20
+ export type ModelMode = Extract<keyof ModelModeMap, string>;
21
+ type ModelBaseDataType<M extends ModelMode> = {
18
22
  /**
19
23
  * - 使用哪一块的模型数据 内置 MB
20
24
  * - MB = 管理后台
21
25
  */
22
- mode: "MB";
26
+ mode: M;
23
27
  key?: string;
24
- name: string;
25
- desc: string;
26
- icon: string;
28
+ name?: string;
29
+ desc?: string;
30
+ icon?: string;
27
31
  /**
28
- * 首页(项目配置)
32
+ * 首页(项目配置) 不配置 会自动找寻第一个可用路由地址
29
33
  */
30
- homePage: string;
31
- } & ModeMenuType;
34
+ homePage?: string;
35
+ };
36
+ export type ModelDataType<M extends ModelMode = ModelMode> = {
37
+ [K in M]: ModelBaseDataType<K> & ModelModeMap[K];
38
+ }[M];
32
39
  export {};
33
40
  //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from 'react';
2
+ export type CardProps = {
3
+ header?: ReactNode;
4
+ footer?: ReactNode;
5
+ children?: ReactNode;
6
+ className?: string;
7
+ };
8
+ declare const Card: import("react").ForwardRefExoticComponent<CardProps & import("react").RefAttributes<HTMLDivElement>>;
9
+ export { Card };
10
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { forwardRef } from 'react';
4
+ const Card = forwardRef(({ header, footer, children, className }, ref) => {
5
+ return (_jsxs("div", { ref: ref, className: cn('tc-ui-card rounded-lg border bg-card text-card-foreground shadow-sm', className), children: [header && (_jsx("div", { className: "tc-ui-card-header border-b px-4 py-3 font-medium", children: header })), _jsx("div", { className: "tc-ui-card-body px-4 py-4", children: children }), footer && (_jsx("div", { className: "tc-ui-card-footer border-t px-4 py-3", children: footer }))] }));
6
+ });
7
+ Card.displayName = 'Card';
8
+ export { Card };
@@ -0,0 +1,2 @@
1
+ export * from './Card';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export * from './Card';
@@ -165,16 +165,20 @@ export function DataTable({ columns, data: pData, loading, rowKey = defaultRowKe
165
165
  : undefined,
166
166
  }));
167
167
  }, [columns, defaultColumnWidth, rowSelection]);
168
- return (_jsxs("div", { className: "tc-ui-data-table bg-background rounded-[20px] overflow-hidden relative", children: [_jsxs(Table, { containerClassName: "rounded-b-none overflow-x-auto", children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [rowSelection && (_jsxs(TableHead, { fixed: "left", style: {
168
+ return (_jsxs("div", { className: "tc-ui-data-table bg-background rounded-[20px] overflow-hidden relative", children: [_jsxs(Table, { containerClassName: "rounded-b-none overflow-x-auto", children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [rowSelection && (_jsxs(TableHead, { fixed: "left",
169
+ // fixedShadow={false}
170
+ showSeparator: false, style: {
169
171
  width: '48px',
170
172
  minWidth: '48px',
171
173
  }, children: [rowSelection.beforeCheckboxNode, _jsx(Checkbox, { checked: allChecked, "aria-label": "Select all rows", indeterminate: partiallyChecked, onChange: (_, event) => handleSelectAllChange(event) })] })), fixedColumns.map(({ column, fixed, fixedOffset }) => {
172
174
  const hasAction = column.isAction ?? column.key === 'action';
173
- return (_jsx(TableHead, { isAction: hasAction, fixed: fixed, fixedOffset: fixedOffset, style: getColumnStyle(column, defaultColumnWidth), children: column.title }, column.key));
175
+ return (_jsx(TableHead, { isAction: hasAction, fixed: fixed, fixedOffset: fixedOffset, hideSeparatorWhenFixedActive: fixed === 'right', style: getColumnStyle(column, defaultColumnWidth), children: column.title }, column.key));
174
176
  })] }) }), _jsx(TableBody, { children: data.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: columns.length + (rowSelection ? 1 : 0), className: "text-muted-foreground", children: _jsxs("div", { className: "flex flex-col items-center w-full gap-2.5", children: [_jsx("img", { src: noResult, alt: t('components.dataTable.noData'), className: " w-24 h-24" }), t('components.dataTable.noData')] }) }) })) : (data.map((record, rowIndex) => {
175
177
  const absoluteRowIndex = pageStartIndex + rowIndex;
176
178
  const recordKey = getRowKey(record, absoluteRowIndex, rowKey);
177
- return (_jsxs(TableRow, { children: [rowSelection && (_jsx(TableCell, { fixed: "left", style: {
179
+ return (_jsxs(TableRow, { children: [rowSelection && (_jsx(TableCell, { fixed: "left",
180
+ // fixedShadow={false}
181
+ style: {
178
182
  width: '48px',
179
183
  minWidth: '48px',
180
184
  }, children: _jsx(Checkbox, { checked: selectedKeySet.has(recordKey), "aria-label": "Select row", onChange: () => handleRowSelectChange(recordKey) }) })), fixedColumns.map(({ column, fixed, fixedOffset }) => {
@@ -30,7 +30,7 @@ function PreviewCore({ images, initialIndex, onClose }) {
30
30
  const hasImages = images.length > 0;
31
31
  const currentIndex = useMemo(() => clamp(index, 0, Math.max(images.length - 1, 0)), [index, images.length]);
32
32
  const currentImage = hasImages ? images[currentIndex] : '';
33
- const reset = () => {
33
+ const reset = useCallback(() => {
34
34
  setScale(1);
35
35
  setRotation(0);
36
36
  setFlipX(false);
@@ -38,7 +38,7 @@ function PreviewCore({ images, initialIndex, onClose }) {
38
38
  setPosition({ x: 0, y: 0 });
39
39
  positionRef.current = { x: 0, y: 0 };
40
40
  lastScaleBeforeNatural.current = null;
41
- };
41
+ }, [setScale]);
42
42
  const handleMouseDown = useCallback((e) => {
43
43
  setIsDragging(true);
44
44
  dragStart.current = { x: e.clientX - positionRef.current.x, y: e.clientY - positionRef.current.y };
@@ -92,7 +92,7 @@ function PreviewCore({ images, initialIndex, onClose }) {
92
92
  };
93
93
  document.addEventListener('keydown', handleKey);
94
94
  return () => document.removeEventListener('keydown', handleKey);
95
- }, [onClose, hasImages, images.length]);
95
+ }, [onClose, hasImages, images.length, reset]);
96
96
  useEffect(() => {
97
97
  if (!imgRef.current)
98
98
  return;
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+ export type LayoutProps = {
3
+ header?: ReactNode;
4
+ sidebar?: ReactNode;
5
+ children?: ReactNode;
6
+ footer?: ReactNode;
7
+ className?: string;
8
+ };
9
+ declare const Layout: import("react").ForwardRefExoticComponent<LayoutProps & import("react").RefAttributes<HTMLDivElement>>;
10
+ export { Layout };
11
+ //# sourceMappingURL=Layout.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { forwardRef } from 'react';
4
+ const Layout = forwardRef(({ header, sidebar, children, footer, className }, ref) => {
5
+ return (_jsxs("div", { ref: ref, className: cn('tc-ui-layout flex h-screen flex-col', className), children: [header && (_jsx("header", { className: "tc-ui-layout-header shrink-0 border-b bg-background", children: header })), _jsxs("div", { className: "tc-ui-layout-body flex flex-1 overflow-hidden", children: [sidebar && (_jsx("aside", { className: "tc-ui-layout-sidebar w-60 shrink-0 border-r bg-background overflow-y-auto", children: sidebar })), _jsx("main", { className: "tc-ui-layout-content flex-1 overflow-y-auto p-4", children: children })] }), footer && (_jsx("footer", { className: "tc-ui-layout-footer shrink-0 border-t bg-background", children: footer }))] }));
6
+ });
7
+ Layout.displayName = 'Layout';
8
+ export { Layout };
@@ -0,0 +1,2 @@
1
+ export * from './Layout';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export * from './Layout';
@@ -0,0 +1,9 @@
1
+ import type { ReactNode } from 'react';
2
+ export type LoadingProps = {
3
+ size?: 'sm' | 'md' | 'lg';
4
+ text?: ReactNode;
5
+ className?: string;
6
+ };
7
+ declare const Loading: import("react").ForwardRefExoticComponent<LoadingProps & import("react").RefAttributes<HTMLDivElement>>;
8
+ export { Loading };
9
+ //# sourceMappingURL=Loading.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { forwardRef } from 'react';
4
+ const sizeStyles = {
5
+ sm: 'h-4 w-4 border-2',
6
+ md: 'h-8 w-8 border-2',
7
+ lg: 'h-12 w-12 border-[3px]',
8
+ };
9
+ const Loading = forwardRef(({ size = 'md', text, className }, ref) => {
10
+ return (_jsxs("div", { ref: ref, className: cn('tc-ui-loading flex flex-col items-center justify-center gap-2', className), children: [_jsx("div", { className: cn('animate-spin rounded-full border-muted border-t-theme', sizeStyles[size]) }), text && _jsx("span", { className: "text-sm text-muted-foreground", children: text })] }));
11
+ });
12
+ Loading.displayName = 'Loading';
13
+ export { Loading };
@@ -0,0 +1,2 @@
1
+ export * from './Loading';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export * from './Loading';
@@ -84,17 +84,18 @@ export const Menu = ({ mode = "left", expandTrigger = "click", expandMode = "acc
84
84
  collapsedLabelTooltip,
85
85
  onSelect,
86
86
  onCollapse,
87
+ store,
87
88
  ]);
88
89
  useEffect(() => {
89
90
  if (controlledSelectedKey !== undefined) {
90
91
  store.setState({ selectedKey: controlledSelectedKey });
91
92
  }
92
- }, [controlledSelectedKey]);
93
+ }, [controlledSelectedKey, store]);
93
94
  useEffect(() => {
94
95
  if (controlledCollapsed !== undefined) {
95
96
  store.setState({ collapsed: controlledCollapsed });
96
97
  }
97
- }, [controlledCollapsed]);
98
+ }, [controlledCollapsed, store]);
98
99
  return (_jsx(MenuStoreContext.Provider, { value: store, children: _jsx(MenuInner, { mode: mode, items: items, className: className, children: children }) }));
99
100
  };
100
101
  Menu.Item = MenuItem;
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+ export type NotificationType = 'info' | 'success' | 'warning' | 'error';
3
+ export type NotificationProps = {
4
+ type?: NotificationType;
5
+ title?: ReactNode;
6
+ message?: ReactNode;
7
+ duration?: number;
8
+ closable?: boolean;
9
+ onClose?: () => void;
10
+ className?: string;
11
+ };
12
+ declare const Notification: import("react").ForwardRefExoticComponent<NotificationProps & import("react").RefAttributes<HTMLDivElement>>;
13
+ export { Notification };
14
+ //# sourceMappingURL=Notification.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { X } from 'lucide-react';
4
+ import { forwardRef, useCallback, useEffect, useState } from 'react';
5
+ const typeStyles = {
6
+ info: 'border-blue-500 bg-blue-50 dark:bg-blue-950',
7
+ success: 'border-green-500 bg-green-50 dark:bg-green-950',
8
+ warning: 'border-yellow-500 bg-yellow-50 dark:bg-yellow-950',
9
+ error: 'border-red-500 bg-red-50 dark:bg-red-950',
10
+ };
11
+ const Notification = forwardRef(({ type = 'info', title, message, duration, closable = true, onClose, className }, ref) => {
12
+ const [visible, setVisible] = useState(true);
13
+ const handleClose = useCallback(() => {
14
+ setVisible(false);
15
+ onClose?.();
16
+ }, [onClose]);
17
+ useEffect(() => {
18
+ if (duration && duration > 0) {
19
+ const timer = setTimeout(handleClose, duration);
20
+ return () => clearTimeout(timer);
21
+ }
22
+ return;
23
+ }, [duration, handleClose]);
24
+ if (!visible)
25
+ return null;
26
+ return (_jsxs("div", { ref: ref, role: "alert", className: cn('tc-ui-notification flex items-start gap-3 rounded-lg border p-4 shadow-lg', typeStyles[type], className), children: [_jsxs("div", { className: "flex-1 min-w-0", children: [title && _jsx("div", { className: "font-medium text-sm", children: title }), message && _jsx("div", { className: "text-sm text-muted-foreground mt-1", children: message })] }), closable && (_jsx("button", { type: "button", onClick: handleClose, className: "shrink-0 rounded p-0.5 hover:bg-black/5 dark:hover:bg-white/10 transition-colors", children: _jsx(X, { className: "h-4 w-4" }) }))] }));
27
+ });
28
+ Notification.displayName = 'Notification';
29
+ export { Notification };
@@ -0,0 +1,2 @@
1
+ export * from './Notification';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export * from './Notification';
@@ -0,0 +1,9 @@
1
+ import type { InputHTMLAttributes, ReactNode } from 'react';
2
+ export type RadioProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'children'> & {
3
+ label?: ReactNode;
4
+ };
5
+ declare const Radio: import("react").ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "children" | "type"> & {
6
+ label?: ReactNode;
7
+ } & import("react").RefAttributes<HTMLInputElement>>;
8
+ export { Radio };
9
+ //# sourceMappingURL=Radio.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { forwardRef } from 'react';
4
+ import { useRadioGroupContext } from './RadioGroup';
5
+ const Radio = forwardRef(({ className, label, disabled, ...props }, ref) => {
6
+ const group = useRadioGroupContext();
7
+ // When inside a RadioGroup, delegate name / checked / onChange to the group
8
+ const name = group.name ?? props.name;
9
+ const checked = group.selectedValue !== undefined ? group.selectedValue === props.value : props.checked;
10
+ const onChange = group.onSelect
11
+ ? () => {
12
+ if (!disabled && typeof props.value === 'string') {
13
+ group.onSelect?.(props.value);
14
+ }
15
+ }
16
+ : props.onChange;
17
+ return (_jsxs("label", { className: cn('tc-ui-radio inline-flex items-center gap-2', disabled && 'cursor-not-allowed opacity-50', !disabled && 'cursor-pointer group', className), children: [_jsx("input", { ref: ref, type: "radio", name: name, checked: checked, disabled: disabled, onChange: onChange, className: "sr-only peer", ...props }), _jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-full border border-border bg-background transition-colors duration-200 ease-out peer-checked:border-theme peer-checked:bg-theme peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-background group-hover:border-foreground/25", children: _jsx("span", { className: "h-2 w-2 rounded-full bg-theme-foreground" }) }), label && _jsx("span", { children: label })] }));
18
+ });
19
+ Radio.displayName = 'Radio';
20
+ export { Radio };
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from 'react';
2
+ export type RadioGroupProps = {
3
+ name?: string;
4
+ value?: string;
5
+ defaultValue?: string;
6
+ onChange?: (value: string) => void;
7
+ direction?: 'horizontal' | 'vertical';
8
+ children?: ReactNode;
9
+ className?: string;
10
+ };
11
+ type RadioGroupContextValue = {
12
+ name?: string;
13
+ selectedValue?: string;
14
+ onSelect?: (value: string) => void;
15
+ };
16
+ export declare function useRadioGroupContext(): RadioGroupContextValue;
17
+ declare const RadioGroup: import("react").ForwardRefExoticComponent<RadioGroupProps & import("react").RefAttributes<HTMLDivElement>>;
18
+ export { RadioGroup };
19
+ //# sourceMappingURL=RadioGroup.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { createContext, forwardRef, useCallback, useContext, useState } from 'react';
4
+ const RadioGroupContext = createContext({});
5
+ export function useRadioGroupContext() {
6
+ return useContext(RadioGroupContext);
7
+ }
8
+ const RadioGroup = forwardRef(({ name, value: controlledValue, defaultValue, onChange, direction = 'vertical', children, className, }, ref) => {
9
+ const [internalValue, setInternalValue] = useState(defaultValue ?? '');
10
+ const isControlled = controlledValue !== undefined;
11
+ const selectedValue = isControlled ? controlledValue : internalValue;
12
+ const handleSelect = useCallback((val) => {
13
+ if (!isControlled) {
14
+ setInternalValue(val);
15
+ }
16
+ onChange?.(val);
17
+ }, [isControlled, onChange]);
18
+ return (_jsx(RadioGroupContext.Provider, { value: { name, selectedValue, onSelect: handleSelect }, children: _jsx("div", { ref: ref, role: "radiogroup", className: cn('tc-ui-radio-group', direction === 'horizontal' ? 'flex flex-wrap gap-4' : 'flex flex-col gap-2', className), children: children }) }));
19
+ });
20
+ RadioGroup.displayName = 'RadioGroup';
21
+ export { RadioGroup };
@@ -0,0 +1,3 @@
1
+ export * from './Radio';
2
+ export * from './RadioGroup';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export * from './Radio';
2
+ export * from './RadioGroup';
@@ -1,6 +1,6 @@
1
1
  import type { MOmit } from '../../types';
2
2
  import type { FormInstance } from 'rc-field-form';
3
- import { type ReactNode } from 'react';
3
+ import type { ReactNode } from 'react';
4
4
  import { type FormFieldSchema } from '../Form';
5
5
  export type SearchProps<T> = {
6
6
  defaultValue?: T;
@@ -1,12 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from '../../lib/utils';
3
- import { useMemo } from 'react';
4
3
  import { SchemaForm } from '../Form';
5
4
  const Search = (props) => {
6
5
  const { defaultValue: pDefaultValue, schemas, children, getForm, btnsClassName } = props;
7
- const defaultValue = useMemo(() => {
8
- return pDefaultValue;
9
- }, []);
10
- return (_jsxs("div", { className: "tc-ui-search flex items-end justify-between gap-4 flex-wrap", children: [_jsx(SchemaForm, { preserve: true, layout: "horizontal", schemas: schemas, initialValues: defaultValue, getForm: getForm, footerButtons: false }), _jsx("div", { className: cn('flex items-center gap-2 self-end ml-auto flex-wrap', btnsClassName), children: children })] }));
6
+ return (_jsxs("div", { className: "tc-ui-search flex items-end justify-between gap-4 flex-wrap", children: [_jsx(SchemaForm, { preserve: true, layout: "horizontal", schemas: schemas, initialValues: pDefaultValue, getForm: getForm, footerButtons: false }), _jsx("div", { className: cn('flex items-center gap-2 self-end ml-auto flex-wrap', btnsClassName), children: children })] }));
11
7
  };
12
8
  export default Search;
@@ -0,0 +1,16 @@
1
+ import type { ReactNode } from 'react';
2
+ export type TabItem = {
3
+ key: string;
4
+ label: ReactNode;
5
+ disabled?: boolean;
6
+ };
7
+ export type TabsProps = {
8
+ items: TabItem[];
9
+ activeKey?: string;
10
+ defaultActiveKey?: string;
11
+ onChange?: (key: string) => void;
12
+ className?: string;
13
+ };
14
+ declare const Tabs: import("react").ForwardRefExoticComponent<TabsProps & import("react").RefAttributes<HTMLDivElement>>;
15
+ export { Tabs };
16
+ //# sourceMappingURL=Tabs.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils';
3
+ import { forwardRef, useCallback, useState } from 'react';
4
+ const Tabs = forwardRef(({ items, activeKey: controlledKey, defaultActiveKey, onChange, className }, ref) => {
5
+ const [internalKey, setInternalKey] = useState(defaultActiveKey ?? items[0]?.key ?? '');
6
+ const isControlled = controlledKey !== undefined;
7
+ const activeKey = isControlled ? controlledKey : internalKey;
8
+ const handleTabClick = useCallback((key) => {
9
+ if (!isControlled) {
10
+ setInternalKey(key);
11
+ }
12
+ onChange?.(key);
13
+ }, [isControlled, onChange]);
14
+ return (_jsx("div", { ref: ref, className: cn('tc-ui-tabs', className), children: _jsx("div", { className: "tc-ui-tabs-nav flex border-b border-border", role: "tablist", children: items.map((item) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeKey === item.key, disabled: item.disabled, onClick: () => !item.disabled && handleTabClick(item.key), className: cn('tc-ui-tabs-tab px-4 py-2 text-sm font-medium transition-colors', 'border-b-2 -mb-px', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', activeKey === item.key
15
+ ? 'border-theme text-theme'
16
+ : 'border-transparent text-muted-foreground hover:text-foreground', item.disabled && 'cursor-not-allowed opacity-50'), children: item.label }, item.key))) }) }));
17
+ });
18
+ Tabs.displayName = 'Tabs';
19
+ export { Tabs };
@@ -0,0 +1,2 @@
1
+ export * from './Tabs';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export * from './Tabs';
@@ -14,7 +14,6 @@ export const useInputController = (params) => {
14
14
  ref(node);
15
15
  }
16
16
  else if (ref) {
17
- // eslint-disable-next-line react-hooks/immutability
18
17
  ref.current = node;
19
18
  }
20
19
  }, [ref]);
@@ -1,5 +1,6 @@
1
1
  export * from './breadcrumb';
2
2
  export * from './Button';
3
+ export * from './Card';
3
4
  export * from './Checkbox';
4
5
  export * from './ConfirmDialog';
5
6
  export * from './DataTable';
@@ -12,17 +13,22 @@ export * from './ImagePreview';
12
13
  export * from './Input';
13
14
  export * from './InputNumber';
14
15
  export * from './Label';
16
+ export * from './Layout';
17
+ export * from './Loading';
15
18
  export * from './Menu';
16
19
  export * from './Message';
17
20
  export * from './Modal';
21
+ export * from './Notification';
18
22
  export * from './Overlay';
19
23
  export * from './Pagination';
24
+ export * from './Radio';
20
25
  export * from './Search';
21
26
  export * from './Select';
22
27
  export * from './Skeleton';
23
28
  export * from './Switch';
24
29
  export * from './table';
25
30
  export * from './TableSearch';
31
+ export * from './Tabs';
26
32
  export * from './Textarea';
27
33
  export * from './Tooltip';
28
34
  export * from './TreeSelect';
@@ -1,5 +1,6 @@
1
1
  export * from './breadcrumb';
2
2
  export * from './Button';
3
+ export * from './Card';
3
4
  export * from './Checkbox';
4
5
  export * from './ConfirmDialog';
5
6
  export * from './DataTable';
@@ -12,17 +13,22 @@ export * from './ImagePreview';
12
13
  export * from './Input';
13
14
  export * from './InputNumber';
14
15
  export * from './Label';
16
+ export * from './Layout';
17
+ export * from './Loading';
15
18
  export * from './Menu';
16
19
  export * from './Message';
17
20
  export * from './Modal';
21
+ export * from './Notification';
18
22
  export * from './Overlay';
19
23
  export * from './Pagination';
24
+ export * from './Radio';
20
25
  export * from './Search';
21
26
  export * from './Select';
22
27
  export * from './Skeleton';
23
28
  export * from './Switch';
24
29
  export * from './table';
25
30
  export * from './TableSearch';
31
+ export * from './Tabs';
26
32
  export * from './Textarea';
27
33
  export * from './Tooltip';
28
34
  export * from './TreeSelect';