@_tc/template-core 0.2.0-bate.0 → 0.2.0-bate.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 (164) hide show
  1. package/.skills/tc-component-usage-skills/reference/template-core-frontend.md +8 -1
  2. package/.skills/tc-generator/SKILL.md +3 -2
  3. package/.skills/tc-generator/reference/example.md +1 -1
  4. package/.skills/tc-generator/reference/model-schema.md +18 -0
  5. package/.skills/tc-generator/reference/project-template/index.js +1 -1
  6. package/.skills/tc-generator/reference/runtime-extensions.md +22 -2
  7. package/AGENT_README.md +35 -14
  8. package/README.md +238 -33
  9. package/cjs/app/controller/view.js +1 -1
  10. package/cjs/app/{extend → extends}/db.js +1 -1
  11. package/cjs/app/extends/localCacheHtmlEtag.js +1 -0
  12. package/cjs/app/extends/render-view.js +1 -0
  13. package/cjs/app/middleware.js +1 -1
  14. package/cjs/app/view/entry.tpl +0 -16
  15. package/cjs/bundler/buildFE.js +1 -0
  16. package/cjs/bundler/index.js +1 -1
  17. package/cjs/bundler/state.js +1 -1
  18. package/cjs/bundler/utils.js +3 -3
  19. package/cjs/packages/common/index.js +1 -1
  20. package/cjs/packages/common/rafTimer.js +1 -0
  21. package/cjs/packages/common/string/index.js +1 -1
  22. package/cjs/packages/core/index.js +1 -1
  23. package/cjs/packages/core/loader/controller.js +1 -1
  24. package/cjs/packages/core/loader/extend.js +1 -1
  25. package/cjs/packages/core/loader/middleware.js +1 -1
  26. package/cjs/packages/core/loader/router-schema.js +1 -1
  27. package/cjs/packages/core/loader/router.js +1 -1
  28. package/cjs/packages/core/loader/service.js +1 -1
  29. package/cjs/packages/utils/runFileFn.js +1 -1
  30. package/esm/app/controller/view.js +28 -15
  31. package/esm/app/{extend → extends}/$fetch.js +1 -1
  32. package/esm/app/{extend → extends}/crypto.js +1 -1
  33. package/esm/app/{extend → extends}/db.js +2 -2
  34. package/esm/app/{extend → extends}/generateErrorMessage.js +1 -1
  35. package/esm/app/extends/localCacheHtmlEtag.js +41 -0
  36. package/esm/app/{extend → extends}/logger.js +1 -1
  37. package/esm/app/{extend → extends}/parsingParamsOnUrl.js +1 -1
  38. package/esm/app/extends/render-view.js +18 -0
  39. package/esm/app/middleware.js +8 -12
  40. package/esm/app/view/entry.tpl +0 -16
  41. package/esm/bundler/buildFE.js +14 -0
  42. package/esm/bundler/index.js +2 -14
  43. package/esm/bundler/state.js +5 -1
  44. package/esm/bundler/utils.js +130 -104
  45. package/esm/packages/common/index.js +7 -6
  46. package/esm/packages/common/rafTimer.js +47 -0
  47. package/esm/packages/common/string/index.js +11 -2
  48. package/esm/packages/core/index.js +34 -28
  49. package/esm/packages/core/loader/controller.js +6 -6
  50. package/esm/packages/core/loader/extend.js +6 -6
  51. package/esm/packages/core/loader/middleware.js +6 -6
  52. package/esm/packages/core/loader/router-schema.js +7 -7
  53. package/esm/packages/core/loader/router.js +13 -13
  54. package/esm/packages/core/loader/service.js +6 -6
  55. package/esm/packages/utils/runFileFn.js +10 -10
  56. package/fe/frontend/apps/dash/Dashboard.js +6 -4
  57. package/fe/frontend/apps/dash/dash.entry.js +4 -0
  58. package/fe/frontend/src/common/generateMenuData.d.ts +4 -1
  59. package/fe/frontend/src/common/generateMenuData.js +3 -3
  60. package/fe/frontend/src/common/language.d.ts +12 -1
  61. package/fe/frontend/src/common/language.js +25 -4
  62. package/fe/frontend/src/common/rafTimer.d.ts +1 -0
  63. package/fe/frontend/src/common/rafTimer.js +2 -0
  64. package/fe/frontend/src/common/request.js +1 -0
  65. package/fe/frontend/src/common/theme.d.ts +7 -0
  66. package/fe/frontend/src/common/theme.js +33 -0
  67. package/fe/frontend/src/components/BasePage/HeaderView.js +2 -2
  68. package/fe/frontend/src/components/LanguageSwitch/LanguageSwitch.js +22 -6
  69. package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.d.ts +3 -2
  70. package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.js +6 -29
  71. package/fe/frontend/src/components/ThemeSwitch/index.d.ts +1 -0
  72. package/fe/frontend/src/components/ThemeSwitch/index.js +3 -2
  73. package/fe/frontend/src/components/index.js +2 -2
  74. package/fe/frontend/src/defaultPages/NotFoundPage/index.js +4 -3
  75. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.js +14 -9
  76. package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.js +8 -7
  77. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaSearch/index.js +20 -24
  78. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.d.ts +10 -0
  79. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.js +17 -0
  80. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.d.ts +5 -0
  81. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.js +8 -0
  82. package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/index.js +50 -32
  83. package/fe/frontend/src/defaultPages/SchemaPage/index.css +0 -4
  84. package/fe/frontend/src/defaultPages/SchemaPage/index.js +5 -3
  85. package/fe/frontend/src/defaultPages/SlotPage/index.js +6 -3
  86. package/fe/frontend/src/hooks/useText.d.ts +3 -0
  87. package/fe/frontend/src/hooks/useText.js +14 -0
  88. package/fe/frontend/src/index.d.ts +11 -3
  89. package/fe/frontend/src/index.js +8 -3
  90. package/fe/frontend/src/language/index.d.ts +0 -2
  91. package/fe/frontend/src/language/index.js +1 -7
  92. package/fe/frontend/src/language/resources.d.ts +2 -0
  93. package/fe/frontend/src/language/resources.js +9 -0
  94. package/fe/model/types/data/schema.d.ts +24 -2
  95. package/fe/model/types/index.d.ts +1 -0
  96. package/fe/packages/common/i18n/default.js +3 -0
  97. package/fe/packages/common/i18n/en-US.js +5 -2
  98. package/fe/packages/common/i18n/index.js +13 -0
  99. package/fe/packages/common/i18n/locales.js +7 -0
  100. package/fe/packages/common/index.d.ts +1 -0
  101. package/fe/packages/common/rafTimer.d.ts +7 -0
  102. package/fe/packages/common/rafTimer.js +168 -0
  103. package/fe/packages/common/string/index.d.ts +9 -0
  104. package/fe/packages/react/hooks/index.d.ts +9 -0
  105. package/fe/packages/react/hooks/index.js +8 -0
  106. package/fe/packages/react/hooks/useRefState.d.ts +4 -12
  107. package/fe/packages/react/hooks/useRefState.js +18 -8
  108. package/fe/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
  109. package/fe/packages/react/ui/components/DataTable/dataTableWidth.js +33 -0
  110. package/fe/packages/react/ui/components/DataTable/dataTableWidth.test.js +39 -0
  111. package/fe/packages/react/ui/components/DataTable/index.d.ts +1 -1
  112. package/fe/packages/react/ui/components/DataTable/index.js +12 -32
  113. package/fe/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
  114. package/fe/packages/react/ui/components/Textarea/Textarea.js +1 -1
  115. package/fe/packages/react/ui/components/types/baseType.d.ts +21 -0
  116. package/fe/packages/react/ui/components/types/baseType.js +0 -0
  117. package/model/frontend/src/common/language.d.ts +12 -1
  118. package/model/frontend/src/hooks/useText.d.ts +3 -0
  119. package/model/frontend/src/language/index.d.ts +0 -2
  120. package/model/frontend/src/language/resources.d.ts +2 -0
  121. package/model/model/types/data/schema.d.ts +24 -2
  122. package/model/model/types/index.d.ts +1 -0
  123. package/model/packages/common/index.d.ts +1 -0
  124. package/model/packages/common/rafTimer.d.ts +7 -0
  125. package/model/packages/common/string/index.d.ts +9 -0
  126. package/model/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
  127. package/model/packages/react/ui/components/DataTable/index.d.ts +1 -1
  128. package/model/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
  129. package/model/packages/react/ui/components/types/baseType.d.ts +21 -0
  130. package/package.json +5 -5
  131. package/types/app/extends/localCacheHtmlEtag.d.ts +10 -0
  132. package/types/app/{extend → extends}/render-view.d.ts +1 -1
  133. package/types/app/service/base.d.ts +1 -1
  134. package/types/app/service/project.d.ts +1 -1
  135. package/types/app/type.d.ts +2 -1
  136. package/types/app/typings.d.ts +10 -8
  137. package/types/bundler/buildFE.d.ts +2 -0
  138. package/types/bundler/index.d.ts +1 -2
  139. package/types/bundler/state.d.ts +4 -0
  140. package/types/bundler/utils.d.ts +5 -0
  141. package/types/index.d.ts +3 -3
  142. package/types/packages/common/i18n/default.d.ts +4 -0
  143. package/types/packages/common/i18n/en-US.d.ts +6 -2
  144. package/types/packages/common/i18n/index.d.ts +21 -0
  145. package/types/packages/common/i18n/locales.d.ts +10 -0
  146. package/types/packages/common/i18n/types.d.ts +40 -0
  147. package/types/packages/common/index.d.ts +1 -0
  148. package/types/packages/common/rafTimer.d.ts +44 -0
  149. package/types/packages/common/string/index.d.ts +16 -0
  150. package/types/packages/core/loader/extend.d.ts +1 -1
  151. package/types/packages/core/types.d.ts +4 -0
  152. package/cjs/app/extend/render-view.js +0 -1
  153. package/esm/app/extend/render-view.js +0 -25
  154. /package/cjs/app/{extend → extends}/$fetch.js +0 -0
  155. /package/cjs/app/{extend → extends}/crypto.js +0 -0
  156. /package/cjs/app/{extend → extends}/generateErrorMessage.js +0 -0
  157. /package/cjs/app/{extend → extends}/logger.js +0 -0
  158. /package/cjs/app/{extend → extends}/parsingParamsOnUrl.js +0 -0
  159. /package/types/app/{extend → extends}/$fetch.d.ts +0 -0
  160. /package/types/app/{extend → extends}/crypto.d.ts +0 -0
  161. /package/types/app/{extend → extends}/db.d.ts +0 -0
  162. /package/types/app/{extend → extends}/generateErrorMessage.d.ts +0 -0
  163. /package/types/app/{extend → extends}/logger.d.ts +0 -0
  164. /package/types/app/{extend → extends}/parsingParamsOnUrl.d.ts +0 -0
