@qw-ui/tokens 0.3.0-next.5 → 0.3.0-next.6

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.
@@ -183,18 +183,44 @@ export declare const WHITE_ALPHA: ReadonlyArray<readonly [string, number]>;
183
183
  export declare function buildAlphaScaleRecipes(): ReferenceRecipe[];
184
184
  /** 4. 间距刻度 = spacing.step × N (N=1..8)。 */
185
185
  export declare function buildSpacingRecipes(): ReferenceRecipe[];
186
- /** 圆角档位系数(sm/lg 从 base 派生;默认 base=8px → 4/8/14)。 */
186
+ /** 圆角档位系数(sm/lg/xl 从 base 派生;默认 base=8px → 4/8/14/16)。 */
187
187
  export declare const RADIUS_FACTORS: {
188
188
  readonly sm: 0.5;
189
189
  readonly md: 1;
190
190
  readonly lg: 1.75;
191
+ readonly xl: 2;
191
192
  };
192
- /** 5. 圆角刻度:sm/md/lg 由 radius.base 按系数派生,full 直通独立裁切基准。 */
193
+ /** 5. 圆角刻度:sm/md/lg/xl 由 radius.base 按系数派生,full 直通独立裁切基准。xl=2×base 对齐治理稿 Radius v2 的 T2 double。 */
193
194
  export declare function buildRadiusRecipes(): ReferenceRecipe[];
194
195
  /** 6. 控件/图标尺寸:md = base 直通,sm/lg = base ∓ spacing.step × n(控件 ×2、图标 ×1)。 */
195
196
  export declare function buildControlIconSizeRecipes(): ReferenceRecipe[];
196
- /** 7. 描边宽度 —— 直通引用。 */
197
- export declare function buildBorderWidthRecipes(): ReferenceRecipe[];
197
+ /** 描边宽度梯度系数(Figma Stroke v1:Half/Base/Double/Triple = 0.5/1/2/3)。 */
198
+ export declare const STROKE_WIDTH_FACTORS: {
199
+ readonly half: 0.5;
200
+ readonly double: 2;
201
+ readonly triple: 3;
202
+ };
203
+ /** 7. 描边宽度(Figma Stroke v1):base 直通 Seed,half/double/triple 按系数派生。 */
204
+ export declare function buildStrokeWidthRecipes(): ReferenceRecipe[];
205
+ /** 六档动作控件高度(Figma Action Control v1):现有公开尺寸契约,不能由单一 T1 Base 可靠派生,直接定义在 T2(T1 不设 Control Size)。 */
206
+ export declare const ACTION_CONTROL_HEIGHTS: {
207
+ readonly "2xs": 24;
208
+ readonly xs: 28;
209
+ readonly sm: 32;
210
+ readonly md: 36;
211
+ readonly lg: 42;
212
+ readonly xl: 50;
213
+ };
214
+ /** 7b. 动作控件尺寸:六档高度 + 2XS 图标特例(Square 复用同档 Height,不另设 token)。 */
215
+ export declare function buildActionControlRecipes(): ReferenceRecipe[];
216
+ /** Avatar 三档直径(Figma 头像 · Avatar S/M/L = 40/50/58)。 */
217
+ export declare const AVATAR_DIAMETERS: {
218
+ readonly sm: 40;
219
+ readonly md: 50;
220
+ readonly lg: 58;
221
+ };
222
+ /** 7c. 展示类专用尺寸:Avatar 直径(Icon Size 规范要求 Avatar 直径使用自己的语义,禁止借用 Icon/Control 刻度)。 */
223
+ export declare function buildAvatarDiameterRecipes(): ReferenceRecipe[];
198
224
  /** 8. 行高(typography 类目):normal 直通 Seed,tight/relaxed = base ∓ 0.25。 */
199
225
  export declare function buildLineHeightRecipes(): ReferenceRecipe[];
200
226
  /** 9. 禁用态不透明度 —— 直通引用。 */
@@ -202,7 +228,7 @@ export declare function buildOpacityRecipes(): ReferenceRecipe[];
202
228
  /** 10. 层级刻度 = zIndex.step × N (N=1..4);角色分配交给 Semantic 层。 */
203
229
  export declare function buildZIndexRecipes(): ReferenceRecipe[];
204
230
  export declare const FONT_FAMILY_KEYS: readonly ["text", "number", "code", "textMacLatin", "textMacZh", "textMacJa", "textWindowsLatin", "textWindowsZh", "textWindowsJa"];
