@_tc/template-core 0.2.0-bate.3 → 0.2.0-bate.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENT_README.md CHANGED
@@ -19,7 +19,7 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
19
19
  | --- | --- |
20
20
  | `@_tc/template-core` | `serverStart`、`baseFn`、Koa/Controller/Service 类型。 |
21
21
  | `@_tc/template-core/bundler` | `buildFE()`、`buildBE()`。 |
22
- | `@_tc/template-core/fe` | 前端初始化、请求方法、Dashboard/Schema 类型、共享状态、业务前端组件。 |
22
+ | `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、请求方法、Dashboard/Schema 类型、token 工具、共享状态、业务前端组件。 |
23
23
  | `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径。 |
24
24
  | `@_tc/template-core/fe/rc` | React UI 组件和 SchemaForm 组件。 |
25
25
  | `@_tc/template-core/fe/tailwind_ui.css` | 内置前端/UI 全局样式。 |
@@ -367,15 +367,23 @@ import '@_tc/template-core/fe/tailwind_ui.css'
367
367
 
368
368
  ```ts
369
369
  import {
370
+ addLanguage,
371
+ addLanguageResources,
370
372
  clearRafTimer,
371
373
  api,
374
+ clearAuthToken,
372
375
  get,
376
+ getAuthToken,
377
+ localKeyMap,
373
378
  post,
379
+ renderImportComponent,
374
380
  request,
375
381
  rafSetInterval,
376
382
  rafSetTimeout,
377
383
  schemaEventBus,
378
384
  schemaStore,
385
+ setAuthToken,
386
+ setLanguage,
379
387
  useSchemaStore,
380
388
  LanguageSwitch,
381
389
  ThemeSwitch,
@@ -407,11 +415,12 @@ import { Button, DataTable, Form, Input, Modal, Select } from '@_tc/template-cor
407
415
  - RAF 计时器:`rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`。
408
416
  - 请求类型:`BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError`。
409
417
  - 请求 header:自动添加 `s_t`、`s_sign`、`projk`;存在短 token 时添加 `Authorization: Bearer ${token}`。
418
+ - Token 工具:`getAuthToken()`、`setAuthToken()`、`clearAuthToken()`、`localKeyMap`;`getAuthToken()` 是同步函数,读取前无需 `await`。
410
419
  - 本地 key:短 token 是 `localStorage.auth_token`,项目 key 是 `localStorage.p_J_k`;刷新 token header 默认名是 `RT`。
411
- - `getAuthToken()` 是同步函数,读取前无需 `await`。
420
+ - 组件加载辅助:`renderImportComponent(import('./Page'))` 会用 `React.lazy` + `Suspense` 渲染动态组件。
412
421
  - Schema 通信:`schemaEventBus`、`eventsInfo`、`merge`。
413
422
  - 共享状态:`modeStore`、`schemaStore`、`apiFreezerStore` 及对应 hooks。
414
- - 多语言:`i18nStore.getState().addResources()`,配置文案可写 `$i18n::...`。
423
+ - 多语言:`addLanguageResources()` / `addResources()` 追加某语种文案,`addLanguage()` 新增语种,`setLanguage()` 切换语言,配置文案可写 `$i18n::...`。
415
424
  - 主题:`ThemeSwitch` 会同步根节点 `dark` class 和 `localStorage`。
416
425
  - `Input type="password"` 会自动显示密码显隐按钮;`allowClear` 不作用于密码输入。
417
426
  - RAF 计时器只在浏览器环境可用,不适合 Node 侧调用。
package/README.md CHANGED
@@ -176,14 +176,15 @@ http://localhost:9000/dash?projk=demo
176
176
 
177
177
  ## 常用公开入口
178
178
 
179
- 完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks/*` 等子路径。
179
+ 完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks` 等子路径。
180
180
 
181
181
  | 入口 | 用途 |
182
182
  | --- | --- |
183
183
  | `@_tc/template-core` | 服务启动、基础 Controller/Service、Koa 类型 |
184
184
  | `@_tc/template-core/bundler` | 构建入口,提供前端资源构建 `buildFE` 和消费方 Node/backend 构建 `buildBE` |
185
- | `@_tc/template-core/fe` | 前端初始化、Dash 路由扩展、请求方法、SchemaPage 事件、共享状态和内置前端组件 |
185
+ | `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、Dash 路由扩展、请求方法、SchemaPage 事件、token 工具、共享状态和内置前端组件 |
186
186
  | `@_tc/template-core/fe/rc` | UI/SchemaForm 组件和类型 |