@@ -1,10 +1,11 @@
1
1
  //#region packages/common/i18n/en-US.ts
2
2
  /**
3
- * UI component library default English language resources.
3
+ * UI 组件库默认英文语言资源。
4
4
  *
5
- * Only built-in component copy belongs here. Applications can override or extend it with I18nProvider.resources.
5
+ * 这里只放组件内置文案,业务项目可以通过 I18nProvider.resources 覆盖或追加。
6
6
  */
7
7
  var defaultEnglishResources = {
8
+ /** 通用操作文案。 */
8
9
  common: {
9
10
  tip: "Prompt",
10
11
  confirm: "Confirm",
@@ -13,6 +14,7 @@ var defaultEnglishResources = {
13
14
  submit: "Submit",
14
15
  reset: "Reset"
15
16
  },
17
+ /** UI 组件内置文案,按组件名分组。 */
16
18
  components: {
17
19
  breadcrumb: { close: "Close" },
18
20
  confirmDialog: {
@@ -64,6 +66,7 @@ var defaultEnglishResources = {
64
66
  rotateRight: "Rotate right",
65
67
  flipHorizontal: "Flip horizontal",
66
68
  flipVertical: "Flip vertical",
69
+ /** {index} 会在运行时由调用方传入的插值数据替换。 */
67
70
  previewImage: "Preview image {index}"
68
71
  },
69
72
  modal: {
@@ -2,6 +2,7 @@ import "./default.js";
2
2
  import "./en-US.js";
3
3
  import { defaultLanguage, languageLocalKey, translations } from "./locales.js";
4
4
  //#region packages/common/i18n/index.ts
5
+ /** 判断某个消息节点是否是可继续递归访问的普通字典。 */
5
6
  var isPlainI18nDictionary = (value) => {
6
7
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7
8
  };
@@ -65,6 +66,10 @@ var translate = (state, key, fillingData, options) => {
65
66
  const value = getI18nPathValue(state.resources[language], key) ?? getI18nPathValue(state.resources[fallbackLanguage], key) ?? options?.fallback ?? key;
66
67
  return typeof value === "string" ? interpolateI18nMessage(value, fillingData) : value;
67
68
  };
69
+ /**
70
+ * 获取可用于持久化语言的浏览器 window。
71
+ * Node、SSR 或测试环境下没有 window 时返回 undefined。
72
+ */
68
73
  var getBrowserWindow = () => {
69
74
  return globalThis.window;
70
75
  };
@@ -92,6 +97,11 @@ var createInitialState = () => ({
92
97
  storageKey: languageLocalKey,
93
98
  persist: true
94
99
  });
100
+ /**
101
+ * 创建模块内部使用的最小 store。
102
+ *
103
+ * 这里只实现 getState / setState / subscribe,避免 common 层为了 i18n 引入状态管理依赖。
104
+ */
95
105
  var createI18nStore = () => {
96
106
  let state;
97
107
  const listeners = /* @__PURE__ */ new Set();
@@ -148,6 +158,7 @@ var createI18nStore = () => {
148
158
  }
149
159
  };
150
160
  };
161
+ /** 全局 i18n store,React 适配层和非 React 代码共享这一份状态。 */
151
162
  var i18nStore = createI18nStore();
152
163
  /**
153
164
  * 对外使用的 i18n 函数。
@@ -156,7 +167,9 @@ var i18nStore = createI18nStore();
156
167
  var i18n = (key, fillingData, options) => {
157
168
  return translate(i18nStore.getState(), key, fillingData, options);
158
169
  };
170
+ /** i18n 的简写别名。 */
159
171
  var t = i18n;
172
+ /** 兼容历史调用的别名,行为等同于 i18n。 */
160
173
  var getLanguage = i18n;
161
174
  //#endregion
162
175
  export { getI18nPathValue, getLanguage, i18n, i18nStore, interpolateI18nMessage, isPlainI18nDictionary, mergeI18nDictionary, mergeI18nResources, t, translate };
@@ -1,8 +1,15 @@
1
1
  import { defaultLanguageResources } from "./default.js";
2
2
  import { defaultEnglishResources } from "./en-US.js";
3
3
  //#region packages/common/i18n/locales.ts
4
+ /** 默认语言,作为初始化语言和翻译兜底语言使用。 */
4
5
  var defaultLanguage = "zh-CN";
6
+ /** 默认保存用户语言偏好的 localStorage key。 */
5
7
  var languageLocalKey = "tc_language";
8
+ /**
9
+ * 内置语言资源。
10
+ *
11
+ * 业务项目可以通过 I18nProvider.resources、setResources 或 addResources 覆盖和追加。
12
+ */
6
13
  var translations = {
7
14
  "zh-CN": defaultLanguageResources,
8
15
  "en-US": defaultEnglishResources
@@ -6,5 +6,6 @@ export * from "./i18n";
6
6
  export * from "./log";
7
7
  export * from "./number";
8
8
  export * from "./object";
9
+ export * from "./rafTimer";
9
10
  export * from "./string";
10
11
  export * from "./types";
@@ -0,0 +1,7 @@
1
+ export type RafTimerId = number;
2
+ export type RafTimerCallback<Args extends unknown[] = []> = (...args: Args) => void;
3
+ export declare const rafSetTimeout: <Args extends unknown[]>(callback: RafTimerCallback<Args>, delay?: number, ...args: Args) => RafTimerId;
4
+ export declare const rafClearTimeout: (timerId: RafTimerId) => void;
5
+ export declare const rafSetInterval: <Args extends unknown[]>(callback: RafTimerCallback<Args>, delay?: number, ...args: Args) => RafTimerId;
6
+ export declare const rafClearInterval: (timerId: RafTimerId) => void;
7
+ export declare const clearRafTimer: (timerId: RafTimerId) => void;
@@ -0,0 +1,168 @@
1
+ //#region packages/common/rafTimer.ts
2
+ var FRAME_FALLBACK_DELAY = 16;
3
+ var timerHost = globalThis;
4
+ var rafTimers = /* @__PURE__ */ new Map();
5
+ var rafTimerSeed = 0;
6
+ /**
7
+ * 统一修正延迟时间,避免传入 undefined 或负数。
8
+ *
9
+ * @param delay 原始延迟时间。
10
+ * @returns 不小于 0 的延迟时间。
11
+ */
12
+ var normalizeDelay = (delay) => Math.max(0, delay ?? 0);
13
+ /**
14
+ * 获取当前时间戳。
15
+ */
16
+ var getNow = () => timerHost.performance?.now?.() ?? Date.now();
17
+ /**
18
+ * 创建帧调度器。
19
+ *
20
+ * 浏览器优先使用 requestAnimationFrame;否则回退到 setTimeout。
21
+ */
22
+ var createFrameScheduler = () => {
23
+ const requestAnimationFrameRef = timerHost.requestAnimationFrame;
24
+ const cancelAnimationFrameRef = timerHost.cancelAnimationFrame;
25
+ if (typeof requestAnimationFrameRef === "function" && typeof cancelAnimationFrameRef === "function") return {
26
+ scheduleFrame: (callback) => requestAnimationFrameRef.call(timerHost, callback),
27
+ cancelFrame: (handle) => cancelAnimationFrameRef.call(timerHost, handle)
28
+ };
29
+ const setTimeoutRef = timerHost.setTimeout;
30
+ const clearTimeoutRef = timerHost.clearTimeout;
31
+ if (typeof setTimeoutRef !== "function" || typeof clearTimeoutRef !== "function") throw new Error("raf timer requires requestAnimationFrame or setTimeout/clearTimeout.");
32
+ return {
33
+ scheduleFrame: (callback) => setTimeoutRef.call(timerHost, () => callback(getNow()), FRAME_FALLBACK_DELAY),
34
+ cancelFrame: (handle) => clearTimeoutRef.call(timerHost, handle)
35
+ };
36
+ };
37
+ var frameScheduler;
38
+ var getFrameScheduler = () => {
39
+ frameScheduler ??= createFrameScheduler();
40
+ return frameScheduler;
41
+ };
42
+ /**
43
+ * 创建唯一的计时器 id。
44
+ *
45
+ * @returns 新的计时器 id。
46
+ */
47
+ var createTimerId = () => {
48
+ rafTimerSeed += 1;
49
+ return rafTimerSeed;
50
+ };
51
+ /**
52
+ * 删除并取消指定计时器。
53
+ *
54
+ * 步骤:
55
+ * 1. 根据 id 查找计时器状态。
56
+ * 2. 如果计时器不存在,直接结束。
57
+ * 3. 取消下一帧回调,并从缓存中移除计时器。
58
+ *
59
+ * @param timerId 要取消的计时器 id。
60
+ */
61
+ var deleteTimer = (timerId) => {
62
+ const timer = rafTimers.get(timerId);
63
+ if (!timer) return;
64
+ getFrameScheduler().cancelFrame(timer.frameId);
65
+ rafTimers.delete(timerId);
66
+ };
67
+ /**
68
+ * 每一帧执行一次的调度函数。
69
+ *
70
+ * 步骤:
71
+ * 1. 读取当前计时器状态。
72
+ * 2. 对比当前时间和起始时间/上次执行时间,判断是否到达延迟。
73
+ * 3. timeout 到点后执行一次并删除计时器。
74
+ * 4. interval 到点后执行回调,并更新上次执行时间。
75
+ * 5. 如果计时器仍然存在,继续注册下一帧。
76
+ *
77
+ * @param timerId 当前计时器 id。
78
+ * @param currentTime requestAnimationFrame 或 fallback 传入的当前时间戳。
79
+ */
80
+ var tick = (timerId, currentTime) => {
81
+ const timer = rafTimers.get(timerId);
82
+ if (!timer) return;
83
+ if (timer.type === "timeout" ? currentTime - timer.startTime >= timer.delay : currentTime - timer.lastRunTime >= timer.delay) {
84
+ if (timer.type === "timeout") {
85
+ rafTimers.delete(timerId);
86
+ timer.callback();
87
+ return;
88
+ }
89
+ timer.lastRunTime = currentTime;
90
+ timer.callback();
91
+ }
92
+ if (rafTimers.has(timerId)) timer.frameId = getFrameScheduler().scheduleFrame((nextTime) => tick(timerId, nextTime));
93
+ };
94
+ /**
95
+ * 创建 requestAnimationFrame 计时器。
96
+ *
97
+ * 步骤:
98
+ * 1. 检查当前运行环境是否支持 requestAnimationFrame。
99
+ * 2. 创建计时器 id,并记录起始时间。
100
+ * 3. 保存计时器类型、延迟、回调和帧 id 等状态。
101
+ * 4. 注册第一帧调度。
102
+ * 5. 将计时器状态写入缓存,并返回计时器 id。
103
+ *
104
+ * @param type 计时器类型。
105
+ * @param callback 到点后执行的回调函数。
106
+ * @param delay 延迟或间隔时间,单位毫秒。
107
+ * @param args 传给回调函数的参数。
108
+ * @returns 计时器 id。
109
+ */
110
+ var createRafTimer = (type, callback, delay, args) => {
111
+ const timerId = createTimerId();
112
+ const startTime = getNow();
113
+ const timer = {
114
+ type,
115
+ delay: normalizeDelay(delay),
116
+ callback: () => callback(...args ?? []),
117
+ startTime,
118
+ lastRunTime: startTime,
119
+ frameId: 0
120
+ };
121
+ rafTimers.set(timerId, timer);
122
+ timer.frameId = getFrameScheduler().scheduleFrame((currentTime) => tick(timerId, currentTime));
123
+ return timerId;
124
+ };
125
+ /**
126
+ * 使用 requestAnimationFrame 驱动,在指定延迟后执行一次回调。
127
+ *
128
+ * @param callback 延迟结束后执行的回调函数。
129
+ * @param delay 延迟时间,单位毫秒,默认 0。
130
+ * @param args 传给回调函数的参数。
131
+ * @returns 计时器 id,可通过 rafClearTimeout 或 clearRafTimer 取消。
132
+ */
133
+ var rafSetTimeout = (callback, delay, ...args) => createRafTimer("timeout", callback, delay, args);
134
+ /**
135
+ * 取消 rafSetTimeout 创建的计时器。
136
+ *
137
+ * @param timerId rafSetTimeout 返回的计时器 id。
138
+ */
139
+ var rafClearTimeout = (timerId) => {
140
+ deleteTimer(timerId);
141
+ };
142
+ /**
143
+ * 使用 requestAnimationFrame 驱动,按指定间隔重复执行回调。
144
+ *
145
+ * @param callback 每次间隔结束后执行的回调函数。
146
+ * @param delay 间隔时间,单位毫秒,默认 0。
147
+ * @param args 传给回调函数的参数。
148
+ * @returns 计时器 id,可通过 rafClearInterval 或 clearRafTimer 取消。
149
+ */
150
+ var rafSetInterval = (callback, delay, ...args) => createRafTimer("interval", callback, delay, args);
151
+ /**
152
+ * 取消 rafSetInterval 创建的计时器。
153
+ *
154
+ * @param timerId rafSetInterval 返回的计时器 id。
155
+ */
156
+ var rafClearInterval = (timerId) => {
157
+ deleteTimer(timerId);
158
+ };
159
+ /**
160
+ * 取消本模块创建的任意 requestAnimationFrame 计时器。
161
+ *
162
+ * @param timerId rafSetTimeout 或 rafSetInterval 返回的计时器 id。
163
+ */
164
+ var clearRafTimer = (timerId) => {
165
+ deleteTimer(timerId);
166
+ };
167
+ //#endregion
168
+ export { clearRafTimer, rafClearInterval, rafClearTimeout, rafSetInterval, rafSetTimeout };
@@ -1,3 +1,12 @@
1
1
  export declare const isBlank: (value: string | null | undefined) => boolean;
2
2
  export declare const capitalize: (value: string) => string;
3
3
  export declare const kebabCase: (value: string) => string;
4
+ type JoinStrValue = string | number | boolean | null | undefined;
5
+ type JoinStrConditionalValue = readonly [condition: unknown, value: JoinStrValue];
6
+ type JoinStrInput = JoinStrValue | JoinStrConditionalValue;
7
+ type JoinStrOptions = {
8
+ separator?: string;
9
+ };
10
+ type JoinStrArgs = readonly JoinStrInput[] | readonly [...JoinStrInput[], JoinStrOptions];
11
+ export declare const joinStr: (...strings: JoinStrArgs) => string;
12
+ export {};
@@ -0,0 +1,9 @@
1
+ export * from "./useBreadcrumb";
2
+ export { default as useExecuteOnce } from "./useExecuteOnce";
3
+ export * from "./useExecuteOnce";
4
+ export { default as useInit } from "./useInit";
5
+ export * from "./useLanguage";
6
+ export { default as usePagination } from "./usePagination";
7
+ export { default as useRefState } from "./useRefState";
8
+ export { default as useWatch } from "./useWatch";
9
+ export * from "./useWatch";
@@ -0,0 +1,8 @@
1
+ import { useBreadcrumb } from "./useBreadcrumb.js";
2
+ import { useLanguage } from "./useLanguage.js";
3
+ import useInit from "./useInit.js";
4
+ import useExecuteOnce, { executionPhaseType } from "./useExecuteOnce.js";
5
+ import useRefState from "./useRefState.js";
6
+ import useWatch, { defaultCompare, identityCompare, shallowCompare } from "./useWatch.js";
7
+ import usePagination from "./usePagination.js";
8
+ export { defaultCompare, executionPhaseType, identityCompare, shallowCompare, useBreadcrumb, useExecuteOnce, useInit, useLanguage, usePagination, useRefState, useWatch };
@@ -1,17 +1,9 @@
1
1
  import { RefObject } from "react";
2
- type SetState<S> = (value: S | ((preValue: S) => S), callback?: CallBackFN<S>) => void;
3
- type CallBackFN<T> = (value: T) => void;
2
+ type SetState<S> = (value: S | ((preValue: S) => S)) => void;
4
3
  type RefState<T> = RefObject<{
5
4
  data: T;
6
5
  }>;
7
- export default function useRefState<S>(initialState: S | (() => S)): [
8
- S,
9
- SetState<S>,
10
- RefState<S>
11
- ];
12
- export default function useRefState<S = undefined>(): [
13
- S | undefined,
14
- SetState<S | undefined>,
15
- RefState<S | undefined>
16
- ];
6
+ type DelayTiming = number | undefined;
7
+ export default function useRefState<S>(initialState: S | (() => S), delayTiming?: DelayTiming): [S, SetState<S>, RefState<S>];
8
+ export default function useRefState<S = undefined>(): [S | undefined, SetState<S | undefined>, RefState<S | undefined>];
17
9
  export {};
@@ -1,23 +1,33 @@
1
1
  import useInit from "./useInit.js";
2
+ import { rafClearTimeout, rafSetTimeout } from "../../common/rafTimer.js";
2
3
  import { useCallback, useLayoutEffect, useRef, useState } from "react";
3
4
  //#region packages/react/hooks/useRefState.ts
4
- function useRefState(initialState) {
5
+ var delayedCall = (call, delayTiming) => {
6
+ if (delayTiming) return rafSetTimeout(call, delayTiming);
7
+ call();
8
+ };
9
+ function useRefState(initialState, delayTiming) {
5
10
  const [v, setValue] = useState(initialState);
6
11
  const data = useRef({ data: void 0 });
7
12
  const callbackRef = useRef(null);
8
13
  const [callbackVersion, setCallbackVersion] = useState(0);
14
+ const refdelayTimer = useRef(void 0);
9
15
  useInit(() => {
10
16
  data.current.data = v;
11
17
  });
12
- const setData = useCallback((action, callback) => {
18
+ const setData = useCallback((action) => {
19
+ if (refdelayTimer.current) {
20
+ rafClearTimeout(refdelayTimer.current);
21
+ refdelayTimer.current = void 0;
22
+ }
13
23
  const value = typeof action === "function" ? action(data.current.data) : action;
14
- setValue(value);
24
+ refdelayTimer.current = delayedCall(() => setValue(value), delayTiming);
15
25
  data.current.data = value;
16
- if (callback) {
17
- callbackRef.current = callback;
18
- setCallbackVersion((version) => version + 1);
19
- }
20
- }, [setCallbackVersion, setValue]);
26
+ }, [
27
+ setCallbackVersion,
28
+ setValue,
29
+ delayTiming
30
+ ]);
21
31
  useLayoutEffect(() => {
22
32
  if (callbackRef.current) {
23
33
  const callback = callbackRef.current;
@@ -0,0 +1,12 @@
1
+ import type { CSSProperties } from "react";
2
+ export type DataTableWidth = number | string;
3
+ export declare const normalizeTableWidth: (value: DataTableWidth | undefined) => string | undefined;
4
+ type TableColumnWidthLike = {
5
+ key?: PropertyKey;
6
+ width?: DataTableWidth;
7
+ isAction?: boolean;
8
+ };
9
+ export declare const getDataTableColumnWidth: <T extends TableColumnWidthLike>(column: T, defaultColumnWidth: DataTableWidth, actionColumnWidth?: number) => string;
10
+ export declare const getDataTableColumnStyle: <T extends TableColumnWidthLike>(column: T, defaultColumnWidth: DataTableWidth, actionColumnWidth?: number) => CSSProperties;
11
+ export declare const getDataTableFixedOffset: (widths: string[]) => string;
12
+ export {};
@@ -0,0 +1,33 @@
1
+ //#region packages/react/ui/components/DataTable/dataTableWidth.ts
2
+ var numericWidthPattern = /^-?(?:\d+|\d*\.\d+)$/;
3
+ var hasWidthValue = (value) => value !== void 0 && value !== null && value !== "";
4
+ var normalizeTableWidth = (value) => {
5
+ if (!hasWidthValue(value)) return;
6
+ if (typeof value === "number") return Number.isFinite(value) ? `${value}px` : void 0;
7
+ const trimmed = value.trim();
8
+ if (trimmed === "") return;
9
+ return numericWidthPattern.test(trimmed) ? `${trimmed}px` : trimmed;
10
+ };
11
+ var hasExplicitWidth = (value) => value !== void 0 && value !== null && value !== "";
12
+ var getDataTableColumnWidth = (column, defaultColumnWidth, actionColumnWidth = 96) => {
13
+ const hasAction = column.isAction ?? column.key === "action";
14
+ return normalizeTableWidth(hasExplicitWidth(column.width) ? column.width : hasAction ? actionColumnWidth : defaultColumnWidth) ?? "0px";
15
+ };
16
+ var getDataTableColumnStyle = (column, defaultColumnWidth, actionColumnWidth = 96) => {
17
+ const hasAction = column.isAction ?? column.key === "action";
18
+ if (hasExplicitWidth(column.width) || hasAction) {
19
+ const width = getDataTableColumnWidth(column, defaultColumnWidth, actionColumnWidth);
20
+ return {
21
+ width,
22
+ minWidth: width
23
+ };
24
+ }
25
+ return { minWidth: normalizeTableWidth(defaultColumnWidth) ?? "0px" };
26
+ };
27
+ var getDataTableFixedOffset = (widths) => {
28
+ if (widths.length === 0) return "0px";
29
+ if (widths.length === 1) return widths[0];
30
+ return `calc(${widths.join(" + ")})`;
31
+ };
32
+ //#endregion
33
+ export { getDataTableColumnStyle, getDataTableColumnWidth, getDataTableFixedOffset, normalizeTableWidth };
@@ -0,0 +1,39 @@
1
+ import { getDataTableColumnStyle, getDataTableColumnWidth, getDataTableFixedOffset, normalizeTableWidth } from "./dataTableWidth.js";
2
+ import assert from "node:assert/strict";
3
+ import test from "node:test";
4
+ //#region packages/react/ui/components/DataTable/dataTableWidth.test.ts
5
+ test("normalizeTableWidth converts numeric widths to px", () => {
6
+ assert.equal(normalizeTableWidth(160), "160px");
7
+ assert.equal(normalizeTableWidth("160"), "160px");
8
+ assert.equal(normalizeTableWidth("160px"), "160px");
9
+ assert.equal(normalizeTableWidth("calc(100% - 20px)"), "calc(100% - 20px)");
10
+ assert.equal(normalizeTableWidth(""), void 0);
11
+ });
12
+ test("getDataTableColumnWidth falls back to default and action widths", () => {
13
+ assert.equal(getDataTableColumnWidth({ key: "name" }, 120), "120px");
14
+ assert.equal(getDataTableColumnWidth({ key: "action" }, 120), "96px");
15
+ assert.equal(getDataTableColumnWidth({
16
+ key: "name",
17
+ width: "180"
18
+ }, 120), "180px");
19
+ assert.equal(getDataTableColumnWidth({
20
+ key: "name",
21
+ isAction: true
22
+ }, 120), "96px");
23
+ });
24
+ test("getDataTableColumnStyle keeps width and minWidth aligned", () => {
25
+ assert.deepEqual(getDataTableColumnStyle({
26
+ key: "name",
27
+ width: "240"
28
+ }, 120), {
29
+ width: "240px",
30
+ minWidth: "240px"
31
+ });
32
+ assert.deepEqual(getDataTableColumnStyle({ key: "name" }, 120), { minWidth: "120px" });
33
+ });
34
+ test("getDataTableFixedOffset combines widths in order", () => {
35
+ assert.equal(getDataTableFixedOffset([]), "0px");
36
+ assert.equal(getDataTableFixedOffset(["48px"]), "48px");
37
+ assert.equal(getDataTableFixedOffset(["48px", "120px"]), "calc(48px + 120px)");
38
+ });
39
+ //#endregion
@@ -24,7 +24,7 @@ interface DataTableProps<T = Record<string, unknown>> {
24
24
  rowSelection?: RowSelection<T>;
25
25
  pagination?: PaginationProps;
26
26
  loading?: boolean;
27
- defaultColumnWidth?: number;
27
+ defaultColumnWidth?: number | string;
28
28
  }
29
29
  export declare function DataTable<T = Record<string, unknown>>({ columns, data: pData, loading, rowKey, rowSelection, defaultColumnWidth, pagination: pPagination, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
30
30
  export { ActionBtn } from "./ActionBtn";
@@ -10,13 +10,14 @@ import "../table/index.js";
10
10
  import { Skeleton } from "../Skeleton/Skeleton.js";
11
11
  import "../Skeleton/index.js";
12
12
  import { ActionBtn } from "./ActionBtn.js";
13
+ import { getDataTableColumnStyle, getDataTableColumnWidth, getDataTableFixedOffset, normalizeTableWidth } from "./dataTableWidth.js";
13
14
  import { useMemo, useState } from "react";
14
15
  import { jsx, jsxs } from "react/jsx-runtime";
15
16
  //#region packages/react/ui/components/DataTable/index.tsx
16
17
  var defaultRowKey = "id";
17
18
  var rowSelectionColumnWidth = 48;
18
19
  var actionColumnWidth = 96;
19
- var zeroOffset = "0px";
20
+ var rowSelectionColumnWidthStyle = normalizeTableWidth(rowSelectionColumnWidth) ?? "48px";
20
21
  var getRowKey = (record, index, rowKey = defaultRowKey) => {
21
22
  if (typeof rowKey === "function") return rowKey(record, index);
22
23
  const key = record[rowKey];
@@ -32,27 +33,6 @@ var renderCellContent = (column, value, record, rowIndex, hasAction) => {
32
33
  });
33
34
  return column.render ? column.render(value, record, rowIndex) : value;
34
35
  };
35
- var getColumnWidth = (column, defaultColumnWidth) => {
36
- const hasAction = column.isAction ?? column.key === "action";
37
- if (column.width) return column.width;
38
- return `${hasAction ? actionColumnWidth : defaultColumnWidth}px`;
39
- };
40
- var getColumnStyle = (column, defaultColumnWidth) => {
41
- const hasAction = column.isAction ?? column.key === "action";
42
- if (column.width || hasAction) {
43
- const width = getColumnWidth(column, defaultColumnWidth);
44
- return {
45
- width,
46
- minWidth: width
47
- };
48
- }
49
- return { minWidth: defaultColumnWidth };
50
- };
51
- var getFixedOffset = (widths) => {
52
- if (widths.length === 0) return zeroOffset;
53
- if (widths.length === 1) return widths[0];
54
- return `calc(${widths.join(" + ")})`;
55
- };
56
36
  function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowSelection, defaultColumnWidth = 100, pagination: pPagination }) {
57
37
  const t = useI18n();
58
38
  const getCellValue = (record, column) => record[column.dataIndex || column.key];
@@ -127,21 +107,21 @@ function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowS
127
107
  column,
128
108
  index,
129
109
  fixed: column.fixed ?? (hasAction ? "right" : void 0),
130
- width: getColumnWidth(column, defaultColumnWidth)
110
+ width: getDataTableColumnWidth(column, defaultColumnWidth, actionColumnWidth)
131
111
  };
132
112
  });
133
- const leftOffsetWidths = rowSelection ? [`${rowSelectionColumnWidth}px`] : [];
113
+ const leftOffsetWidths = rowSelection ? [rowSelectionColumnWidthStyle] : [];
134
114
  const leftOffsets = /* @__PURE__ */ new Map();
135
115
  for (const item of columnsWithFixed) {
136
116
  if (item.fixed !== "left") continue;
137
- leftOffsets.set(item.index, getFixedOffset(leftOffsetWidths));
117
+ leftOffsets.set(item.index, getDataTableFixedOffset(leftOffsetWidths));
138
118
  leftOffsetWidths.push(item.width);
139
119
  }
140
120
  const rightOffsetWidths = [];
141
121
  const rightOffsets = /* @__PURE__ */ new Map();
142
122
  for (const item of [...columnsWithFixed].reverse()) {
143
123
  if (item.fixed !== "right") continue;
144
- rightOffsets.set(item.index, getFixedOffset(rightOffsetWidths));
124
+ rightOffsets.set(item.index, getDataTableFixedOffset(rightOffsetWidths));
145
125
  rightOffsetWidths.push(item.width);
146
126
  }
147
127
  return columnsWithFixed.map((item) => ({
@@ -162,8 +142,8 @@ function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowS
162
142
  fixed: "left",
163
143
  showSeparator: false,
164
144
  style: {
165
- width: "48px",
166
- minWidth: "48px"
145
+ width: rowSelectionColumnWidthStyle,
146
+ minWidth: rowSelectionColumnWidthStyle
167
147
  },
168
148
  children: [rowSelection.beforeCheckboxNode, /* @__PURE__ */ jsx(Checkbox, {
169
149
  checked: allChecked,
@@ -177,7 +157,7 @@ function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowS
177
157
  fixed,
178
158
  fixedOffset,
179
159
  hideSeparatorWhenFixedActive: fixed === "right",
180
- style: getColumnStyle(column, defaultColumnWidth),
160
+ style: getDataTableColumnStyle(column, defaultColumnWidth, actionColumnWidth),
181
161
  children: column.title
182
162
  }, column.key);
183
163
  })] }) }), /* @__PURE__ */ jsx(TableBody, { children: data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, {
@@ -196,8 +176,8 @@ function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowS
196
176
  return /* @__PURE__ */ jsxs(TableRow, { children: [rowSelection && /* @__PURE__ */ jsx(TableCell, {
197
177
  fixed: "left",
198
178
  style: {
199
- width: "48px",
200
- minWidth: "48px"
179
+ width: rowSelectionColumnWidthStyle,
180
+ minWidth: rowSelectionColumnWidthStyle
201
181
  },
202
182
  children: /* @__PURE__ */ jsx(Checkbox, {
203
183
  checked: selectedKeySet.has(recordKey),
@@ -211,7 +191,7 @@ function DataTable({ columns, data: pData, loading, rowKey = defaultRowKey, rowS
211
191
  isAction: hasAction,
212
192
  fixed,
213
193
  fixedOffset,
214
- style: getColumnStyle(column, defaultColumnWidth),
194
+ style: getDataTableColumnStyle(column, defaultColumnWidth, actionColumnWidth),
215
195
  children: renderCellContent(column, value, record, rowIndex, hasAction)
216
196
  }, column.key);
217
197
  })] }, recordKey);
@@ -1,5 +1,5 @@
1
1
  import type { ChangeEvent, TextareaHTMLAttributes } from "react";
2
- export type TextareaProps = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "onChange" | "defaultValue"> & {
2
+ export type TextareaProps = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange' | 'defaultValue'> & {
3
3
  value?: string;
4
4
  onChange?: (v: string, e: ChangeEvent<HTMLTextAreaElement>) => void;
5
5
  defaultValue?: string;
@@ -21,7 +21,7 @@ var Textarea = forwardRef(({ className, textareaClassName, value: controlledValu
21
21
  setInternalValue
22
22
  ]);
23
23
  return /* @__PURE__ */ jsxs("div", {
24
- className: cn("tc-ui-textarea relative w-fit", className),
24
+ className: cn("tc-ui-textarea relative", className),
25
25
  children: [/* @__PURE__ */ jsx("textarea", {
26
26
  ref: setRefs,
27
27
  value,
@@ -0,0 +1,21 @@
1
+ export type ColumnDefForKey<T> = {
2
+ [K in keyof T]: {
3
+ key: K;
4
+ title: string;
5
+ dataIndex?: string;
6
+ width?: number | string;
7
+ isAction?: boolean;
8
+ render?: (value: T[K], record: T, index: number) => React.ReactNode;
9
+ renderExport?: (value: T[K], record: T, index: number) => React.ReactNode;
10
+ };
11
+ }[keyof T];
12
+ export type ColumnDefAction<T> = {
13
+ key: 'action';
14
+ title: string;
15
+ dataIndex?: string;
16
+ width?: number | string;
17
+ isAction?: boolean;
18
+ render?: (value: unknown, record: T, index: number) => React.ReactNode;
19
+ renderExport?: (value: unknown, record: T, index: number) => React.ReactNode;
20
+ };
21
+ export type ColumnDef<T = Record<string, unknown>> = ColumnDefForKey<T> | ColumnDefAction<T>;
@@ -1,2 +1,13 @@
1
- import type { I18nInterpolationValues, I18nTranslateOptions } from "../../../../fe/packages/react/ui/i18n/index";
1
+ import type { I18nAddResourcesOptions, I18nDictionary, I18nInterpolationValues, I18nLanguage, I18nResources, I18nSetResourcesOptions, I18nTranslateOptions } from "../../../../fe/packages/react/ui/i18n/index";
2
+ export declare const addLanguageResources: (language: I18nLanguage, messages: I18nDictionary, options?: I18nAddResourcesOptions) => void;
3
+ export declare const setLanguage: (language: I18nLanguage) => void;
4
+ export declare const setFallbackLanguage: (language: I18nLanguage) => void;
5
+ export declare const setResources: (resources: I18nResources, options?: I18nSetResourcesOptions) => void;
6
+ export declare const getCurrentLanguage: () => string;
7
+ export declare const getFallbackLanguage: () => string;
8
+ export declare const getI18nResources: () => Partial<Record<string, I18nDictionary>>;
9
+ export declare const getSupportedLanguages: () => string[];
10
+ export declare const registerFrontendI18nResources: (resources?: I18nResources) => Promise<void>;
2
11
  export declare const getText: (key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string;
12
+ export declare const t: <T = string>(key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string | T;
13
+ export type { I18nAddResourcesOptions, I18nDictionary, I18nInterpolationValues, I18nLanguage, I18nResources, I18nSetResourcesOptions, I18nTranslateOptions, };
@@ -0,0 +1,3 @@
1
+ import type { I18nInterpolationValues, I18nTranslateOptions } from "../../../../fe/packages/react/ui/i18n/index";
2
+ export type TextTranslator = <T = string>(key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => T | string;
3
+ export declare const useText: () => TextTranslator;
@@ -1,6 +1,4 @@
1
- import type { I18nResources } from "../../../../fe/packages/react/ui/i18n/index";
2
1
  export declare const i18nKeyPrefix = "$i18n::";
3
- export declare const frontendI18nResources: I18nResources;
4
2
  export declare const withI18nKey: (key: string) => string;
5
3
  export declare const frontendLangKeys: {
6
4
  readonly appTitle: string;