@4399ywkf/core 5.0.16 → 5.0.17

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/dist/index.d.ts CHANGED
@@ -278,27 +278,41 @@ declare const i18nPlugin: (options?: I18nPluginOptions | undefined) => YwkfPlugi
278
278
 
279
279
  interface ThemePluginOptions {
280
280
  /**
281
- * 是否启用暗色模式
281
+ * 是否启用暗色模式切换能力
282
282
  * @default true
283
283
  */
284
284
  darkMode?: boolean;
285
285
  /**
286
- * 默认主题模式(作为 store 的初始值,运行时可通过 useThemeStore 动态切换)
287
- * 参考 lobe-ui 默认暗色风格
288
- * @default "dark"
286
+ * 默认主题模式(运行时可通过 useThemeStore 动态切换)
287
+ * @default "light"
289
288
  */
290
289
  defaultAppearance?: "light" | "dark" | "auto";
291
290
  /**
292
- * 主色调(作为 store 的初始值,运行时可通过 useThemeStore 动态切换)
293
- * @default "#1677ff"
291
+ * 主色调(Lobe-UI 命名预设,运行时可通过 useThemeStore 动态切换)
292
+ *
293
+ * 不设置时使用 Lobe-UI 默认 primary 色阶(黑色系),
294
+ * 可选值:"blue" | "cyan" | "geekblue" | "gold" | "green" | "lime"
295
+ * | "magenta" | "orange" | "purple" | "red" | "volcano" | "yellow"
296
+ *
297
+ * @default undefined
294
298
  */
295
299
  primaryColor?: string;
296
300
  /**
297
- * 中性色(作为 store 的初始值)
301
+ * 中性色(Lobe-UI 命名预设)
302
+ *
303
+ * 可选值:"mauve" | "olive" | "sage" | "sand" | "slate"
304
+ *
305
+ * @default undefined
298
306
  */
299
307
  neutralColor?: string;
300
308
  /**
301
- * antd 前缀
309
+ * antd 组件前缀
310
+ *
311
+ * 支持三种配置方式(优先级从高到低):
312
+ * 1. 运行时环境变量 process.env.YWKF_PREFIX_CLS
313
+ * 2. 插件选项中直接指定
314
+ * 3. 默认值 "ant"
315
+ *
302
316
  * @default "ant"
303
317
  */
304
318
  prefixCls?: string;
@@ -319,14 +333,6 @@ interface ThemePluginOptions {
319
333
  * - 应用启动时读取 window.__YWKF_THEME__ 作为初始覆盖
320
334
  * - 监听 ywkf:theme-change 自定义事件,实现运行时主题同步
321
335
  *
322
- * 主应用注入示例:
323
- * ```ts
324
- * window.__YWKF_THEME__ = { primaryColor: "#ff4d4f", appearance: "dark" };
325
- * window.dispatchEvent(new CustomEvent("ywkf:theme-change", {
326
- * detail: { primaryColor: "#52c41a" },
327
- * }));
328
- * ```
329
- *
330
336
  * @default false
331
337
  */
332
338
  externalTheme?: boolean;
@@ -334,12 +340,11 @@ interface ThemePluginOptions {
334
340
  /**
335
341
  * 响应式主题系统插件
336
342
  *
337
- * 基于 antd-style + Zustand 提供运行时可变的主题管理能力:
338
- * - 生成 ThemeProvider 包裹组件到 .ywkf/theme.tsx
339
- * - 生成 useThemeStore / useTheme 等 hooks 供业务消费
340
- * - 注入 ThemeProvider 到 bootstrap
341
- * - 支持亮/暗色/跟随系统自动切换
342
- * - 支持微前端场景下主应用注入主题
343
+ * 基于 antd-style + @4399ywkf/theme-system + Zustand 提供运行时可变的主题管理:
344
+ * - 使用 Lobe-UI 色彩体系(13 阶色阶 + 自定义算法)
345
+ * - 支持 PrimaryColors / NeutralColors 命名预设
346
+ * - 亮/暗色/跟随系统自动切换
347
+ * - 支持微前端场景主应用注入主题
343
348
  *
344
349
  * @example
345
350
  * ```ts
@@ -348,26 +353,14 @@ interface ThemePluginOptions {
348
353
  * export default defineConfig({
349
354
  * plugins: [
350
355
  * themePlugin({
351
- * darkMode: true,
352
- * defaultAppearance: "auto",
353
- * primaryColor: "#1677ff",
354
- * externalTheme: true,
356
+ * defaultAppearance: "light",
357
+ * primaryColor: "geekblue",
358
+ * neutralColor: "slate",
359
+ * prefixCls: "my-app",
355
360
  * }),
356
361
  * ],
357
362
  * });
358
363
  * ```
359
- *
360
- * 业务组件中使用:
361
- * ```tsx
362
- * import { useThemeStore, useTheme } from "@/.ywkf/theme";
363
- *
364
- * function ThemeSwitch() {
365
- * const { appearance, setAppearance } = useThemeStore(
366
- * (s) => ({ appearance: s.appearance, setAppearance: s.setAppearance }),
367
- * );
368
- * return <Switch checked={appearance === "dark"} onChange={(v) => setAppearance(v ? "dark" : "light")} />;
369
- * }
370
- * ```
371
364
  */
372
365
  declare const themePlugin: (options?: ThemePluginOptions | undefined) => YwkfPlugin;
373
366
 
package/dist/index.js CHANGED
@@ -3064,13 +3064,13 @@ function scaffoldLocaleJsonDirs(cwd, localesDir, locales, defaultLocale, namespa
3064
3064
  import { join as join9 } from "path";
3065
3065
  var themePlugin = createPlugin((options = {}) => ({
3066
3066
  name: "@4399ywkf/plugin-theme",
3067
- version: "2.0.0",
3068
- description: "antd-style \u54CD\u5E94\u5F0F\u4E3B\u9898\u7CFB\u7EDF\u63D2\u4EF6",
3067
+ version: "3.0.0",
3068
+ description: "Lobe-UI \u98CE\u683C\u54CD\u5E94\u5F0F\u4E3B\u9898\u7CFB\u7EDF\u63D2\u4EF6",
3069
3069
  setup(context) {
3070
3070
  const {
3071
3071
  darkMode = true,
3072
- defaultAppearance = "dark",
3073
- primaryColor = "#1677ff",
3072
+ defaultAppearance = "light",
3073
+ primaryColor,
3074
3074
  neutralColor,
3075
3075
  prefixCls = "ant",
3076
3076
  cssVar = true,
@@ -3078,7 +3078,7 @@ var themePlugin = createPlugin((options = {}) => ({
3078
3078
  externalTheme = false
3079
3079
  } = options;
3080
3080
  const { logger } = context;
3081
- logger.info(`\u4E3B\u9898\u6A21\u5F0F: ${defaultAppearance}, \u4E3B\u8272: ${primaryColor}, \u54CD\u5E94\u5F0F: \u2713`);
3081
+ logger.info(`\u4E3B\u9898\u6A21\u5F0F: ${defaultAppearance}, \u4E3B\u8272: ${primaryColor ?? "primary(\u9ED8\u8BA4\u9ED1)"}, \u54CD\u5E94\u5F0F: \u2713`);
3082
3082
  const hooks = {
3083
3083
  modifyRspackConfig(config, ctx) {
3084
3084
  const themePath = join9(ctx.cwd, ".ywkf", "theme.tsx");
@@ -3161,7 +3161,7 @@ function generateThemeProvider(opts) {
3161
3161
  externalTheme
3162
3162
  } = opts;
3163
3163
  const sections = [];
3164
- sections.push(`// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-theme \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539`);
3164
+ sections.push(`// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-theme v3 \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539`);
3165
3165
  sections.push(buildImports({ globalReset, cssVar }));
3166
3166
  sections.push(TYPES_CODE);
3167
3167
  sections.push(buildStoreCode({ defaultAppearance, primaryColor, neutralColor }));
@@ -3177,6 +3177,7 @@ function buildImports(opts) {
3177
3177
  const reactImports = [
3178
3178
  "useCallback",
3179
3179
  "useEffect",
3180
+ "useMemo",
3180
3181
  ...opts.cssVar ? ["useLayoutEffect", "useRef"] : [],
3181
3182
  "type ReactNode"
3182
3183
  ];
@@ -3189,7 +3190,8 @@ function buildImports(opts) {
3189
3190
  import React, { ${reactImports.join(", ")} } from "react";
3190
3191
  import { ${antdStyleImports.join(", ")} } from "antd-style";
3191
3192
  import { createWithEqualityFn } from "zustand/traditional";
3192
- import { shallow } from "zustand/shallow";`;
3193
+ import { shallow } from "zustand/shallow";
3194
+ import { createThemeConfig, type PrimaryColors, type NeutralColors } from "@4399ywkf/theme-system";`;
3193
3195
  }
3194
3196
  var TYPES_CODE = `
3195
3197
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Types \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
@@ -3198,28 +3200,30 @@ export type ThemeAppearance = "light" | "dark" | "auto";
3198
3200
 
3199
3201
  export interface ThemeState {
3200
3202
  appearance: ThemeAppearance;
3201
- primaryColor: string;
3202
- neutralColor?: string;
3203
+ primaryColor?: PrimaryColors;
3204
+ neutralColor?: NeutralColors;
3203
3205
  }
3204
3206
 
3205
3207
  export interface ThemeActions {
3206
3208
  setAppearance: (mode: ThemeAppearance) => void;
3207
- setPrimaryColor: (color: string) => void;
3208
- setNeutralColor: (color: string) => void;
3209
- /** \u6279\u91CF\u66F4\u65B0\u4E3B\u9898\u72B6\u6001 */
3209
+ setPrimaryColor: (color: PrimaryColors | undefined) => void;
3210
+ setNeutralColor: (color: NeutralColors | undefined) => void;
3210
3211
  setTheme: (partial: Partial<ThemeState>) => void;
3211
3212
  }
3212
3213
 
3213
- export type ThemeStore = ThemeState & ThemeActions;`;
3214
+ export type ThemeStore = ThemeState & ThemeActions;
3215
+
3216
+ export type { PrimaryColors, NeutralColors };`;
3214
3217
  function buildStoreCode(opts) {
3215
- const neutralLine = opts.neutralColor ? `
3216
- neutralColor: "${opts.neutralColor}",` : "";
3218
+ const primaryLine = opts.primaryColor ? ` primaryColor: "${opts.primaryColor}" as PrimaryColors,` : ` primaryColor: undefined,`;
3219
+ const neutralLine = opts.neutralColor ? ` neutralColor: "${opts.neutralColor}" as NeutralColors,` : ` neutralColor: undefined,`;
3217
3220
  return `
3218
3221
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Theme Store \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3219
3222
 
3220
3223
  const DEFAULT_THEME: ThemeState = {
3221
3224
  appearance: "${opts.defaultAppearance}",
3222
- primaryColor: "${opts.primaryColor}",${neutralLine}
3225
+ ${primaryLine}
3226
+ ${neutralLine}
3223
3227
  };
3224
3228
 
3225
3229
  export const useThemeStore = createWithEqualityFn<ThemeStore>()(
@@ -3236,7 +3240,6 @@ export const useThemeStore = createWithEqualityFn<ThemeStore>()(
3236
3240
  var HOOKS_CODE = `
3237
3241
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Convenience Hooks \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3238
3242
 
3239
- /** \u83B7\u53D6\u5F53\u524D\u4E3B\u9898\u72B6\u6001\uFF08appearance + primaryColor + neutralColor\uFF09 */
3240
3243
  export const useTheme = () =>
3241
3244
  useThemeStore(
3242
3245
  (s) => ({
@@ -3247,14 +3250,10 @@ export const useTheme = () =>
3247
3250
  shallow,
3248
3251
  );
3249
3252
 
3250
- /** \u4EC5\u8BA2\u9605 appearance */
3251
3253
  export const useAppearance = () => useThemeStore((s) => s.appearance);
3252
-
3253
- /** \u4EC5\u8BA2\u9605 primaryColor */
3254
3254
  export const usePrimaryColor = () => useThemeStore((s) => s.primaryColor);`;
3255
3255
  var GLOBAL_RESET_CODE = `
3256
3256
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Global Style \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3257
- // \u53C2\u8003 lobe-ui GlobalStyle\uFF1A\u4F7F\u7528 theme tokens \u5B9E\u73B0\u54CD\u5E94\u5F0F\u5168\u5C40\u6837\u5F0F
3258
3257
 
3259
3258
  const GlobalReset = createGlobalStyle(({ theme }) => css\`
3260
3259
  :root {
@@ -3315,8 +3314,6 @@ const GlobalReset = createGlobalStyle(({ theme }) => css\`
3315
3314
  \`);`;
3316
3315
  var CSS_VAR_SYNC_CODE = `
3317
3316
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CSS Variable Sync \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3318
- // \u5C06 antd-style \u6CE8\u5165\u7684 css-var-* class \u540C\u6B65\u5230 <html>\uFF0C
3319
- // \u4F7F\u5168\u5C40 CSS / Tailwind \u4E5F\u80FD\u6D88\u8D39 antd CSS \u53D8\u91CF
3320
3317
 
3321
3318
  const CSS_VAR_PREFIX = "css-var-";
3322
3319
 
@@ -3382,7 +3379,6 @@ function useAppearanceSync(appearance: ThemeAppearance) {
3382
3379
  }`;
3383
3380
  var EXTERNAL_THEME_CODE = `
3384
3381
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 External Theme Injection \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3385
- // \u5FAE\u524D\u7AEF\u573A\u666F\uFF1A\u76D1\u542C\u4E3B\u5E94\u7528\u4E0B\u53D1\u7684\u4E3B\u9898\u53D8\u66F4
3386
3382
 
3387
3383
  function useExternalTheme() {
3388
3384
  useEffect(() => {
@@ -3412,52 +3408,41 @@ function buildWrapperCode(opts) {
3412
3408
  return `
3413
3409
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ThemeWrapper \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3414
3410
 
3411
+ const RUNTIME_PREFIX_CLS = typeof process !== "undefined"
3412
+ && process.env?.YWKF_PREFIX_CLS
3413
+ || "${prefixCls}";
3414
+
3415
3415
  interface ThemeWrapperProps {
3416
3416
  children: ReactNode;
3417
3417
  }
3418
3418
 
3419
- /**
3420
- * \u4E3B\u9898\u5305\u88F9\u7EC4\u4EF6
3421
- *
3422
- * \u7531 themePlugin \u81EA\u52A8\u6CE8\u5165\u5230\u5E94\u7528\u542F\u52A8\u5C42\uFF0C\u4ECE useThemeStore \u8BFB\u53D6\u4E3B\u9898\u72B6\u6001\u3002
3423
- * \u4E1A\u52A1\u4FA7\u901A\u8FC7 useThemeStore / useTheme \u6D88\u8D39\u6216\u4FEE\u6539\u4E3B\u9898\u3002
3424
- */
3425
3419
  export function ThemeWrapper({ children }: ThemeWrapperProps) {${refLine}
3426
- const { appearance, primaryColor } = useThemeStore(
3427
- (s) => ({ appearance: s.appearance, primaryColor: s.primaryColor }),
3420
+ const { appearance, primaryColor, neutralColor } = useThemeStore(
3421
+ (s) => ({ appearance: s.appearance, primaryColor: s.primaryColor, neutralColor: s.neutralColor }),
3428
3422
  shallow,
3429
3423
  );${cssVarSyncLine}${appearanceSyncLine}${externalThemeLine}
3430
3424
 
3425
+ const resolvedAppearance = useMemo(() => {
3426
+ if (appearance !== "auto") return appearance;
3427
+ if (typeof window === "undefined") return "light";
3428
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
3429
+ }, [appearance]);
3430
+
3431
3431
  const theme = useCallback<GetAntdTheme>(
3432
- () => ({${cssVar ? "\n cssVar: true," : ""}
3433
- token: {
3434
- colorPrimary: primaryColor,
3435
- // lobe-ui base tokens
3436
- borderRadius: 8,
3437
- borderRadiusLG: 12,
3438
- borderRadiusSM: 6,
3439
- borderRadiusXS: 4,
3440
- controlHeight: 36,
3441
- fontFamily: [
3442
- '"HarmonyOS Sans", "Segoe UI", "SF Pro Display"',
3443
- '-apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial',
3444
- '"PingFang SC", "Hiragino Sans GB", "Microsoft Yahei", "Noto Sans SC", sans-serif',
3445
- '"Segoe UI Emoji", "Noto Color Emoji"',
3446
- ].join(", "),
3447
- fontFamilyCode: [
3448
- 'Hack, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas',
3449
- '"PingFang SC", "Noto Sans SC", monospace',
3450
- ].join(", "),
3451
- },
3432
+ (ap) => createThemeConfig({
3433
+ appearance: ap as "light" | "dark",
3434
+ primaryColor,
3435
+ neutralColor,
3452
3436
  }),
3453
- [primaryColor],
3437
+ [primaryColor, neutralColor],
3454
3438
  );
3455
3439
 
3456
3440
  return (
3457
3441
  <AntdThemeProvider
3458
- prefixCls="${prefixCls}"
3442
+ prefixCls={RUNTIME_PREFIX_CLS}
3443
+ appearance={resolvedAppearance}
3459
3444
  themeMode={appearance}
3460
- theme={theme}
3445
+ theme={theme}${cssVar ? "\n customToken={{ cssVar: true }}" : ""}
3461
3446
  >
3462
3447
  ${globalReset ? "<GlobalReset />" : ""}
3463
3448
  ${childrenSlot}