187
+ | `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口 |
187
188
  | `@_tc/template-core/fe/tailwind_ui.css` | 前端全局样式入口,源码对应 `frontend/src/main.css` |
188
189
  | `@_tc/template-core/model` | model 配置类型 |
189
190
 
@@ -310,18 +311,33 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
310
311
  import {
311
312
  api,
312
313
  apiFreezerStore,
314
+ addLanguage,
315
+ addLanguageResources,
316
+ addResources,
313
317
  AsyncSelect,
318
+ clearAuthToken,
314
319
  eventsInfo,
320
+ getCurrentLanguage,
321
+ getFallbackLanguage,
315
322
  FreezeState,
316
323
  get,
324
+ getSupportedLanguages,
325
+ getAuthToken,
317
326
  LanguageSwitch,
327
+ localKeyMap,
318
328
  merge,
319
329
  modeStore,
320
330
  post,
331
+ renderImportComponent,
321
332
  request,
322
333
  schemaEventBus,
323
334
  schemaStore,
335
+ setFallbackLanguage,
336
+ setLanguage,
337
+ setResources,
338
+ setAuthToken,
324
339
  ThemeSwitch,
340
+ t,
325
341
  useApiFreezer,
326
342
  useModeStore,
327
343
  useSchemaStore,
@@ -352,29 +368,34 @@ import type {
352
368
  | --- | --- |
353
369
  | 应用启动 | `initApp` |
354
370
  | 内置前端组件 | `AsyncSelect`、`LanguageSwitch`、`ThemeSwitch` |
371
+ | 组件加载辅助 | `renderImportComponent` |
355
372
  | Dash 扩展类型 | `DashRoutesExtender`、`DashRoutesContext`、`DashComponentsMap`、`DashHeaderUserAreaProps`、`DashRouteGuard` |
356
373
  | SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer` |
357
374
  | SchemaForm 类型 | `FormFieldSchema`、`SchemaFormComponentsMap`、`SchemaFormNamespace`、`SelectProps` |
358
375
  | 请求方法 | `api`、`request`、`get`、`post`、`put`、`patch`、`del` |
359
376
  | 请求类型 | `BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError` |
377
+ | Token 工具 | `getAuthToken`、`setAuthToken`、`clearAuthToken`、`localKeyMap` |
378
+ | 多语言工具 | `getText`、`t`、`addLanguage`、`addLanguageResources`、`addResources`、`setLanguage`、`setFallbackLanguage`、`setResources`、`getCurrentLanguage`、`getFallbackLanguage`、`getSupportedLanguages` |
360
379
  | 请求冻结 | `apiFreezerStore`、`useApiFreezer`、`FreezeState`、`ApiFreezerRequestMatcher` |
361
380
  | 事件工具 | `eventsInfo`、`merge` |
362
381
  | 共享状态 | `modeStore`、`useModeStore`、`schemaStore`、`useSchemaStore`、`schemaEventBus` |
363
382
 
364
383
  `modeStore` 管项目模型和当前项目数据,`schemaStore` 管当前 Schema 页面的 schema/cache,`schemaEventBus` 用来在 Search、Table、CallCom 之间通信。
365
384
 
385
+ `renderImportComponent` 封装了 `React.lazy` + `Suspense`,默认会用页面骨架屏作为 fallback。`getAuthToken()`、`setAuthToken()` 和 `clearAuthToken()` 用于读写或清理本地短 token,`localKeyMap` 暴露对应的本地存储 key 常量。
386
+
366
387
  只使用请求层时,也可以从 `@_tc/template-core/fe/common/request` 导入 `api`、请求方法和请求类型;这是发布包显式子路径,不要下钻到 `frontend/src/common/request`。
367
388
 
368
389
  ### 前端多语言
369
390
 
370
- TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n 能力。框架内置中文、英文资源,项目可以继续追加自己的资源。
391
+ TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n 能力。框架内置中文、英文资源,项目可以继续追加自己的资源或新增语种。
371
392
 
372
393
  **追加自定义语言资源**:
373
394
 