205
- /** 字号档位倍数(沿用既定视觉:14px 基准 → 12/16/20/24)。 */
231
+ /** 字号档位倍数(沿用既定视觉:14px 基准 → 11/12/16/20/24;xs=11 对齐治理稿 T2 Font Size 2XS)。 */
206
232
  export declare const FONT_SIZE_FACTORS: Record<string, number>;
207
233
  /** 11. 排版原子:字体族来自平台 Seed;字重是机械标准常量;字号按既定倍数派生。 */
208
234
  export declare function buildTypographyRecipes(): ReferenceRecipe[];
@@ -14,6 +14,16 @@ export type SemanticMode = "light" | "dark";
14
14
  export declare const RADIUS_ROLES: Record<string, string>;
15
15
  export declare const CONTROL_HEIGHT_ROLES: Record<string, string>;
16
16
  export declare const ICON_SIZE_ROLES: Record<string, string>;
17
+ export declare const ACTION_CONTROL_HEIGHT_ROLES: Record<string, string>;
18
+ export declare const ACTION_CONTROL_PADDING_INLINE_ROLES: Record<string, string>;
19
+ export declare const ACTION_CONTROL_ICON_ROLES: Record<string, string>;
20
+ export declare const ACTION_CONTROL_GAP_ROLES: Record<string, string>;
21
+ export declare const BORDER_WIDTH_ROLES: Record<string, string>;
22
+ export declare const DIVIDER_WIDTH_ROLES: Record<string, string>;
23
+ export declare const FOCUS_RING_ROLES: Record<string, string>;
24
+ export declare const INDICATOR_ROLES: Record<string, string>;
25
+ /** 展示类专用尺寸:Avatar 直径三档(Figma 头像 S/M/L)。 */
26
+ export declare const AVATAR_DIAMETER_ROLES: Record<string, string>;
17
27
  export declare const INSET_STACK_ROLES: Record<string, string>;
18
28
  export declare const Z_INDEX_ROLES: Record<string, string>;
19
29
  export declare const MOTION_DURATION_ROLES: Record<string, string>;
package/dist/index.d.ts CHANGED
@@ -12,5 +12,3 @@ export type { LiveCssOptions } from "./derive/live-css.js";
12
12
  export { buildFigmaColorSnapshot } from "./figma/color-snapshot.js";
13
13
  export { validateFigmaColorTokens, assertFigmaColorTokens, figmaT3RolePaths, } from "./figma/color-contract.js";
14
14
  export type { FigmaColorTokenValidationResult } from "./figma/color-contract.js";
15
- export { compatRegistrySchema, compatPathToCssVar, buildCompatFromRegistry, formatCompatTypes, } from "./compat/index.js";
16
- export type { CompatEntry, CompatRegistry, CompatBuild } from "./compat/index.js";
package/dist/index.js CHANGED
@@ -1510,13 +1510,14 @@ function buildSpacingRecipes() {
1510
1510
  }));
1511
1511
  return out;
1512
1512
  }
1513
- /** 圆角档位系数(sm/lg 从 base 派生;默认 base=8px → 4/8/14)。 */
1513
+ /** 圆角档位系数(sm/lg/xl 从 base 派生;默认 base=8px → 4/8/14/16)。 */
1514
1514
  const RADIUS_FACTORS = {
1515
1515
  sm: .5,
1516
1516
  md: 1,
1517
- lg: 1.75
1517
+ lg: 1.75,
1518
+ xl: 2
1518
1519
  };