374
395
  ```ts
375
- import { i18nStore } from '@_tc/template-core/fe'
396
+ import { addLanguageResources } from '@_tc/template-core/fe'
376
397
 
377
- i18nStore.getState().addResources('zh-CN', {
398
+ addLanguageResources('zh-CN', {
378
399
  business: {
379
400
  product: {
380
401
  menu: '商品管理',
@@ -397,6 +418,24 @@ i18nStore.getState().addResources('en-US', {
397
418
  })
398
419
  ```
399
420
 
421
+ **新增语种并切换**:
422
+
423
+ ```ts
424
+ import { addLanguage, setLanguage } from '@_tc/template-core/fe'
425
+
426
+ addLanguage('ja-JP', {
427
+ business: {
428
+ product: {
429
+ menu: '商品管理',
430
+ },
431
+ },
432
+ })
433
+
434
+ setLanguage('ja-JP')
435
+ ```
436
+
437
+ `addLanguageResources()` / `addResources()` 默认会深合并同语种文案;传 `{ merge: false }` 可以替换该语种资源。`setResources(resources, { merge: true })` 可批量合并多语种资源。`LanguageSwitch` 默认会把已注册语种加入选项;需要自定义展示文案时仍可传入 `options`。
438
+
400
439
  资源注册时不写 `$i18n::` 前缀,配置中使用时才写:
401
440
 
402
441
  ```ts
@@ -502,7 +541,7 @@ export function Toolbar() {
502
541
  }
503
542
  ```
504
543
 
505
- `ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class
544
+ `ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class。默认 Dashboard 会在渲染前调用 `initThemeMode()`,让已保存主题尽早生效。
506
545
 
507
546
  常用参数:
508
547
 
@@ -514,6 +553,17 @@ export function Toolbar() {
514
553
  | `persist` | 是否写入 localStorage,默认 `true`。 |
515
554
  | `storageKey` | 自定义本地存储 key,默认 `tc_theme`。 |
516
555
 
556
+ 如需在自定义入口或组件外手动初始化/切换主题,可以从 `@_tc/template-core/fe` 导入主题工具:
557
+
558
+ ```ts
559
+ import { applyThemeMode, getCurrentThemeMode, initThemeMode, themeSwitchStorageKey } from '@_tc/template-core/fe'
560
+
561
+ initThemeMode()
562
+ applyThemeMode('dark', true)
563
+ ```
564
+
565
+ `@_tc/template-core/fe/rc` 和 `@_tc/template-core/fe/rc/hooks` 也会随发布包提供对应 UI 与 hooks 入口;hooks 汇总入口包含 `useBreadcrumb`、`useExecuteOnce`、`useInit`、`useLanguage`、`usePagination`、`useRefState`、`useWatch`。
566
+
517
567
  ### 前端请求封装详解
518
568
 
519
569
  框架内置的请求封装基于 `@tc/common/http`,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
@@ -1,6 +1,7 @@
1
1
  import { QK, leftSidebarBasePath } from "../../src/common/menu.js";
2
2
  import Dashboard from "./Dashboard.js";
3
3
  import { renderImportComponent } from "../../src/common/importComponent.js";
4
+ import { initThemeMode } from "../../src/common/theme.js";
4
5
  import { initApp } from "../../src/main.js";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  import extendDashRoutes from "@tc/scalability/dash/customRoutes";
@@ -54,6 +55,7 @@ initApp(({ children }) => /* @__PURE__ */ jsx("div", {
54
55
  }), {
55
56
  routes: getDefaultPageRoutes(),
56
57
  beforeRender: async (context) => {
58
+ initThemeMode();
57
59
  if (typeof initDash === "function") await initDash(context);
58
60
  }
59
61
  });
@@ -1,2 +1,14 @@
1
- import type { I18nInterpolationValues, I18nTranslateOptions } from "../../../packages/react/ui/i18n/index";
1
+ import type { I18nAddResourcesOptions, I18nDictionary, I18nInterpolationValues, I18nLanguage, I18nResources, I18nSetResourcesOptions, I18nTranslateOptions } from "../../../packages/react/ui/i18n/index";
2
+ export declare const addLanguageResources: (language: I18nLanguage, messages: I18nDictionary, options?: I18nAddResourcesOptions) => void;
3
+ export declare const addResources: (language: I18nLanguage, messages: I18nDictionary, options?: I18nAddResourcesOptions) => void;
4
+ export declare const addLanguage: (language: I18nLanguage, messages?: I18nDictionary, options?: I18nAddResourcesOptions) => void;
5
+ export declare const setLanguage: (language: I18nLanguage) => void;
6
+ export declare const setFallbackLanguage: (language: I18nLanguage) => void;
7
+ export declare const setResources: (resources: I18nResources, options?: I18nSetResourcesOptions) => void;
8
+ export declare const getCurrentLanguage: () => string;
9
+ export declare const getFallbackLanguage: () => string;
10
+ export declare const getI18nResources: () => Partial<Record<string, I18nDictionary>>;
11
+ export declare const getSupportedLanguages: () => string[];
2
12
  export declare const getText: (key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string;
13
+ export declare const t: <T = string>(key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string | T;
14
+ export type { I18nAddResourcesOptions, I18nDictionary, I18nInterpolationValues, I18nLanguage, I18nResources, I18nSetResourcesOptions, I18nTranslateOptions, };
@@ -2,11 +2,32 @@ import { frontendI18nResources, i18nKeyPrefix } from "../language/index.js";
2
2
  import { i18n, i18nStore } from "../../../packages/common/i18n/index.js";
3
3
  import "../../../packages/react/ui/i18n/index.js";
4
4
  //#region frontend/src/common/language.ts
5
- i18nStore.getState().addResources("zh-CN", frontendI18nResources["zh-CN"] ?? {});
6
- i18nStore.getState().addResources("en-US", frontendI18nResources["en-US"] ?? {});
5
+ var addLanguageResources = (language, messages, options) => {
6
+ i18nStore.getState().addResources(language, messages, options);
7
+ };
8
+ var addResources = addLanguageResources;
9
+ var addLanguage = (language, messages = {}, options) => {
10
+ addLanguageResources(language, messages, options);
11
+ };
12
+ var setLanguage = (language) => {
13
+ i18nStore.getState().setLanguage(language);
14
+ };
15
+ var setFallbackLanguage = (language) => {
16
+ i18nStore.getState().setFallbackLanguage(language);
17
+ };
18
+ var setResources = (resources, options) => {
19
+ i18nStore.getState().setResources(resources, options);
20
+ };
21
+ var getCurrentLanguage = () => i18nStore.getState().language;
22
+ var getFallbackLanguage = () => i18nStore.getState().fallbackLanguage;
23
+ var getI18nResources = () => i18nStore.getState().resources;
24
+ var getSupportedLanguages = () => Object.keys(getI18nResources());
25
+ addLanguageResources("zh-CN", frontendI18nResources["zh-CN"] ?? {});
26
+ addLanguageResources("en-US", frontendI18nResources["en-US"] ?? {});
7
27
  var getText = (key, fillingData, options) => {
8
28
  if (key.includes("$i18n::")) return i18n(key.replace(i18nKeyPrefix, ""), fillingData, options);
9
29
  return key;
10
30
  };
31
+ var t = i18n;
11
32
  //#endregion
12
- export { getText };
33
+ export { addLanguage, addLanguageResources, addResources, getCurrentLanguage, getFallbackLanguage, getI18nResources, getSupportedLanguages, getText, setFallbackLanguage, setLanguage, setResources, t };
@@ -0,0 +1,7 @@
1
+ export type ThemeSwitchMode = 'light' | 'dark';
2
+ export declare const themeSwitchStorageKey = "tc_theme";
3
+ export declare const getStoredThemeMode: (storageKey?: string) => ThemeSwitchMode | null;
4
+ export declare const getCurrentThemeMode: (defaultValue?: ThemeSwitchMode, storageKey?: string) => ThemeSwitchMode;
5
+ export declare const persistThemeMode: (mode: ThemeSwitchMode, storageKey?: string) => void;
6
+ export declare const applyThemeMode: (mode?: ThemeSwitchMode, persist?: boolean, storageKey?: string) => void;
7
+ export declare const initThemeMode: (defaultValue?: ThemeSwitchMode, storageKey?: string) => ThemeSwitchMode;
@@ -0,0 +1,33 @@
1
+ //#region frontend/src/common/theme.ts
2
+ var themeSwitchStorageKey = "tc_theme";
3
+ var canUseDocument = () => typeof document !== "undefined";
4
+ var canUseLocalStorage = () => typeof localStorage !== "undefined";
5
+ var getStoredThemeMode = (storageKey = themeSwitchStorageKey) => {
6
+ if (!canUseLocalStorage()) return null;
7
+ const value = localStorage.getItem(storageKey);
8
+ return value === "light" || value === "dark" ? value : null;
9
+ };
10
+ var getCurrentThemeMode = (defaultValue, storageKey = themeSwitchStorageKey) => {
11
+ const storedMode = getStoredThemeMode(storageKey);
12
+ if (storedMode) return storedMode;
13
+ if (defaultValue) return defaultValue;
14
+ if (!canUseDocument()) return "light";
15
+ return document.documentElement.classList.contains("dark") ? "dark" : "light";
16
+ };
17
+ var persistThemeMode = (mode, storageKey = themeSwitchStorageKey) => {
18
+ if (canUseLocalStorage()) localStorage.setItem(storageKey, mode);
19
+ };
20
+ var applyThemeMode = (mode = getCurrentThemeMode(), persist = false, storageKey = themeSwitchStorageKey) => {
21
+ if (!canUseDocument()) return;
22
+ const root = document.documentElement;
23
+ root.classList.toggle("dark", mode === "dark");
24
+ root.style.colorScheme = mode;
25
+ if (persist) persistThemeMode(mode, storageKey);
26
+ };
27
+ var initThemeMode = (defaultValue, storageKey = themeSwitchStorageKey) => {
28
+ const mode = getCurrentThemeMode(defaultValue, storageKey);
29
+ applyThemeMode(mode, false, storageKey);
30
+ return mode;
31
+ };
32
+ //#endregion
33
+ export { applyThemeMode, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey };
@@ -2,7 +2,7 @@ import { frontendLangKeys } from "../../language/index.js";
2
2
  import { i18nStore } from "../../../../packages/common/i18n/index.js";
3
3
  import { useI18nStore } from "../../../../packages/react/ui/i18n/useI18n.js";
4
4
  import "../../../../packages/react/ui/i18n/index.js";
5
- import { getText } from "../../common/language.js";
5
+ import { getSupportedLanguages, getText } from "../../common/language.js";
6
6
  import { cn } from "../../../../packages/react/ui/lib/utils.js";
7
7
  import { Button } from "../../../../packages/react/ui/components/Button/Button.js";
8
8
  import { Dropdown } from "../../../../packages/react/ui/components/Dropdown/Dropdown.js";
@@ -20,10 +20,23 @@ var getDefaultLanguageOptions = () => [{
20
20
  value: "en-US",
21
21
  searchText: "en-US English"
22
22
  }];
23
+ var getLanguageOptions = () => {
24
+ const baseOptions = getDefaultLanguageOptions();
25
+ const seen = new Set(baseOptions.map((option) => option.value));
26
+ return [...baseOptions, ...getSupportedLanguages().filter((language) => !seen.has(language)).map((language) => ({
27
+ label: language,
28
+ value: language,
29
+ searchText: language
30
+ }))];
31
+ };
23
32
  var LanguageSwitch = ({ value, defaultValue, options, onChange, className, buttonClassName, placeholder, disabled, loading, clearable: _clearable, searchable: _searchable, placement = "bottom-end", getPopupContainer = "parent", ...props }) => {
24
33
  const rootRef = useRef(null);
25
34
  const currentLanguage = useI18nStore((state) => state.language);
26
- const mergedOptions = useMemo(() => options ?? getDefaultLanguageOptions(), [currentLanguage, options]);
35
+ const mergedOptions = useMemo(() => options ?? getLanguageOptions(), [
36
+ currentLanguage,
37
+ options,
38
+ useI18nStore((state) => state.resources)
39
+ ]);
27
40
  const selectedLanguage = value ?? currentLanguage ?? defaultValue;
28
41
  const selectedOption = mergedOptions.find((option) => option.value === selectedLanguage);
29
42
  const displayText = selectedOption?.label ?? placeholder ?? getText(frontendLangKeys.languageSwitchPlaceholder);
@@ -1,4 +1,6 @@
1
- export type ThemeSwitchMode = 'light' | 'dark';
1
+ import { type ThemeSwitchMode } from "../../common/theme";
2
+ export { applyThemeMode, themeSwitchStorageKey } from "../../common/theme";
3
+ export type { ThemeSwitchMode } from "../../common/theme";
2
4
  export interface ThemeSwitchProps {
3
5
  value?: ThemeSwitchMode;
4
6
  defaultValue?: ThemeSwitchMode;
@@ -9,6 +11,5 @@ export interface ThemeSwitchProps {
9
11
  persist?: boolean;
10
12
  storageKey?: string;
11
13
  }
12
- export declare const themeSwitchStorageKey = "tc_theme";
13
14
  declare const ThemeSwitch: ({ value, defaultValue, onChange, disabled, className, showLabel, persist, storageKey, }: ThemeSwitchProps) => import("react/jsx-runtime").JSX.Element;
14
15
  export default ThemeSwitch;
@@ -6,35 +6,11 @@ import { cn } from "../../../../packages/react/ui/lib/utils.js";
6
6
  import { Switch } from "../../../../packages/react/ui/components/Switch/Switch.js";
7
7
  import { Tooltip } from "../../../../packages/react/ui/components/Tooltip/Tooltip.js";
8
8
  import "../../../../packages/react/ui/index.js";
9
+ import { applyThemeMode, getCurrentThemeMode, persistThemeMode, themeSwitchStorageKey } from "../../common/theme.js";
9
10
  import { useEffect, useState } from "react";
10
11
  import { jsx, jsxs } from "react/jsx-runtime";
11
12
  import { Moon, Sun } from "lucide-react";
12
13
  //#region frontend/src/components/ThemeSwitch/ThemeSwitch.tsx
13
- var themeSwitchStorageKey = "tc_theme";
14
- var canUseDocument = () => typeof document !== "undefined";
15
- var canUseLocalStorage = () => typeof localStorage !== "undefined";
16
- var getStoredThemeMode = (storageKey) => {
17
- if (!canUseLocalStorage()) return null;
18
- const value = localStorage.getItem(storageKey);
19
- return value === "light" || value === "dark" ? value : null;
20
- };
21
- var getCurrentThemeMode = (defaultValue, storageKey = themeSwitchStorageKey) => {
22
- const storedMode = getStoredThemeMode(storageKey);
23
- if (storedMode) return storedMode;
24
- if (defaultValue) return defaultValue;
25
- if (!canUseDocument()) return "light";
26
- return document.documentElement.classList.contains("dark") ? "dark" : "light";
27
- };
28
- var persistThemeMode = (mode, storageKey) => {
29
- if (canUseLocalStorage()) localStorage.setItem(storageKey, mode);
30
- };
31
- var applyThemeMode = (mode, persist, storageKey) => {
32
- if (!canUseDocument()) return;
33
- const root = document.documentElement;
34
- root.classList.toggle("dark", mode === "dark");
35
- root.style.colorScheme = mode;
36
- if (persist) persistThemeMode(mode, storageKey);
37
- };
38
14
  var ThemeSwitch = ({ value, defaultValue, onChange, disabled, className, showLabel = false, persist = true, storageKey = themeSwitchStorageKey }) => {
39
15
  useI18nStore((state) => state.language);
40
16
  const [internalMode, setInternalMode] = useState(() => getCurrentThemeMode(defaultValue, storageKey));
@@ -84,4 +60,4 @@ var ThemeSwitch = ({ value, defaultValue, onChange, disabled, className, showLab
84
60
  });
85
61
  };
86
62
  //#endregion
87
- export { ThemeSwitch as default, themeSwitchStorageKey };
63
+ export { applyThemeMode, ThemeSwitch as default, themeSwitchStorageKey };
@@ -1,3 +1,4 @@
1
1
  import ThemeSwitch from "./ThemeSwitch";
2
2
  export * from "./ThemeSwitch";
3
+ export * from "../../common/theme";
3
4
  export default ThemeSwitch;
@@ -1,5 +1,6 @@
1
- import ThemeSwitch, { themeSwitchStorageKey } from "./ThemeSwitch.js";
1
+ import { applyThemeMode, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey } from "../../common/theme.js";
2
+ import ThemeSwitch from "./ThemeSwitch.js";
2
3
  //#region frontend/src/components/ThemeSwitch/index.ts
3
4
  var ThemeSwitch_default = ThemeSwitch;
4
5
  //#endregion
5
- export { ThemeSwitch_default as default, themeSwitchStorageKey };
6
+ export { applyThemeMode, ThemeSwitch_default as default, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey };
@@ -1,7 +1,7 @@
1
1
  import HeaderView from "./BasePage/HeaderView.js";
2
+ import { applyThemeMode, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey } from "../common/theme.js";
2
3
  import { generateRouter } from "./Router/index.js";
3
4
  import AsyncSelect_default from "./AsyncSelect/index.js";
4
5
  import LanguageSwitch_default from "./LanguageSwitch/index.js";
5
- import { themeSwitchStorageKey } from "./ThemeSwitch/ThemeSwitch.js";
6
6
  import ThemeSwitch_default from "./ThemeSwitch/index.js";
7
- export { AsyncSelect_default as AsyncSelect, HeaderView, LanguageSwitch_default as LanguageSwitch, ThemeSwitch_default as ThemeSwitch, generateRouter, themeSwitchStorageKey };
7
+ export { AsyncSelect_default as AsyncSelect, HeaderView, LanguageSwitch_default as LanguageSwitch, ThemeSwitch_default as ThemeSwitch, applyThemeMode, generateRouter, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey };
@@ -4,12 +4,16 @@ export * from "./main";
4
4
  export type { CallComComponentsMap, CallComRenderer } from "./defaultPages/SchemaPage/schemaType";
5
5
  export * from "./components/index";
6
6
  export type { FormFieldSchema, SchemaFormComponentsMap, SchemaFormNamespace, SelectProps } from "../../packages/react/ui/index";
7
- export { api, del, get, patch, post, put, request } from "./common/request";
8
- export type { AxiosError, BaseResponse, PageParams, PageResponse, RequestConfig, ResponseConfig } from "./common/request";
7
+ export { renderImportComponent } from "./common/importComponent";
9
8
  export { clearRafTimer, rafClearInterval, rafClearTimeout, rafSetInterval, rafSetTimeout } from "./common/rafTimer";
10
9
  export type { RafTimerCallback, RafTimerId } from "./common/rafTimer";
10
+ export { api, del, FetchAxios, get, patch, post, put, request } from "./common/request";
11
+ export type { AxiosError, BaseResponse, PageParams, PageResponse, RequestConfig, ResponseConfig, } from "./common/request";
12
+ export { applyThemeMode, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey, } from "./common/theme";
13
+ export type { ThemeSwitchMode } from "./common/theme";
14
+ export { clearAuthToken, getAuthToken, localKeyMap, setAuthToken } from "./common/auth/index";
15
+ export * from "./common/language";
11
16
  export * from "./defaultPages/SchemaPage/data/eventInfo";
12
17
  export { merge } from "./defaultPages/SchemaPage/utils/permissions";
13
18
  export * from "./exportStore";
14
19
  export { i18n, i18nStore } from "../../packages/react/ui/i18n/index";
15
- export { getAuthToken, localKeyMap, setAuthToken } from "./common/auth/index";
@@ -1,10 +1,14 @@
1
- import { getAuthToken, localKeyMap, setAuthToken } from "./common/auth/index.js";
1
+ import { clearAuthToken, getAuthToken, localKeyMap, setAuthToken } from "./common/auth/index.js";
2
2
  import { i18n, i18nStore } from "../../packages/common/i18n/index.js";
3
3
  import "../../packages/react/ui/i18n/index.js";
4
+ import { addLanguage, addLanguageResources, addResources, getCurrentLanguage, getFallbackLanguage, getI18nResources, getSupportedLanguages, getText, setFallbackLanguage, setLanguage, setResources, t } from "./common/language.js";
4
5
  import { FreezeState, apiFreezerStore, useApiFreezer } from "./stores/apiFreezer.js";
6
+ import FetchAxios from "../../packages/common/http/index.js";
5
7
  import { api, del, get, patch, post, put, request } from "./common/request.js";
6
8
  import { modeStore, useModeStore } from "./stores/mode.js";
7
9
  import HeaderView from "./components/BasePage/HeaderView.js";
10
+ import { renderImportComponent } from "./common/importComponent.js";
11
+ import { applyThemeMode, getCurrentThemeMode, getStoredThemeMode, initThemeMode, persistThemeMode, themeSwitchStorageKey } from "./common/theme.js";
8
12
  import { generateRouter } from "./components/Router/index.js";
9
13
  import { schemaEventBus } from "./stores/schemaEventBus.js";
10
14
  import { schemaStore, useSchemaStore } from "./stores/schemaStore.js";
@@ -13,9 +17,8 @@ import { initApp } from "./main.js";
13
17
  import { clearRafTimer, rafClearInterval, rafClearTimeout, rafSetInterval, rafSetTimeout } from "./common/rafTimer.js";
14
18
  import AsyncSelect_default from "./components/AsyncSelect/index.js";
15
19
  import LanguageSwitch_default from "./components/LanguageSwitch/index.js";
16
- import { themeSwitchStorageKey } from "./components/ThemeSwitch/ThemeSwitch.js";
17
20
  import ThemeSwitch_default from "./components/ThemeSwitch/index.js";
18
21
  import "./components/index.js";
19
22
  import { eventsInfo } from "./defaultPages/SchemaPage/data/eventInfo.js";
20
23
  import { merge } from "./defaultPages/SchemaPage/utils/permissions.js";
21
- export { AsyncSelect_default as AsyncSelect, FreezeState, HeaderView, LanguageSwitch_default as LanguageSwitch, ThemeSwitch_default as ThemeSwitch, api, apiFreezerStore, clearRafTimer, del, eventsInfo, generateRouter, get, getAuthToken, i18n, i18nStore, initApp, localKeyMap, merge, modeStore, patch, post, put, rafClearInterval, rafClearTimeout, rafSetInterval, rafSetTimeout, request, schemaEventBus, schemaStore, setAuthToken, themeSwitchStorageKey, useApiFreezer, useModeStore, useSchemaStore };
24
+ export { AsyncSelect_default as AsyncSelect, FetchAxios, FreezeState, HeaderView, LanguageSwitch_default as LanguageSwitch, ThemeSwitch_default as ThemeSwitch, addLanguage, addLanguageResources, addResources, api, apiFreezerStore, applyThemeMode, clearAuthToken, clearRafTimer, del, eventsInfo, generateRouter, get, getAuthToken, getCurrentLanguage, getCurrentThemeMode, getFallbackLanguage, getI18nResources, getStoredThemeMode, getSupportedLanguages, getText, i18n, i18nStore, initApp, initThemeMode, localKeyMap, merge, modeStore, patch, persistThemeMode, post, put, rafClearInterval, rafClearTimeout, rafSetInterval, rafSetTimeout, renderImportComponent, request, schemaEventBus, schemaStore, setAuthToken, setFallbackLanguage, setLanguage, setResources, t, themeSwitchStorageKey, useApiFreezer, useModeStore, useSchemaStore };
@@ -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,2 +1,14 @@
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 addResources: (language: I18nLanguage, messages: I18nDictionary, options?: I18nAddResourcesOptions) => void;
4
+ export declare const addLanguage: (language: I18nLanguage, messages?: I18nDictionary, options?: I18nAddResourcesOptions) => void;
5
+ export declare const setLanguage: (language: I18nLanguage) => void;
6
+ export declare const setFallbackLanguage: (language: I18nLanguage) => void;
7
+ export declare const setResources: (resources: I18nResources, options?: I18nSetResourcesOptions) => void;
8
+ export declare const getCurrentLanguage: () => string;
9
+ export declare const getFallbackLanguage: () => string;
10
+ export declare const getI18nResources: () => Partial<Record<string, I18nDictionary>>;
11
+ export declare const getSupportedLanguages: () => string[];
2
12
  export declare const getText: (key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string;
13
+ export declare const t: <T = string>(key: string, fillingData?: I18nInterpolationValues, options?: I18nTranslateOptions) => string | T;
14
+ export type { I18nAddResourcesOptions, I18nDictionary, I18nInterpolationValues, I18nLanguage, I18nResources, I18nSetResourcesOptions, I18nTranslateOptions, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_tc/template-core",
3
- "version": "0.2.0-bate.3",
3
+ "version": "0.2.0-bate.5",
4
4
  "description": "A full-stack TypeScript admin framework powered by Koa, React, and Vite - monorepo root",
5
5
  "types": "./types/index.d.ts",
6
6
  "exports": {
@@ -34,10 +34,10 @@
34
34
  "require": "./fe/packages/react/ui/index.js",
35
35
  "types": "./fe/packages/react/ui/index.d.ts"
36
36
  },
37
- "./fe/rc/hooks/*": {
38
- "import": "./fe/packages/react/hooks/*",
39
- "require": "./fe/packages/react/hooks/*",
40
- "types": "./fe/packages/react/hooks/*"
37
+ "./fe/rc/hooks": {
38
+ "import": "./fe/packages/react/hooks/index.js",
39
+ "require": "./fe/packages/react/hooks/index.js",
40
+ "types": "./fe/packages/react/hooks/index.d.ts"
41
41
  },
42
42
  "./fe/rc/*": {
43
43
  "import": "./fe/packages/react/ui/*",