1519
- /** 5. 圆角刻度:sm/md/lg 由 radius.base 按系数派生,full 直通独立裁切基准。 */
1520
+ /** 5. 圆角刻度:sm/md/lg/xl 由 radius.base 按系数派生,full 直通独立裁切基准。xl=2×base 对齐治理稿 Radius v2 的 T2 double。 */
1520
1521
  function buildRadiusRecipes() {
1521
1522
  return [
1522
1523
  ref([
@@ -1545,6 +1546,15 @@ function buildRadiusRecipes() {
1545
1546
  seedRef: "size.radius.base",
1546
1547
  factor: RADIUS_FACTORS.lg
1547
1548
  }),
1549
+ ref([
1550
+ "size",
1551
+ "radius",
1552
+ "xl"
1553
+ ], {
1554
+ kind: "scale",
1555
+ seedRef: "size.radius.base",
1556
+ factor: RADIUS_FACTORS.xl
1557
+ }),
1548
1558
  ref([
1549
1559
  "size",
1550
1560
  "radius",
@@ -1617,16 +1627,108 @@ function buildControlIconSizeRecipes() {
1617
1627
  })
1618
1628
  ];
1619
1629
  }
1620
- /** 7. 描边宽度 —— 直通引用。 */
1621
- function buildBorderWidthRecipes() {
1622
- return [ref([
1630
+ /** 描边宽度梯度系数(Figma Stroke v1:Half/Base/Double/Triple = 0.5/1/2/3)。 */
1631
+ const STROKE_WIDTH_FACTORS = {
1632
+ half: .5,
1633
+ double: 2,
1634
+ triple: 3
1635
+ };
1636
+ /** 7. 描边宽度(Figma Stroke v1):base 直通 Seed,half/double/triple 按系数派生。 */
1637
+ function buildStrokeWidthRecipes() {
1638
+ const seedRef = "size.borderWidth.hairline";
1639
+ return [
1640
+ ref([
1641
+ "size",
1642
+ "strokeWidth",
1643
+ "half"
1644
+ ], {
1645
+ kind: "scale",
1646
+ seedRef,
1647
+ factor: STROKE_WIDTH_FACTORS.half
1648
+ }),
1649
+ ref([
1650
+ "size",
1651
+ "strokeWidth",
1652
+ "base"
1653
+ ], {
1654
+ kind: "alias",
1655
+ seedRef
1656
+ }),
1657
+ ref([
1658
+ "size",
1659
+ "strokeWidth",
1660
+ "double"
1661
+ ], {
1662
+ kind: "scale",
1663
+ seedRef,
1664
+ factor: STROKE_WIDTH_FACTORS.double
1665
+ }),
1666
+ ref([
1667
+ "size",
1668
+ "strokeWidth",
1669
+ "triple"
1670
+ ], {
1671
+ kind: "scale",
1672
+ seedRef,
1673
+ factor: STROKE_WIDTH_FACTORS.triple
1674
+ })
1675
+ ];
1676
+ }
1677
+ /** 六档动作控件高度(Figma Action Control v1):现有公开尺寸契约,不能由单一 T1 Base 可靠派生,直接定义在 T2(T1 不设 Control Size)。 */
1678
+ const ACTION_CONTROL_HEIGHTS = {
1679
+ "2xs": 24,
1680
+ xs: 28,
1681
+ sm: 32,
1682
+ md: 36,
1683
+ lg: 42,
1684
+ xl: 50
1685
+ };
1686
+ /** 7b. 动作控件尺寸:六档高度 + 2XS 图标特例(Square 复用同档 Height,不另设 token)。 */
1687
+ function buildActionControlRecipes() {
1688
+ const out = [];
1689
+ for (const [step, value] of Object.entries(ACTION_CONTROL_HEIGHTS)) out.push(ref([
1623
1690
  "size",
1624
- "borderWidth",
1625
- "hairline"
1691
+ "actionControlHeight",
1692
+ step
1626
1693
  ], {
1627
- kind: "alias",
1628
- seedRef: "size.borderWidth.hairline"
1629
- })];
1694
+ kind: "literal",
1695
+ value: `${value}px`
1696
+ }, {
1697
+ source: "Figma 千问三方——Token 改造 · Foundation/Action Control Standard v1",
1698
+ rationale: "六档高度 24/28/32/36/42/50 是现有公开尺寸契约,治理稿将其直接定义在 T2,T1 不设置 Control Size。"
1699
+ }));
1700
+ out.push(ref([
1701
+ "size",
1702
+ "actionControlIcon",
1703
+ "2xs"
1704
+ ], {
1705
+ kind: "literal",
1706
+ value: "14px"
1707
+ }, {
1708
+ source: "Figma 千问三方——Token 改造 · Foundation/Action Control Standard v1",
1709
+ rationale: "2XS 图标 14px 是治理稿已标记的组件特例(不扩充全局 Icon Scale);视觉验证通过后优先归一化为 Icon Size/Small。"
1710
+ }));
1711
+ return out;
1712
+ }
1713
+ /** Avatar 三档直径(Figma 头像 · Avatar S/M/L = 40/50/58)。 */
1714
+ const AVATAR_DIAMETERS = {
1715
+ sm: 40,
1716
+ md: 50,
1717
+ lg: 58
1718
+ };
1719
+ /** 7c. 展示类专用尺寸:Avatar 直径(Icon Size 规范要求 Avatar 直径使用自己的语义,禁止借用 Icon/Control 刻度)。 */
1720
+ function buildAvatarDiameterRecipes() {
1721
+ return Object.entries(AVATAR_DIAMETERS).map(([step, value]) => ref([
1722
+ "size",
1723
+ "avatarDiameter",
1724
+ step
1725
+ ], {
1726
+ kind: "literal",
1727
+ value: `${value}px`
1728
+ }, {
1729
+ source: "Figma 千问三方——Token 改造 · 头像 · Avatar(S/M/L)",
1730
+ rationale: "Avatar 直径 40/50/58 是展示类专用尺寸契约;Icon Size 规范明确 Avatar 直径必须使用各自语义,不由 T1 派生。"
1731
+ }));
1630
1732
  }
1631
1733
  /** 8. 行高(typography 类目):normal 直通 Seed,tight/relaxed = base ∓ 0.25。 */
1632
1734
  function buildLineHeightRecipes() {
@@ -1698,8 +1800,9 @@ const FONT_FAMILY_KEYS = [
1698
1800
  "textWindowsZh",
1699
1801
  "textWindowsJa"
1700
1802
  ];
1701
- /** 字号档位倍数(沿用既定视觉:14px 基准 → 12/16/20/24)。 */
1803
+ /** 字号档位倍数(沿用既定视觉:14px 基准 → 11/12/16/20/24;xs=11 对齐治理稿 T2 Font Size 2XS)。 */
1702
1804
  const FONT_SIZE_FACTORS = {
1805
+ xs: .786,
1703
1806
  sm: .857,
1704
1807
  lg: 1.143,
1705
1808
  xl: 1.429,
@@ -1828,7 +1931,9 @@ function allReferenceRecipes() {
1828
1931
  ...buildSpacingRecipes(),
1829
1932
  ...buildRadiusRecipes(),
1830
1933
  ...buildControlIconSizeRecipes(),
1831
- ...buildBorderWidthRecipes(),
1934
+ ...buildStrokeWidthRecipes(),
1935
+ ...buildActionControlRecipes(),
1936
+ ...buildAvatarDiameterRecipes(),
1832
1937
  ...buildLineHeightRecipes(),
1833
1938
  ...buildOpacityRecipes(),
1834
1939
  ...buildZIndexRecipes(),
@@ -1863,8 +1968,10 @@ function semVar(path) {
1863
1968
  return toVar("sem", path);
1864
1969
  }
1865
1970
  const RADIUS_ROLES = {
1971
+ sm: "size.radius.sm",
1866
1972
  control: "size.radius.md",
1867
1973
  card: "size.radius.lg",
1974
+ xl: "size.radius.xl",
1868
1975
  pill: "size.radius.full",
1869
1976
  full: "size.radius.full"
1870
1977
  };
@@ -1878,6 +1985,57 @@ const ICON_SIZE_ROLES = {
1878
1985
  md: "size.iconSize.md",
1879
1986
  lg: "size.iconSize.lg"
1880
1987
  };
1988
+ const ACTION_CONTROL_HEIGHT_ROLES = {
1989
+ "2xs": "size.actionControlHeight.2xs",
1990
+ xs: "size.actionControlHeight.xs",
1991
+ sm: "size.actionControlHeight.sm",
1992
+ md: "size.actionControlHeight.md",
1993
+ lg: "size.actionControlHeight.lg",
1994
+ xl: "size.actionControlHeight.xl"
1995
+ };
1996
+ const ACTION_CONTROL_PADDING_INLINE_ROLES = {
1997
+ "2xs": "size.spacing.2",
1998
+ xs: "size.spacing.2",
1999
+ sm: "size.spacing.4",
2000
+ md: "size.spacing.4",
2001
+ lg: "size.spacing.5",
2002
+ xl: "size.spacing.8"
2003
+ };
2004
+ const ACTION_CONTROL_ICON_ROLES = {
2005
+ "2xs": "size.actionControlIcon.2xs",
2006
+ xs: "size.iconSize.sm",
2007
+ sm: "size.iconSize.sm",
2008
+ md: "size.iconSize.sm",
2009
+ lg: "size.iconSize.sm",
2010
+ xl: "size.iconSize.md"
2011
+ };
2012
+ const ACTION_CONTROL_GAP_ROLES = {
2013
+ "2xs": "size.spacing.1",
2014
+ xs: "size.spacing.1",
2015
+ sm: "size.spacing.2",
2016
+ md: "size.spacing.2",
2017
+ lg: "size.spacing.2",
2018
+ xl: "size.spacing.2"
2019
+ };
2020
+ const BORDER_WIDTH_ROLES = {
2021
+ default: "size.strokeWidth.base",
2022
+ strong: "size.strokeWidth.double"
2023
+ };
2024
+ const DIVIDER_WIDTH_ROLES = {
2025
+ thin: "size.strokeWidth.half",
2026
+ default: "size.strokeWidth.base"
2027
+ };
2028
+ const FOCUS_RING_ROLES = {
2029
+ width: "size.strokeWidth.double",
2030
+ offset: "size.strokeWidth.double"
2031
+ };
2032
+ const INDICATOR_ROLES = { loading: "size.strokeWidth.double" };
2033
+ /** 展示类专用尺寸:Avatar 直径三档(Figma 头像 S/M/L)。 */
2034
+ const AVATAR_DIAMETER_ROLES = {
2035
+ sm: "size.avatarDiameter.sm",
2036
+ md: "size.avatarDiameter.md",
2037
+ lg: "size.avatarDiameter.lg"
2038
+ };
1881
2039
  const INSET_STACK_ROLES = {
1882
2040
  sm: "size.spacing.2",
1883
2041
  md: "size.spacing.4",
@@ -1945,6 +2103,22 @@ const TYPOGRAPHY_ROLES = {
1945
2103
  lineHeightRef: "typography.lineHeight.normal",
1946
2104
  letterSpacingRef: T_LETTER
1947
2105
  },
2106
+ /** 大正文(治理稿 T3 字段「大正文 16px · T2 M」):行高沿用 canonical 比例引擎。 */
2107
+ bodyLg: {
2108
+ fontFamilyRef: "typography.fontFamily.text",
2109
+ fontSizeRef: "typography.fontSize.lg",
2110
+ fontWeightRef: "typography.fontWeight.regular",
2111
+ lineHeightRef: "typography.lineHeight.normal",
2112
+ letterSpacingRef: T_LETTER
2113
+ },
2114
+ /** 小标签(治理稿 Text/Label/Small = 11/500/16):字号取 T2 xs=11px。 */
2115
+ labelSm: {
2116
+ fontFamilyRef: "typography.fontFamily.text",
2117
+ fontSizeRef: "typography.fontSize.xs",
2118
+ fontWeightRef: "typography.fontWeight.medium",
2119
+ lineHeightRef: "typography.lineHeight.normal",
2120
+ letterSpacingRef: T_LETTER
2121
+ },
1948
2122
  code: {
1949
2123
  fontFamilyRef: "typography.fontFamily.code",
1950
2124
  fontSizeRef: "typography.fontSize.sm",
@@ -1996,6 +2170,51 @@ function semanticRoleEntries() {
1996
2170
  "iconSize",
1997
2171
  role
1998
2172
  ], refPath);
2173
+ for (const [role, refPath] of Object.entries(ACTION_CONTROL_HEIGHT_ROLES)) structural([
2174
+ "size",
2175
+ "actionControlHeight",
2176
+ role
2177
+ ], refPath);
2178
+ for (const [role, refPath] of Object.entries(ACTION_CONTROL_PADDING_INLINE_ROLES)) structural([
2179
+ "size",
2180
+ "actionControlPaddingInline",
2181
+ role
2182
+ ], refPath);
2183
+ for (const [role, refPath] of Object.entries(ACTION_CONTROL_ICON_ROLES)) structural([
2184
+ "size",
2185
+ "actionControlIcon",
2186
+ role
2187
+ ], refPath);
2188
+ for (const [role, refPath] of Object.entries(ACTION_CONTROL_GAP_ROLES)) structural([
2189
+ "size",
2190
+ "actionControlGap",
2191
+ role
2192
+ ], refPath);
2193
+ for (const [role, refPath] of Object.entries(BORDER_WIDTH_ROLES)) structural([
2194
+ "size",
2195
+ "borderWidth",
2196
+ role
2197
+ ], refPath);
2198
+ for (const [role, refPath] of Object.entries(DIVIDER_WIDTH_ROLES)) structural([
2199
+ "size",
2200
+ "dividerWidth",
2201
+ role
2202
+ ], refPath);
2203
+ for (const [role, refPath] of Object.entries(FOCUS_RING_ROLES)) structural([
2204
+ "size",
2205
+ "focusRing",
2206
+ role
2207
+ ], refPath);
2208
+ for (const [role, refPath] of Object.entries(INDICATOR_ROLES)) structural([
2209
+ "size",
2210
+ "indicator",
2211
+ role
2212
+ ], refPath);
2213
+ for (const [role, refPath] of Object.entries(AVATAR_DIAMETER_ROLES)) structural([
2214
+ "size",
2215
+ "avatarDiameter",
2216
+ role
2217
+ ], refPath);
1999
2218
  for (const [role, refPath] of Object.entries(INSET_STACK_ROLES)) {
2000
2219
  structural([
2001
2220
  "size",
@@ -2630,212 +2849,6 @@ function assertFigmaColorTokens(doc) {
2630
2849
  if (!result.ok) throw new Error(`Invalid Figma Color tokens:\n${result.errors.map((error) => `- ${error}`).join("\n")}`);
2631
2850
  }
2632
2851
  //#endregion
2633
- //#region src/compat/schema.ts
2634
- /** DTCG 兼容的颜色字面量:hex、hex/NN% 透明度后缀,或结构化 srgb。 */
2635
- const legacyHexColor = z.string().regex(/^#[0-9A-Fa-f]{6}(\/\d{1,3}%)?$/, "期望 #RRGGBB 或 #RRGGBB/NN%");
2636
- const structuredColor = z.object({
2637
- colorSpace: z.literal("srgb"),
2638
- components: z.tuple([
2639
- z.number(),
2640
- z.number(),
2641
- z.number()
2642
- ]),
2643
- alpha: z.number().min(0).max(1)
2644
- });
2645
- const dimensionValue = z.object({
2646
- value: z.number(),
2647
- unit: z.enum([
2648
- "px",
2649
- "rem",
2650
- "em",
2651
- "%"
2652
- ])
2653
- });
2654
- const modePair = z.object({
2655
- light: z.union([
2656
- legacyHexColor,
2657
- structuredColor,
2658
- z.string()
2659
- ]),
2660
- dark: z.union([
2661
- legacyHexColor,
2662
- structuredColor,
2663
- z.string()
2664
- ])
2665
- });
2666
- const compatStatusSchema = z.enum([
2667
- "active",
2668
- "aliased",
2669
- "deprecated"
2670
- ]);
2671
- const compatEntrySchema = z.object({
2672
- path: z.string().regex(/^[a-z][a-z0-9-]*\.[a-z][a-z0-9.-]*$/, "path 格式:<component>.<category>.<name>,如 button.color.bg-soft-brand"),
2673
- type: z.enum([
2674
- "color",
2675
- "dimension",
2676
- "typography",
2677
- "motion"
2678
- ]),
2679
- value: z.union([
2680
- modePair,
2681
- dimensionValue,
2682
- z.object({ aliasOf: z.string().min(1) })
2683
- ]),
2684
- source: z.object({
2685
- figma: z.string().url(),
2686
- nodeId: z.string().min(1),
2687
- legacyName: z.string().nullable()
2688
- }),
2689
- introducedBy: z.string().min(1),
2690
- reason: z.string().min(1),
2691
- owner: z.string().min(1),
2692
- targetSemanticRole: z.string().nullable(),
2693
- status: compatStatusSchema,
2694
- reviewAfter: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
2695
- migrationIssue: z.string().nullable()
2696
- }).superRefine((entry, ctx) => {
2697
- if (entry.status === "aliased") {
2698
- if (!("aliasOf" in entry.value)) ctx.addIssue({
2699
- code: "custom",
2700
- message: "status=aliased 时 value 必须为 { aliasOf }",
2701
- path: ["value"]
2702
- });
2703
- if (!entry.targetSemanticRole) ctx.addIssue({
2704
- code: "custom",
2705
- message: "status=aliased 时 targetSemanticRole 必填",
2706
- path: ["targetSemanticRole"]
2707
- });
2708
- }
2709
- if (entry.status === "active" && "aliasOf" in entry.value) ctx.addIssue({
2710
- code: "custom",
2711
- message: "status=active 时不得使用 aliasOf",
2712
- path: ["value"]
2713
- });
2714
- });
2715
- const compatRegistrySchema = z.object({
2716
- $description: z.string().optional(),
2717
- version: z.literal(1),
2718
- graceDays: z.number().int().positive().default(90),
2719
- entries: z.array(compatEntrySchema).min(1)
2720
- });
2721
- /** path → CSS 变量名:`button.color.bg-soft-brand` → `--qw-compat-button-color-bg-soft-brand` */
2722
- function compatPathToCssVar(path) {
2723
- return `--qw-compat-${path.replace(/\./g, "-")}`;
2724
- }
2725
- /** path → component slug(第一段) */
2726
- function compatComponentOf(path) {
2727
- return path.split(".")[0];
2728
- }
2729
- /** path → helper suffix(component 之后的段,用 `-` 连接) */
2730
- function compatSuffixOf(path) {
2731
- return path.split(".").slice(1).join("-");
2732
- }
2733
- //#endregion
2734
- //#region src/compat/color.ts
2735
- /**
2736
- * 将 legacy hex(含 /NN% 透明度后缀)或 DTCG srgb 结构转为 CSS 颜色字符串。
2737
- */
2738
- function compatColorToCss(input) {
2739
- if (typeof input === "string") {
2740
- const m = /^#([0-9A-Fa-f]{6})(?:\/(\d{1,3})%)?$/.exec(input);
2741
- if (!m) throw new Error(`[qw-compat] 无法解析颜色: ${input}`);
2742
- const n = Number.parseInt(m[1], 16);
2743
- const r = n >> 16 & 255;
2744
- const g = n >> 8 & 255;
2745
- const b = n & 255;
2746
- const alpha = m[2] != null ? Number(m[2]) / 100 : 1;
2747
- if (alpha >= 1) return `#${m[1].toUpperCase()}`;
2748
- return `rgba(${r}, ${g}, ${b}, ${roundAlpha(alpha)})`;
2749
- }
2750
- const [r, g, b] = input.components.map((c) => Math.round(c * 255));
2751
- const alpha = input.alpha;
2752
- if (alpha >= 1) return `#${[
2753
- r,
2754
- g,
2755
- b
2756
- ].map((x) => x.toString(16).padStart(2, "0")).join("")}`;
2757
- return `rgba(${r}, ${g}, ${b}, ${roundAlpha(alpha)})`;
2758
- }
2759
- function roundAlpha(a) {
2760
- return Math.round(a * 1e3) / 1e3;
2761
- }
2762
- //#endregion
2763
- //#region src/compat/build.ts
2764
- function dimensionToCss(value) {
2765
- return `${value.value}${value.unit}`;
2766
- }
2767
- function resolveEntryValue(entry, mode, semCssVar) {
2768
- const v = entry.value;
2769
- if ("aliasOf" in v) return `var(${semCssVar(v.aliasOf)})`;
2770
- if ("light" in v && "dark" in v) {
2771
- const raw = v[mode];
2772
- if (entry.type === "color") return compatColorToCss(raw);
2773
- return String(raw);
2774
- }
2775
- if ("value" in v && "unit" in v) return dimensionToCss(v);
2776
- throw new Error(`[qw-compat] 条目 ${entry.path} 的 value 形状无法解析`);
2777
- }
2778
- /** semantic role 点分路径 → --qw-sem-* CSS 变量 */
2779
- function semRoleToCssVar(role) {
2780
- const parts = role.split(".");
2781
- return `--qw-sem-${parts[0]}-${parts.slice(1).join("-")}`;
2782
- }
2783
- function buildCompatFromRegistry(registry) {
2784
- const light = {};
2785
- const dark = {};
2786
- const paths = {};
2787
- const byComponent = {};
2788
- for (const entry of registry.entries) {
2789
- const cssVar = compatPathToCssVar(entry.path);
2790
- paths[entry.path] = cssVar;
2791
- const component = compatComponentOf(entry.path);
2792
- const suffix = compatSuffixOf(entry.path);
2793
- if (!byComponent[component]) byComponent[component] = [];
2794
- byComponent[component].push(suffix);
2795
- const resolve = (mode) => resolveEntryValue(entry, mode, semRoleToCssVar);
2796
- if ("light" in entry.value && "dark" in entry.value) {
2797
- light[cssVar] = resolve("light");
2798
- const darkVal = resolve("dark");
2799
- if (darkVal !== light[cssVar]) dark[cssVar] = darkVal;
2800
- } else light[cssVar] = resolve("light");
2801
- }
2802
- return {
2803
- light,
2804
- dark,
2805
- paths,
2806
- byComponent,
2807
- entries: registry.entries,
2808
- graceDays: registry.graceDays
2809
- };
2810
- }
2811
- function componentSuffixTypeName(component) {
2812
- return `Compat${component.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("")}Suffix`;
2813
- }
2814
- function componentSuffixConstName(component) {
2815
- return `compat${component.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("")}Suffixes`;
2816
- }
2817
- /** 生成 compat token-paths TypeScript 片段(并入 tokens.ts) */
2818
- function formatCompatTypes(build) {
2819
- const components = Object.keys(build.byComponent).sort();
2820
- const lines = ["export const compatComponents = " + JSON.stringify(components) + " as const;", "export type CompatComponent = (typeof compatComponents)[number];"];
2821
- for (const c of components) {
2822
- const suffixes = [...build.byComponent[c]].sort();
2823
- const constName = componentSuffixConstName(c);
2824
- const typeName = componentSuffixTypeName(c);
2825
- lines.push(`export const ${constName} = ${JSON.stringify(suffixes)} as const;`);
2826
- lines.push(`export type ${typeName} = (typeof ${constName})[number];`);
2827
- }
2828
- if (components.length === 1) {
2829
- const c = components[0];
2830
- lines.push(`export type CompatSuffix<C extends CompatComponent> = C extends ${JSON.stringify(c)} ? ${componentSuffixTypeName(c)} : never;`);
2831
- } else if (components.length > 1) {
2832
- lines.push("export type CompatSuffix<C extends CompatComponent> =");
2833
- for (const c of components) lines.push(` C extends ${JSON.stringify(c)} ? ${componentSuffixTypeName(c)} :`);
2834
- lines.push(" never;");
2835
- }
2836
- return lines.join("\n");
2837
- }
2838
- //#endregion
2839
- export { COLOR_ROLES, FIGMA_COLOR_COLLECTION, FIGMA_COLOR_PREFIX, FIGMA_T1_SEED_HEX, FIGMA_T2_SOLID_SCALE, FIGMA_T2_STEP_ALPHA, FIGMA_T3_COLOR_ROLES, L_TARGETS, RAMP_COLORS, SHADOW_COMPOSITE_ROLES, STEPS, SeedSchema, T1_COLOR_KEYS, T2_ALPHA_KEYS, T2_ALPHA_STEPS, T2_OKLCH_STEPS, T2_PURE_SEEDS, T2_PURE_STEP, TYPOGRAPHY_ROLES, allReferenceRecipes, assertFigmaColorTokens, buildCompatFromRegistry, buildFigmaColorSnapshot, buildLiveCss, buildReference, buildSemanticColor, buildSemanticStructural, compatPathToCssVar, compatRegistrySchema, contrastRatio, defaultSeed, derivationToCssExpr, derive, evaluateDerivation, figmaT3RolePaths, formatCompatTypes, formatDerivation, hexToSeedColor, ramp, seedColorToCss, seedColorToHex, seedCssVars, seedRefsOf, seedValueAt, semanticRoleEntries, sourceKindOf, toVar, validateFigmaColorTokens, validateSeed };
2852
+ export { COLOR_ROLES, FIGMA_COLOR_COLLECTION, FIGMA_COLOR_PREFIX, FIGMA_T1_SEED_HEX, FIGMA_T2_SOLID_SCALE, FIGMA_T2_STEP_ALPHA, FIGMA_T3_COLOR_ROLES, L_TARGETS, RAMP_COLORS, SHADOW_COMPOSITE_ROLES, STEPS, SeedSchema, T1_COLOR_KEYS, T2_ALPHA_KEYS, T2_ALPHA_STEPS, T2_OKLCH_STEPS, T2_PURE_SEEDS, T2_PURE_STEP, TYPOGRAPHY_ROLES, allReferenceRecipes, assertFigmaColorTokens, buildFigmaColorSnapshot, buildLiveCss, buildReference, buildSemanticColor, buildSemanticStructural, contrastRatio, defaultSeed, derivationToCssExpr, derive, evaluateDerivation, figmaT3RolePaths, formatDerivation, hexToSeedColor, ramp, seedColorToCss, seedColorToHex, seedCssVars, seedRefsOf, seedValueAt, semanticRoleEntries, sourceKindOf, toVar, validateFigmaColorTokens, validateSeed };
2840
2853
 
2841
2854
  //# sourceMappingURL=index.js.map