@qw-ui/core 0.1.0 → 0.2.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/avatar/avatar.d.ts +145 -0
  2. package/dist/avatar/index.d.ts +1 -0
  3. package/dist/avatar/index.js +150 -0
  4. package/dist/avatar/index.js.map +1 -0
  5. package/dist/button/button.d.ts +84 -0
  6. package/dist/button/index.d.ts +1 -0
  7. package/dist/button/index.js +104 -0
  8. package/dist/button/index.js.map +1 -0
  9. package/dist/dialog/dialog.d.ts +59 -0
  10. package/dist/dialog/index.d.ts +1 -56
  11. package/dist/dialog/index.js +31 -30
  12. package/dist/dialog/index.js.map +1 -1
  13. package/dist/divider/divider.d.ts +23 -0
  14. package/dist/divider/index.d.ts +1 -0
  15. package/dist/divider/index.js +18 -0
  16. package/dist/divider/index.js.map +1 -0
  17. package/dist/empty/empty.d.ts +12 -0
  18. package/dist/empty/index.d.ts +1 -0
  19. package/dist/empty/index.js +21 -0
  20. package/dist/empty/index.js.map +1 -0
  21. package/dist/icon/icon.d.ts +11 -0
  22. package/dist/icon/index.d.ts +1 -0
  23. package/dist/icon/index.js +20 -0
  24. package/dist/icon/index.js.map +1 -0
  25. package/dist/image/image.d.ts +88 -0
  26. package/dist/image/index.d.ts +1 -0
  27. package/dist/image/index.js +84 -0
  28. package/dist/image/index.js.map +1 -0
  29. package/dist/index.d.ts +22 -4
  30. package/dist/index.js +12 -50
  31. package/dist/loading/index.d.ts +1 -0
  32. package/dist/loading/index.js +19 -0
  33. package/dist/loading/index.js.map +1 -0
  34. package/dist/loading/loading.d.ts +26 -0
  35. package/dist/search-bar/index.d.ts +1 -0
  36. package/dist/search-bar/index.js +252 -0
  37. package/dist/search-bar/index.js.map +1 -0
  38. package/dist/search-bar/search-bar.d.ts +146 -0
  39. package/dist/skeleton/index.d.ts +1 -0
  40. package/dist/skeleton/index.js +28 -0
  41. package/dist/skeleton/index.js.map +1 -0
  42. package/dist/skeleton/skeleton.d.ts +38 -0
  43. package/dist/tabs/index.d.ts +1 -36
  44. package/dist/tabs/index.js +34 -18
  45. package/dist/tabs/index.js.map +1 -1
  46. package/dist/tabs/tabs.d.ts +61 -0
  47. package/dist/toast/index.d.ts +1 -0
  48. package/dist/toast/index.js +44 -0
  49. package/dist/toast/index.js.map +1 -0
  50. package/dist/toast/toast.d.ts +52 -0
  51. package/dist/top-bar/index.d.ts +1 -0
  52. package/dist/top-bar/index.js +43 -0
  53. package/dist/top-bar/index.js.map +1 -0
  54. package/dist/top-bar/top-bar.d.ts +86 -0
  55. package/dist/visual-manifest.d.ts +142 -0
  56. package/package.json +61 -4
  57. package/dist/index.js.map +0 -1
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Avatar 的跨框架行为契约。
3
+ *
4
+ * Avatar 是无状态的 Prototype A:Core 归一化 props、推导降级模式和徽标状态,
5
+ * 生成 root/image/badge 的 data 属性。React/Vue 适配器只投影内容通道并渲染固定 DOM。
6
+ * 图片加载状态通过 `data-load-status` 属性由 CSS 声明式管理,不参与 Core 状态归一化。
7
+ */
8
+ export declare const AVATAR_SHAPES: readonly ["circle", "square"];
9
+ export declare const AVATAR_SIZES: readonly ["s", "m", "l"];
10
+ export declare const AVATAR_PARTS: readonly ["root", "image", "fallback", "badge"];
11
+ export declare const AVATAR_LOAD_STATUS: readonly ["loading", "loaded", "error"];
12
+ export declare const AVATAR_BADGE_TYPES: readonly ["dot", "number"];
13
+ export declare const BADGE_COUNT_MAX = 99;
14
+ export type AvatarShape = (typeof AVATAR_SHAPES)[number];
15
+ export type AvatarSize = (typeof AVATAR_SIZES)[number];
16
+ export type AvatarPart = (typeof AVATAR_PARTS)[number];
17
+ export type AvatarLoadStatus = (typeof AVATAR_LOAD_STATUS)[number];
18
+ export type BadgeType = (typeof AVATAR_BADGE_TYPES)[number];
19
+ /** 徽标配置(双栈共享标量,内容通道不进入 Core)。 */
20
+ export interface BadgeConfig {
21
+ /** 徽标类型。 */
22
+ type: BadgeType;
23
+ /** 数字徽标的数值。 */
24
+ count?: number;
25
+ /** 徽标无障碍标签。 */
26
+ ariaLabel?: string;
27
+ }
28
+ /** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */
29
+ export interface QwAvatarProps {
30
+ /** 图片源地址。空字符串或 undefined 时不渲染 img,直接进入降级。 */
31
+ src?: string;
32
+ /** 名称,用于提取缩写和 aria-label。 */
33
+ name?: string;
34
+ /** 外形,默认 `circle`。 */
35
+ shape?: AvatarShape;
36
+ /** 尺寸,默认 `m`。 */
37
+ size?: AvatarSize;
38
+ /** 装饰模式(从辅助技术隐藏)。 */
39
+ decorative?: boolean;
40
+ /** 自定义背景色,设置后覆盖所有展示形式的默认背景色。 */
41
+ bg?: string;
42
+ /** 徽标配置。 */
43
+ badge?: BadgeConfig;
44
+ }
45
+ /** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */
46
+ export interface AvatarContentPresence {
47
+ /** 是否提供有效 `src`(非空字符串)。 */
48
+ hasImage: boolean;
49
+ /** 是否提供 `name`。 */
50
+ hasName: boolean;
51
+ /** 是否提供自定义降级内容(`fallback` prop / `#fallback` slot)。 */
52
+ hasFallback: boolean;
53
+ /** 是否提供自定义图标内容(`icon` prop / `#icon` slot)。 */
54
+ hasIcon: boolean;
55
+ /** 是否提供子元素(`children` / 默认 slot)。 */
56
+ hasChildren: boolean;
57
+ /** 是否提供 `badge` 配置。 */
58
+ hasBadge: boolean;
59
+ }
60
+ /** 内容展示模式,按优先级互斥推导:children > image > icon > name。 */
61
+ export type DisplayMode = "children" | "image" | "icon" | "initials";
62
+ /** 图片加载失败时的降级展示模式。 */
63
+ export type FallbackMode = "custom" | "initials" | "icon";
64
+ /** 适配器唯一可消费的归一化结果。 */
65
+ export interface ResolvedAvatarState {
66
+ shape: AvatarShape;
67
+ size: AvatarSize;
68
+ hasImage: boolean;
69
+ hasName: boolean;
70
+ decorative: boolean;
71
+ /** 用户传入的自定义背景色(undefined 时使用默认分色逻辑)。 */
72
+ bg: string | undefined;
73
+ /** 互斥展示模式:children > image > icon > name > default-icon。 */
74
+ displayMode: DisplayMode;
75
+ /** 图片加载失败时的降级模式(仅 displayMode="image" 时有效)。 */
76
+ fallbackMode: FallbackMode;
77
+ initials: string | undefined;
78
+ hasBadge: boolean;
79
+ badgeType: BadgeType | undefined;
80
+ badgeOverflow: boolean;
81
+ badgeDisplayCount: number | undefined;
82
+ badgeHidden: boolean;
83
+ }
84
+ /** Core 生成、由适配器覆盖到根元素的属性。 */
85
+ export interface AvatarRootProps {
86
+ "data-scope": "avatar";
87
+ "data-part": "root";
88
+ "data-shape": AvatarShape;
89
+ "data-size": AvatarSize;
90
+ "data-display": DisplayMode;
91
+ "data-load-status": AvatarLoadStatus;
92
+ "data-fallback": FallbackMode;
93
+ role?: "img";
94
+ "aria-label"?: string;
95
+ "aria-hidden"?: "true";
96
+ "data-has-badge"?: "true";
97
+ "data-badge-type"?: BadgeType;
98
+ }
99
+ /** Core 生成、由适配器覆盖到图片包装元素的属性。 */
100
+ export interface AvatarImageProps {
101
+ "data-scope": "avatar";
102
+ "data-part": "image";
103
+ }
104
+ /** Core 生成、由适配器覆盖到 img 元素的属性。 */
105
+ export interface AvatarImageElementProps {
106
+ alt: "";
107
+ loading: "lazy";
108
+ }
109
+ /** Core 生成、由适配器覆盖到降级内容元素的属性。 */
110
+ export interface AvatarFallbackProps {
111
+ "data-scope": "avatar";
112
+ "data-part": "fallback";
113
+ "aria-hidden": "true";
114
+ }
115
+ /** Core 生成、由适配器覆盖到徽标元素的属性。 */
116
+ export interface AvatarBadgeProps {
117
+ "data-scope": "avatar";
118
+ "data-part": "badge";
119
+ "data-badge-type": BadgeType;
120
+ "aria-label"?: string;
121
+ }
122
+ /**
123
+ * 从名称提取文字缩写。
124
+ *
125
+ * - 纯 CJK(汉字/假名/谚文)取首字
126
+ * - 纯拉丁取前 2 字符大写
127
+ * - 混合取前 2 字符
128
+ * - 上限 2 字符
129
+ * - 空字符串返回空字符串
130
+ *
131
+ * 使用 `Array.from()` 按码点迭代,不按 `charCodeAt` 截断。
132
+ */
133
+ export declare function extractInitials(name: string): string;
134
+ /** 将公开输入和内容通道归一化为唯一的跨框架状态。 */
135
+ export declare function resolveAvatarState(props?: QwAvatarProps, presence?: AvatarContentPresence): ResolvedAvatarState;
136
+ /** 将归一化结果转成 root 属性。 */
137
+ export declare function getAvatarRootProps(state: ResolvedAvatarState): AvatarRootProps;
138
+ /** 将归一化结果转成图片包装元素的属性。 */
139
+ export declare function getAvatarImageProps(_state: ResolvedAvatarState): AvatarImageProps;
140
+ /** 将归一化结果转成 img 元素的属性。 */
141
+ export declare function getAvatarImageElementProps(_state: ResolvedAvatarState): AvatarImageElementProps;
142
+ /** 将归一化结果转成降级内容元素的属性。 */
143
+ export declare function getAvatarFallbackProps(_state: ResolvedAvatarState): AvatarFallbackProps;
144
+ /** 将归一化结果转成徽标元素的属性。 */
145
+ export declare function getAvatarBadgeProps(state: ResolvedAvatarState): AvatarBadgeProps;
@@ -0,0 +1 @@
1
+ export * from "./avatar.js";
@@ -0,0 +1,150 @@
1
+ //#region src/avatar/avatar.ts
2
+ /**
3
+ * Avatar 的跨框架行为契约。
4
+ *
5
+ * Avatar 是无状态的 Prototype A:Core 归一化 props、推导降级模式和徽标状态,
6
+ * 生成 root/image/badge 的 data 属性。React/Vue 适配器只投影内容通道并渲染固定 DOM。
7
+ * 图片加载状态通过 `data-load-status` 属性由 CSS 声明式管理,不参与 Core 状态归一化。
8
+ */
9
+ const AVATAR_SHAPES = ["circle", "square"];
10
+ const AVATAR_SIZES = [
11
+ "s",
12
+ "m",
13
+ "l"
14
+ ];
15
+ const AVATAR_PARTS = [
16
+ "root",
17
+ "image",
18
+ "fallback",
19
+ "badge"
20
+ ];
21
+ const AVATAR_LOAD_STATUS = [
22
+ "loading",
23
+ "loaded",
24
+ "error"
25
+ ];
26
+ const AVATAR_BADGE_TYPES = ["dot", "number"];
27
+ const BADGE_COUNT_MAX = 99;
28
+ const EMPTY_PRESENCE = {
29
+ hasImage: false,
30
+ hasName: false,
31
+ hasFallback: false,
32
+ hasIcon: false,
33
+ hasChildren: false,
34
+ hasBadge: false
35
+ };
36
+ /**
37
+ * 从名称提取文字缩写。
38
+ *
39
+ * - 纯 CJK(汉字/假名/谚文)取首字
40
+ * - 纯拉丁取前 2 字符大写
41
+ * - 混合取前 2 字符
42
+ * - 上限 2 字符
43
+ * - 空字符串返回空字符串
44
+ *
45
+ * 使用 `Array.from()` 按码点迭代,不按 `charCodeAt` 截断。
46
+ */
47
+ function extractInitials(name) {
48
+ if (!name) return "";
49
+ const chars = Array.from(name).filter((ch) => ch.trim() !== "");
50
+ if (chars.length === 0) return "";
51
+ const isCjk = (ch) => /[\u{4E00}-\u{9FFF}\u{3040}-\u{30FF}\u{AC00}-\u{D7AF}]/u.test(ch);
52
+ if (chars.every(isCjk)) return chars[0];
53
+ return chars.slice(0, 2).join("").toUpperCase();
54
+ }
55
+ /** 将公开输入和内容通道归一化为唯一的跨框架状态。 */
56
+ function resolveAvatarState(props = {}, presence = EMPTY_PRESENCE) {
57
+ const hasImage = presence.hasImage;
58
+ const hasName = presence.hasName;
59
+ const decorative = props.decorative ?? false;
60
+ const bg = props.bg;
61
+ const displayMode = presence.hasChildren ? "children" : hasImage ? "image" : presence.hasIcon ? "icon" : hasName ? "initials" : "icon";
62
+ const fallbackMode = presence.hasFallback ? "custom" : presence.hasIcon ? "icon" : hasName ? "initials" : "icon";
63
+ const initials = hasName && props.name ? extractInitials(props.name) : void 0;
64
+ const hasBadge = presence.hasBadge;
65
+ const badgeType = hasBadge ? props.badge?.type : void 0;
66
+ let badgeDisplayCount;
67
+ let badgeOverflow = false;
68
+ let badgeHidden = false;
69
+ if (hasBadge && badgeType === "number") {
70
+ const rawCount = props.badge?.count ?? 0;
71
+ if (rawCount <= 0) {
72
+ badgeHidden = true;
73
+ badgeDisplayCount = void 0;
74
+ } else if (rawCount > 99) {
75
+ badgeOverflow = true;
76
+ badgeDisplayCount = 99;
77
+ } else badgeDisplayCount = rawCount;
78
+ }
79
+ return {
80
+ shape: props.shape ?? "circle",
81
+ size: props.size ?? "m",
82
+ hasImage,
83
+ hasName,
84
+ decorative,
85
+ bg,
86
+ displayMode,
87
+ fallbackMode,
88
+ initials,
89
+ hasBadge: hasBadge && !badgeHidden,
90
+ badgeType,
91
+ badgeOverflow,
92
+ badgeDisplayCount,
93
+ badgeHidden
94
+ };
95
+ }
96
+ /** 将归一化结果转成 root 属性。 */
97
+ function getAvatarRootProps(state) {
98
+ const props = {
99
+ "data-scope": "avatar",
100
+ "data-part": "root",
101
+ "data-shape": state.shape,
102
+ "data-size": state.size,
103
+ "data-display": state.displayMode,
104
+ "data-load-status": state.displayMode === "image" ? "loading" : "error",
105
+ "data-fallback": state.fallbackMode
106
+ };
107
+ if (state.decorative) {
108
+ props["aria-hidden"] = "true";
109
+ props["role"] = "img";
110
+ } else if (state.hasName) props["role"] = "img";
111
+ if (state.hasBadge && state.badgeType) {
112
+ props["data-has-badge"] = "true";
113
+ props["data-badge-type"] = state.badgeType;
114
+ }
115
+ return props;
116
+ }
117
+ /** 将归一化结果转成图片包装元素的属性。 */
118
+ function getAvatarImageProps(_state) {
119
+ return {
120
+ "data-scope": "avatar",
121
+ "data-part": "image"
122
+ };
123
+ }
124
+ /** 将归一化结果转成 img 元素的属性。 */
125
+ function getAvatarImageElementProps(_state) {
126
+ return {
127
+ alt: "",
128
+ loading: "lazy"
129
+ };
130
+ }
131
+ /** 将归一化结果转成降级内容元素的属性。 */
132
+ function getAvatarFallbackProps(_state) {
133
+ return {
134
+ "data-scope": "avatar",
135
+ "data-part": "fallback",
136
+ "aria-hidden": "true"
137
+ };
138
+ }
139
+ /** 将归一化结果转成徽标元素的属性。 */
140
+ function getAvatarBadgeProps(state) {
141
+ return {
142
+ "data-scope": "avatar",
143
+ "data-part": "badge",
144
+ "data-badge-type": state.badgeType ?? "dot"
145
+ };
146
+ }
147
+ //#endregion
148
+ export { AVATAR_BADGE_TYPES, AVATAR_LOAD_STATUS, AVATAR_PARTS, AVATAR_SHAPES, AVATAR_SIZES, BADGE_COUNT_MAX, extractInitials, getAvatarBadgeProps, getAvatarFallbackProps, getAvatarImageElementProps, getAvatarImageProps, getAvatarRootProps, resolveAvatarState };
149
+
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/avatar/avatar.ts"],"sourcesContent":["/**\n * Avatar 的跨框架行为契约。\n *\n * Avatar 是无状态的 Prototype A:Core 归一化 props、推导降级模式和徽标状态,\n * 生成 root/image/badge 的 data 属性。React/Vue 适配器只投影内容通道并渲染固定 DOM。\n * 图片加载状态通过 `data-load-status` 属性由 CSS 声明式管理,不参与 Core 状态归一化。\n */\n\nexport const AVATAR_SHAPES = [\"circle\", \"square\"] as const;\nexport const AVATAR_SIZES = [\"s\", \"m\", \"l\"] as const;\nexport const AVATAR_PARTS = [\"root\", \"image\", \"fallback\", \"badge\"] as const;\nexport const AVATAR_LOAD_STATUS = [\"loading\", \"loaded\", \"error\"] as const;\nexport const AVATAR_BADGE_TYPES = [\"dot\", \"number\"] as const;\nexport const BADGE_COUNT_MAX = 99;\n\nexport type AvatarShape = (typeof AVATAR_SHAPES)[number];\nexport type AvatarSize = (typeof AVATAR_SIZES)[number];\nexport type AvatarPart = (typeof AVATAR_PARTS)[number];\nexport type AvatarLoadStatus = (typeof AVATAR_LOAD_STATUS)[number];\nexport type BadgeType = (typeof AVATAR_BADGE_TYPES)[number];\n\n/** 徽标配置(双栈共享标量,内容通道不进入 Core)。 */\nexport interface BadgeConfig {\n /** 徽标类型。 */\n type: BadgeType;\n /** 数字徽标的数值。 */\n count?: number;\n /** 徽标无障碍标签。 */\n ariaLabel?: string;\n}\n\n/** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */\nexport interface QwAvatarProps {\n /** 图片源地址。空字符串或 undefined 时不渲染 img,直接进入降级。 */\n src?: string;\n /** 名称,用于提取缩写和 aria-label。 */\n name?: string;\n /** 外形,默认 `circle`。 */\n shape?: AvatarShape;\n /** 尺寸,默认 `m`。 */\n size?: AvatarSize;\n /** 装饰模式(从辅助技术隐藏)。 */\n decorative?: boolean;\n /** 自定义背景色,设置后覆盖所有展示形式的默认背景色。 */\n bg?: string;\n /** 徽标配置。 */\n badge?: BadgeConfig;\n}\n\n/** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */\nexport interface AvatarContentPresence {\n /** 是否提供有效 `src`(非空字符串)。 */\n hasImage: boolean;\n /** 是否提供 `name`。 */\n hasName: boolean;\n /** 是否提供自定义降级内容(`fallback` prop / `#fallback` slot)。 */\n hasFallback: boolean;\n /** 是否提供自定义图标内容(`icon` prop / `#icon` slot)。 */\n hasIcon: boolean;\n /** 是否提供子元素(`children` / 默认 slot)。 */\n hasChildren: boolean;\n /** 是否提供 `badge` 配置。 */\n hasBadge: boolean;\n}\n\n/** 内容展示模式,按优先级互斥推导:children > image > icon > name。 */\nexport type DisplayMode = \"children\" | \"image\" | \"icon\" | \"initials\";\n\n/** 图片加载失败时的降级展示模式。 */\nexport type FallbackMode = \"custom\" | \"initials\" | \"icon\";\n\n/** 适配器唯一可消费的归一化结果。 */\nexport interface ResolvedAvatarState {\n shape: AvatarShape;\n size: AvatarSize;\n hasImage: boolean;\n hasName: boolean;\n decorative: boolean;\n /** 用户传入的自定义背景色(undefined 时使用默认分色逻辑)。 */\n bg: string | undefined;\n /** 互斥展示模式:children > image > icon > name > default-icon。 */\n displayMode: DisplayMode;\n /** 图片加载失败时的降级模式(仅 displayMode=\"image\" 时有效)。 */\n fallbackMode: FallbackMode;\n initials: string | undefined;\n hasBadge: boolean;\n badgeType: BadgeType | undefined;\n badgeOverflow: boolean;\n badgeDisplayCount: number | undefined;\n badgeHidden: boolean;\n}\n\n/** Core 生成、由适配器覆盖到根元素的属性。 */\nexport interface AvatarRootProps {\n \"data-scope\": \"avatar\";\n \"data-part\": \"root\";\n \"data-shape\": AvatarShape;\n \"data-size\": AvatarSize;\n \"data-display\": DisplayMode;\n \"data-load-status\": AvatarLoadStatus;\n \"data-fallback\": FallbackMode;\n role?: \"img\";\n \"aria-label\"?: string;\n \"aria-hidden\"?: \"true\";\n \"data-has-badge\"?: \"true\";\n \"data-badge-type\"?: BadgeType;\n}\n\n/** Core 生成、由适配器覆盖到图片包装元素的属性。 */\nexport interface AvatarImageProps {\n \"data-scope\": \"avatar\";\n \"data-part\": \"image\";\n}\n\n/** Core 生成、由适配器覆盖到 img 元素的属性。 */\nexport interface AvatarImageElementProps {\n alt: \"\";\n loading: \"lazy\";\n}\n\n/** Core 生成、由适配器覆盖到降级内容元素的属性。 */\nexport interface AvatarFallbackProps {\n \"data-scope\": \"avatar\";\n \"data-part\": \"fallback\";\n \"aria-hidden\": \"true\";\n}\n\n/** Core 生成、由适配器覆盖到徽标元素的属性。 */\nexport interface AvatarBadgeProps {\n \"data-scope\": \"avatar\";\n \"data-part\": \"badge\";\n \"data-badge-type\": BadgeType;\n \"aria-label\"?: string;\n}\n\nconst EMPTY_PRESENCE: AvatarContentPresence = {\n hasImage: false,\n hasName: false,\n hasFallback: false,\n hasIcon: false,\n hasChildren: false,\n hasBadge: false,\n};\n\n/**\n * 从名称提取文字缩写。\n *\n * - 纯 CJK(汉字/假名/谚文)取首字\n * - 纯拉丁取前 2 字符大写\n * - 混合取前 2 字符\n * - 上限 2 字符\n * - 空字符串返回空字符串\n *\n * 使用 `Array.from()` 按码点迭代,不按 `charCodeAt` 截断。\n */\nexport function extractInitials(name: string): string {\n if (!name) return \"\";\n const chars = Array.from(name).filter((ch) => ch.trim() !== \"\");\n if (chars.length === 0) return \"\";\n\n const isCjk = (ch: string) => /[\\u{4E00}-\\u{9FFF}\\u{3040}-\\u{30FF}\\u{AC00}-\\u{D7AF}]/u.test(ch);\n const allCjk = chars.every(isCjk);\n\n if (allCjk) {\n return chars[0]!;\n }\n\n const result = chars.slice(0, 2).join(\"\").toUpperCase();\n return result;\n}\n\n/** 将公开输入和内容通道归一化为唯一的跨框架状态。 */\nexport function resolveAvatarState(\n props: QwAvatarProps = {},\n presence: AvatarContentPresence = EMPTY_PRESENCE,\n): ResolvedAvatarState {\n const hasImage = presence.hasImage;\n const hasName = presence.hasName;\n const decorative = props.decorative ?? false;\n const bg = props.bg;\n\n // 互斥展示优先级:children > image > icon > name > default-icon\n const displayMode: DisplayMode = presence.hasChildren\n ? \"children\"\n : hasImage\n ? \"image\"\n : presence.hasIcon\n ? \"icon\"\n : hasName\n ? \"initials\"\n : \"icon\"; // 默认:展示 User 图标\n\n // 图片加载失败时的降级模式(仅 displayMode=\"image\" 时有效)\n // 降级优先级:fallback prop > icon > name > default-icon\n const fallbackMode: FallbackMode = presence.hasFallback\n ? \"custom\"\n : presence.hasIcon\n ? \"icon\"\n : hasName\n ? \"initials\"\n : \"icon\";\n\n const initials = hasName && props.name ? extractInitials(props.name) : undefined;\n\n // 徽标逻辑\n const hasBadge = presence.hasBadge;\n const badgeType = hasBadge ? props.badge?.type : undefined;\n\n let badgeDisplayCount: number | undefined;\n let badgeOverflow = false;\n let badgeHidden = false;\n\n if (hasBadge && badgeType === \"number\") {\n const rawCount = props.badge?.count ?? 0;\n if (rawCount <= 0) {\n badgeHidden = true;\n badgeDisplayCount = undefined;\n } else if (rawCount > BADGE_COUNT_MAX) {\n badgeOverflow = true;\n badgeDisplayCount = BADGE_COUNT_MAX;\n } else {\n badgeDisplayCount = rawCount;\n }\n }\n\n return {\n shape: props.shape ?? \"circle\",\n size: props.size ?? \"m\",\n hasImage,\n hasName,\n decorative,\n bg,\n displayMode,\n fallbackMode,\n initials,\n hasBadge: hasBadge && !badgeHidden,\n badgeType,\n badgeOverflow,\n badgeDisplayCount,\n badgeHidden,\n };\n}\n\n/** 将归一化结果转成 root 属性。 */\nexport function getAvatarRootProps(state: ResolvedAvatarState): AvatarRootProps {\n const props: AvatarRootProps = {\n \"data-scope\": \"avatar\",\n \"data-part\": \"root\",\n \"data-shape\": state.shape,\n \"data-size\": state.size,\n \"data-display\": state.displayMode,\n \"data-load-status\": state.displayMode === \"image\" ? \"loading\" : \"error\",\n \"data-fallback\": state.fallbackMode,\n };\n\n // aria 策略:\n // - decorative → aria-hidden=\"true\" + role=\"img\"(AT 忽略)\n // - 有 name → role=\"img\" + aria-label(由适配器设置)\n // - 无 name 且非 decorative → 不设 role(避免 role-img-alt 违规)\n if (state.decorative) {\n props[\"aria-hidden\"] = \"true\";\n props[\"role\"] = \"img\";\n } else if (state.hasName) {\n props[\"role\"] = \"img\";\n // aria-label 由适配器从 name 设置(Core 不持有 name 的运行时值)\n }\n\n if (state.hasBadge && state.badgeType) {\n props[\"data-has-badge\"] = \"true\";\n props[\"data-badge-type\"] = state.badgeType;\n }\n\n return props;\n}\n\n/** 将归一化结果转成图片包装元素的属性。 */\nexport function getAvatarImageProps(_state: ResolvedAvatarState): AvatarImageProps {\n return {\n \"data-scope\": \"avatar\",\n \"data-part\": \"image\",\n };\n}\n\n/** 将归一化结果转成 img 元素的属性。 */\nexport function getAvatarImageElementProps(\n _state: ResolvedAvatarState,\n): AvatarImageElementProps {\n return {\n alt: \"\",\n loading: \"lazy\",\n };\n}\n\n/** 将归一化结果转成降级内容元素的属性。 */\nexport function getAvatarFallbackProps(\n _state: ResolvedAvatarState,\n): AvatarFallbackProps {\n return {\n \"data-scope\": \"avatar\",\n \"data-part\": \"fallback\",\n \"aria-hidden\": \"true\",\n };\n}\n\n/** 将归一化结果转成徽标元素的属性。 */\nexport function getAvatarBadgeProps(state: ResolvedAvatarState): AvatarBadgeProps {\n const props: AvatarBadgeProps = {\n \"data-scope\": \"avatar\",\n \"data-part\": \"badge\",\n \"data-badge-type\": state.badgeType ?? \"dot\",\n };\n\n // aria-label 来自 badge.ariaLabel,由适配器透传\n return props;\n}\n"],"mappings":";;;;;;;;AAQA,MAAa,gBAAgB,CAAC,UAAU,QAAQ;AAChD,MAAa,eAAe;CAAC;CAAK;CAAK;AAAG;AAC1C,MAAa,eAAe;CAAC;CAAQ;CAAS;CAAY;AAAO;AACjE,MAAa,qBAAqB;CAAC;CAAW;CAAU;AAAO;AAC/D,MAAa,qBAAqB,CAAC,OAAO,QAAQ;AAClD,MAAa,kBAAkB;AA0H/B,MAAM,iBAAwC;CAC5C,UAAU;CACV,SAAS;CACT,aAAa;CACb,SAAS;CACT,aAAa;CACb,UAAU;AACZ;;;;;;;;;;;;AAaA,SAAgB,gBAAgB,MAAsB;CACpD,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,QAAQ,MAAM,KAAK,IAAI,CAAC,CAAC,QAAQ,OAAO,GAAG,KAAK,MAAM,EAAE;CAC9D,IAAI,MAAM,WAAW,GAAG,OAAO;CAE/B,MAAM,SAAS,OAAe,yDAAyD,KAAK,EAAE;CAG9F,IAFe,MAAM,MAAM,KAElB,GACP,OAAO,MAAM;CAIf,OADe,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,YAC9B;AACd;;AAGA,SAAgB,mBACd,QAAuB,CAAC,GACxB,WAAkC,gBACb;CACrB,MAAM,WAAW,SAAS;CAC1B,MAAM,UAAU,SAAS;CACzB,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,KAAK,MAAM;CAGjB,MAAM,cAA2B,SAAS,cACtC,aACA,WACE,UACA,SAAS,UACP,SACA,UACE,aACA;CAIV,MAAM,eAA6B,SAAS,cACxC,WACA,SAAS,UACP,SACA,UACE,aACA;CAER,MAAM,WAAW,WAAW,MAAM,OAAO,gBAAgB,MAAM,IAAI,IAAI,KAAA;CAGvE,MAAM,WAAW,SAAS;CAC1B,MAAM,YAAY,WAAW,MAAM,OAAO,OAAO,KAAA;CAEjD,IAAI;CACJ,IAAI,gBAAgB;CACpB,IAAI,cAAc;CAElB,IAAI,YAAY,cAAc,UAAU;EACtC,MAAM,WAAW,MAAM,OAAO,SAAS;EACvC,IAAI,YAAY,GAAG;GACjB,cAAc;GACd,oBAAoB,KAAA;EACtB,OAAO,IAAI,WAAA,IAA4B;GACrC,gBAAgB;GAChB,oBAAA;EACF,OACE,oBAAoB;CAExB;CAEA,OAAO;EACL,OAAO,MAAM,SAAS;EACtB,MAAM,MAAM,QAAQ;EACpB;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,YAAY,CAAC;EACvB;EACA;EACA;EACA;CACF;AACF;;AAGA,SAAgB,mBAAmB,OAA6C;CAC9E,MAAM,QAAyB;EAC7B,cAAc;EACd,aAAa;EACb,cAAc,MAAM;EACpB,aAAa,MAAM;EACnB,gBAAgB,MAAM;EACtB,oBAAoB,MAAM,gBAAgB,UAAU,YAAY;EAChE,iBAAiB,MAAM;CACzB;CAMA,IAAI,MAAM,YAAY;EACpB,MAAM,iBAAiB;EACvB,MAAM,UAAU;CAClB,OAAO,IAAI,MAAM,SACf,MAAM,UAAU;CAIlB,IAAI,MAAM,YAAY,MAAM,WAAW;EACrC,MAAM,oBAAoB;EAC1B,MAAM,qBAAqB,MAAM;CACnC;CAEA,OAAO;AACT;;AAGA,SAAgB,oBAAoB,QAA+C;CACjF,OAAO;EACL,cAAc;EACd,aAAa;CACf;AACF;;AAGA,SAAgB,2BACd,QACyB;CACzB,OAAO;EACL,KAAK;EACL,SAAS;CACX;AACF;;AAGA,SAAgB,uBACd,QACqB;CACrB,OAAO;EACL,cAAc;EACd,aAAa;EACb,eAAe;CACjB;AACF;;AAGA,SAAgB,oBAAoB,OAA8C;CAQhF,OAAO;EANL,cAAc;EACd,aAAa;EACb,mBAAmB,MAAM,aAAa;CAI7B;AACb"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Button 的跨框架行为契约。
3
+ *
4
+ * Button 是无状态的 Prototype A:这里仅归一化公开 props 与内容通道,React/Vue
5
+ * 适配器不得复制 icon-only、disabled 或 block 的组合规则。
6
+ */
7
+ export declare const BUTTON_VARIANTS: readonly ["solid", "soft", "outline", "ghost", "link"];
8
+ export declare const BUTTON_TONES: readonly ["brand", "neutral", "danger"];
9
+ export declare const BUTTON_SIZES: readonly ["mini", "xs", "s", "normal", "m", "l"];
10
+ export declare const BUTTON_SHAPES: readonly ["default", "square", "round"];
11
+ export declare const BUTTON_ICON_POSITIONS: readonly ["start", "end"];
12
+ export declare const BUTTON_PARTS: readonly ["root", "content", "icon", "label", "spinner"];
13
+ export type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
14
+ export type ButtonTone = (typeof BUTTON_TONES)[number];
15
+ export type ButtonSize = (typeof BUTTON_SIZES)[number];
16
+ export type ButtonShape = (typeof BUTTON_SHAPES)[number];
17
+ export type ButtonIconPosition = (typeof BUTTON_ICON_POSITIONS)[number];
18
+ export type ButtonPart = (typeof BUTTON_PARTS)[number];
19
+ /** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */
20
+ export interface QwButtonProps {
21
+ /** 视觉层级,默认 `solid`。 */
22
+ variant?: ButtonVariant;
23
+ /** 语气,默认 `brand`。 */
24
+ tone?: ButtonTone;
25
+ /** 尺寸,默认 `normal`。 */
26
+ size?: ButtonSize;
27
+ /** 外形,默认 `default`。 */
28
+ shape?: ButtonShape;
29
+ /** 图标与默认内容同时存在时的视觉位置,默认 `start`。 */
30
+ iconPosition?: ButtonIconPosition;
31
+ /** 有默认内容时撑满容器可用宽度。 */
32
+ block?: boolean;
33
+ /** 忙碌时保持内容、显示 spinner 并禁用原生 button。 */
34
+ loading?: boolean;
35
+ /** 原生禁用状态。 */
36
+ disabled?: boolean;
37
+ /** 原生 button 类型,默认 `button`。 */
38
+ type?: "button" | "submit" | "reset";
39
+ }
40
+ /** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */
41
+ export interface ButtonContentPresence {
42
+ hasIcon: boolean;
43
+ hasContent: boolean;
44
+ }
45
+ /** 适配器唯一可消费的归一化结果。 */
46
+ export interface ResolvedButtonState {
47
+ variant: ButtonVariant;
48
+ tone: ButtonTone;
49
+ size: ButtonSize;
50
+ shape: ButtonShape;
51
+ iconPosition: ButtonIconPosition;
52
+ hasIcon: boolean;
53
+ hasContent: boolean;
54
+ iconOnly: boolean;
55
+ loading: boolean;
56
+ effectiveDisabled: boolean;
57
+ effectiveBlock: boolean;
58
+ warning?: "icon-only-block-ignored";
59
+ type: "button" | "submit" | "reset";
60
+ }
61
+ /** Core 生成、由适配器最后覆盖到根元素的属性。 */
62
+ export interface ButtonRootProps {
63
+ type: "button" | "submit" | "reset";
64
+ disabled: boolean;
65
+ "aria-busy"?: true;
66
+ "data-scope": "button";
67
+ "data-part": "root";
68
+ "data-variant": ButtonVariant;
69
+ "data-tone": ButtonTone;
70
+ "data-size": ButtonSize;
71
+ "data-shape": ButtonShape;
72
+ "data-icon-position": ButtonIconPosition;
73
+ "data-has-icon"?: "true";
74
+ "data-icon-only"?: "true";
75
+ "data-block"?: "true";
76
+ "data-loading"?: "true";
77
+ }
78
+ /** 将公开输入和内容通道归一化为唯一的跨框架状态。 */
79
+ export declare function resolveButtonState(props?: QwButtonProps, presence?: ButtonContentPresence): ResolvedButtonState;
80
+ /**
81
+ * 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法
82
+ * aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。
83
+ */
84
+ export declare function getButtonRootProps(state: ResolvedButtonState): ButtonRootProps;
@@ -0,0 +1 @@
1
+ export * from "./button.js";
@@ -0,0 +1,104 @@
1
+ //#region src/button/button.ts
2
+ /**
3
+ * Button 的跨框架行为契约。
4
+ *
5
+ * Button 是无状态的 Prototype A:这里仅归一化公开 props 与内容通道,React/Vue
6
+ * 适配器不得复制 icon-only、disabled 或 block 的组合规则。
7
+ */
8
+ const BUTTON_VARIANTS = [
9
+ "solid",
10
+ "soft",
11
+ "outline",
12
+ "ghost",
13
+ "link"
14
+ ];
15
+ const BUTTON_TONES = [
16
+ "brand",
17
+ "neutral",
18
+ "danger"
19
+ ];
20
+ const BUTTON_SIZES = [
21
+ "mini",
22
+ "xs",
23
+ "s",
24
+ "normal",
25
+ "m",
26
+ "l"
27
+ ];
28
+ const BUTTON_SHAPES = [
29
+ "default",
30
+ "square",
31
+ "round"
32
+ ];
33
+ const BUTTON_ICON_POSITIONS = ["start", "end"];
34
+ const BUTTON_PARTS = [
35
+ "root",
36
+ "content",
37
+ "icon",
38
+ "label",
39
+ "spinner"
40
+ ];
41
+ const EMPTY_PRESENCE = {
42
+ hasIcon: false,
43
+ hasContent: false
44
+ };
45
+ const BUILD_MODE = import.meta.env?.MODE;
46
+ /**
47
+ * 诊断只属于明确的开发环境。Vite 会在浏览器构建中提供 `import.meta.env.MODE`;
48
+ * 未注入 process/env 的已发布浏览器产物默认静默,避免生产控制台噪音。
49
+ */
50
+ function isDevelopmentBuild() {
51
+ if (BUILD_MODE != null) return BUILD_MODE !== "production";
52
+ const nodeEnv = globalThis.process?.env?.NODE_ENV;
53
+ return nodeEnv === "development" || nodeEnv === "test";
54
+ }
55
+ /** 将公开输入和内容通道归一化为唯一的跨框架状态。 */
56
+ function resolveButtonState(props = {}, presence = EMPTY_PRESENCE) {
57
+ const hasIcon = presence.hasIcon;
58
+ const hasContent = presence.hasContent;
59
+ const iconOnly = hasIcon && !hasContent;
60
+ const loading = props.loading ?? false;
61
+ const effectiveDisabled = (props.disabled ?? false) || loading;
62
+ const effectiveBlock = (props.block ?? false) && !iconOnly;
63
+ return {
64
+ variant: props.variant ?? "solid",
65
+ tone: props.tone ?? "brand",
66
+ size: props.size ?? "normal",
67
+ shape: props.shape ?? "default",
68
+ iconPosition: props.iconPosition ?? "start",
69
+ hasIcon,
70
+ hasContent,
71
+ iconOnly,
72
+ loading,
73
+ effectiveDisabled,
74
+ effectiveBlock,
75
+ ...iconOnly && props.block && isDevelopmentBuild() ? { warning: "icon-only-block-ignored" } : {},
76
+ type: props.type ?? "button"
77
+ };
78
+ }
79
+ /**
80
+ * 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法
81
+ * aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。
82
+ */
83
+ function getButtonRootProps(state) {
84
+ return {
85
+ type: state.type,
86
+ disabled: state.effectiveDisabled,
87
+ ...state.loading ? { "aria-busy": true } : {},
88
+ "data-scope": "button",
89
+ "data-part": "root",
90
+ "data-variant": state.variant,
91
+ "data-tone": state.tone,
92
+ "data-size": state.size,
93
+ "data-shape": state.shape,
94
+ "data-icon-position": state.iconPosition,
95
+ ...state.hasIcon ? { "data-has-icon": "true" } : {},
96
+ ...state.iconOnly ? { "data-icon-only": "true" } : {},
97
+ ...state.effectiveBlock ? { "data-block": "true" } : {},
98
+ ...state.loading ? { "data-loading": "true" } : {}
99
+ };
100
+ }
101
+ //#endregion
102
+ export { BUTTON_ICON_POSITIONS, BUTTON_PARTS, BUTTON_SHAPES, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, getButtonRootProps, resolveButtonState };
103
+
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/button/button.ts"],"sourcesContent":["/**\n * Button 的跨框架行为契约。\n *\n * Button 是无状态的 Prototype A:这里仅归一化公开 props 与内容通道,React/Vue\n * 适配器不得复制 icon-only、disabled 或 block 的组合规则。\n */\n\nexport const BUTTON_VARIANTS = [\"solid\", \"soft\", \"outline\", \"ghost\", \"link\"] as const;\nexport const BUTTON_TONES = [\"brand\", \"neutral\", \"danger\"] as const;\nexport const BUTTON_SIZES = [\"mini\", \"xs\", \"s\", \"normal\", \"m\", \"l\"] as const;\nexport const BUTTON_SHAPES = [\"default\", \"square\", \"round\"] as const;\nexport const BUTTON_ICON_POSITIONS = [\"start\", \"end\"] as const;\nexport const BUTTON_PARTS = [\"root\", \"content\", \"icon\", \"label\", \"spinner\"] as const;\n\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\nexport type ButtonTone = (typeof BUTTON_TONES)[number];\nexport type ButtonSize = (typeof BUTTON_SIZES)[number];\nexport type ButtonShape = (typeof BUTTON_SHAPES)[number];\nexport type ButtonIconPosition = (typeof BUTTON_ICON_POSITIONS)[number];\nexport type ButtonPart = (typeof BUTTON_PARTS)[number];\n\n/** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */\nexport interface QwButtonProps {\n /** 视觉层级,默认 `solid`。 */\n variant?: ButtonVariant;\n /** 语气,默认 `brand`。 */\n tone?: ButtonTone;\n /** 尺寸,默认 `normal`。 */\n size?: ButtonSize;\n /** 外形,默认 `default`。 */\n shape?: ButtonShape;\n /** 图标与默认内容同时存在时的视觉位置,默认 `start`。 */\n iconPosition?: ButtonIconPosition;\n /** 有默认内容时撑满容器可用宽度。 */\n block?: boolean;\n /** 忙碌时保持内容、显示 spinner 并禁用原生 button。 */\n loading?: boolean;\n /** 原生禁用状态。 */\n disabled?: boolean;\n /** 原生 button 类型,默认 `button`。 */\n type?: \"button\" | \"submit\" | \"reset\";\n}\n\n/** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */\nexport interface ButtonContentPresence {\n hasIcon: boolean;\n hasContent: boolean;\n}\n\n/** 适配器唯一可消费的归一化结果。 */\nexport interface ResolvedButtonState {\n variant: ButtonVariant;\n tone: ButtonTone;\n size: ButtonSize;\n shape: ButtonShape;\n iconPosition: ButtonIconPosition;\n hasIcon: boolean;\n hasContent: boolean;\n iconOnly: boolean;\n loading: boolean;\n effectiveDisabled: boolean;\n effectiveBlock: boolean;\n warning?: \"icon-only-block-ignored\";\n type: \"button\" | \"submit\" | \"reset\";\n}\n\n/** Core 生成、由适配器最后覆盖到根元素的属性。 */\nexport interface ButtonRootProps {\n type: \"button\" | \"submit\" | \"reset\";\n disabled: boolean;\n \"aria-busy\"?: true;\n \"data-scope\": \"button\";\n \"data-part\": \"root\";\n \"data-variant\": ButtonVariant;\n \"data-tone\": ButtonTone;\n \"data-size\": ButtonSize;\n \"data-shape\": ButtonShape;\n \"data-icon-position\": ButtonIconPosition;\n \"data-has-icon\"?: \"true\";\n \"data-icon-only\"?: \"true\";\n \"data-block\"?: \"true\";\n \"data-loading\"?: \"true\";\n}\n\nconst EMPTY_PRESENCE: ButtonContentPresence = { hasIcon: false, hasContent: false };\nconst BUILD_MODE = (import.meta as ImportMeta & { env?: { MODE?: string } }).env?.MODE;\n\n/**\n * 诊断只属于明确的开发环境。Vite 会在浏览器构建中提供 `import.meta.env.MODE`;\n * 未注入 process/env 的已发布浏览器产物默认静默,避免生产控制台噪音。\n */\nfunction isDevelopmentBuild(): boolean {\n if (BUILD_MODE != null) return BUILD_MODE !== \"production\";\n\n const nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV;\n return nodeEnv === \"development\" || nodeEnv === \"test\";\n}\n\n/** 将公开输入和内容通道归一化为唯一的跨框架状态。 */\nexport function resolveButtonState(\n props: QwButtonProps = {},\n presence: ButtonContentPresence = EMPTY_PRESENCE,\n): ResolvedButtonState {\n const hasIcon = presence.hasIcon;\n const hasContent = presence.hasContent;\n const iconOnly = hasIcon && !hasContent;\n const loading = props.loading ?? false;\n const effectiveDisabled = (props.disabled ?? false) || loading;\n const effectiveBlock = (props.block ?? false) && !iconOnly;\n\n return {\n variant: props.variant ?? \"solid\",\n tone: props.tone ?? \"brand\",\n size: props.size ?? \"normal\",\n shape: props.shape ?? \"default\",\n iconPosition: props.iconPosition ?? \"start\",\n hasIcon,\n hasContent,\n iconOnly,\n loading,\n effectiveDisabled,\n effectiveBlock,\n ...(iconOnly && props.block && isDevelopmentBuild()\n ? { warning: \"icon-only-block-ignored\" as const }\n : {}),\n type: props.type ?? \"button\",\n };\n}\n\n/**\n * 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法\n * aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。\n */\nexport function getButtonRootProps(state: ResolvedButtonState): ButtonRootProps {\n return {\n type: state.type,\n disabled: state.effectiveDisabled,\n ...(state.loading ? { \"aria-busy\": true as const } : {}),\n \"data-scope\": \"button\",\n \"data-part\": \"root\",\n \"data-variant\": state.variant,\n \"data-tone\": state.tone,\n \"data-size\": state.size,\n \"data-shape\": state.shape,\n \"data-icon-position\": state.iconPosition,\n ...(state.hasIcon ? { \"data-has-icon\": \"true\" as const } : {}),\n ...(state.iconOnly ? { \"data-icon-only\": \"true\" as const } : {}),\n ...(state.effectiveBlock ? { \"data-block\": \"true\" as const } : {}),\n ...(state.loading ? { \"data-loading\": \"true\" as const } : {}),\n };\n}\n"],"mappings":";;;;;;;AAOA,MAAa,kBAAkB;CAAC;CAAS;CAAQ;CAAW;CAAS;AAAM;AAC3E,MAAa,eAAe;CAAC;CAAS;CAAW;AAAQ;AACzD,MAAa,eAAe;CAAC;CAAQ;CAAM;CAAK;CAAU;CAAK;AAAG;AAClE,MAAa,gBAAgB;CAAC;CAAW;CAAU;AAAO;AAC1D,MAAa,wBAAwB,CAAC,SAAS,KAAK;AACpD,MAAa,eAAe;CAAC;CAAQ;CAAW;CAAQ;CAAS;AAAS;AAwE1E,MAAM,iBAAwC;CAAE,SAAS;CAAO,YAAY;AAAM;AAClF,MAAM,aAAc,OAAO,KAAkD,KAAK;;;;;AAMlF,SAAS,qBAA8B;CACrC,IAAI,cAAc,MAAM,OAAO,eAAe;CAE9C,MAAM,UAAW,WAA6D,SAAS,KAAK;CAC5F,OAAO,YAAY,iBAAiB,YAAY;AAClD;;AAGA,SAAgB,mBACd,QAAuB,CAAC,GACxB,WAAkC,gBACb;CACrB,MAAM,UAAU,SAAS;CACzB,MAAM,aAAa,SAAS;CAC5B,MAAM,WAAW,WAAW,CAAC;CAC7B,MAAM,UAAU,MAAM,WAAW;CACjC,MAAM,qBAAqB,MAAM,YAAY,UAAU;CACvD,MAAM,kBAAkB,MAAM,SAAS,UAAU,CAAC;CAElD,OAAO;EACL,SAAS,MAAM,WAAW;EAC1B,MAAM,MAAM,QAAQ;EACpB,MAAM,MAAM,QAAQ;EACpB,OAAO,MAAM,SAAS;EACtB,cAAc,MAAM,gBAAgB;EACpC;EACA;EACA;EACA;EACA;EACA;EACA,GAAI,YAAY,MAAM,SAAS,mBAAmB,IAC9C,EAAE,SAAS,0BAAmC,IAC9C,CAAC;EACL,MAAM,MAAM,QAAQ;CACtB;AACF;;;;;AAMA,SAAgB,mBAAmB,OAA6C;CAC9E,OAAO;EACL,MAAM,MAAM;EACZ,UAAU,MAAM;EAChB,GAAI,MAAM,UAAU,EAAE,aAAa,KAAc,IAAI,CAAC;EACtD,cAAc;EACd,aAAa;EACb,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACnB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,sBAAsB,MAAM;EAC5B,GAAI,MAAM,UAAU,EAAE,iBAAiB,OAAgB,IAAI,CAAC;EAC5D,GAAI,MAAM,WAAW,EAAE,kBAAkB,OAAgB,IAAI,CAAC;EAC9D,GAAI,MAAM,iBAAiB,EAAE,cAAc,OAAgB,IAAI,CAAC;EAChE,GAAI,MAAM,UAAU,EAAE,gBAAgB,OAAgB,IAAI,CAAC;CAC7D;AACF"}
@@ -0,0 +1,59 @@
1
+ import type { Props as ZagDialogProps } from "@zag-js/dialog";
2
+ /**
3
+ * QwDialogProps — Dialog 的用户输入。
4
+ *
5
+ * 对 zag.js 输入做两件事 (§06):
6
+ * 1. 默认值收口:closeOnEsc / closeOnOutside / scrollLock 默认全 true;
7
+ * 2. 命名 rebrand:把 zag 的 closeOnInteractOutside / preventScroll 改成业务易懂命名;
8
+ * 3. 业务 props 透出:onOpenChange / initialFocus / returnFocus 在 React/Vue 同名。
9
+ *
10
+ * 业务方只需 import 本类型,不需要直接 import `@zag-js/*`。
11
+ */
12
+ export interface QwDialogProps {
13
+ /** 唯一 id 前缀;不传时由 zag 安全生成 (SSR/CSR 一致)。 */
14
+ id?: string;
15
+ /** 受控开关。 */
16
+ open?: boolean;
17
+ /** 非受控初值。 */
18
+ defaultOpen?: boolean;
19
+ /** ESC 关闭,默认 true (zag 原名 closeOnEscape)。 */
20
+ closeOnEsc?: boolean;
21
+ /** 点击 backdrop 关闭,默认 true (zag 原名 closeOnInteractOutside)。 */
22
+ closeOnOutside?: boolean;
23
+ /** 滚动锁,默认 true (zag 原名 preventScroll)。 */
24
+ scrollLock?: boolean;
25
+ /** 模态遮蔽,默认 true。 */
26
+ modal?: boolean;
27
+ /** 角色,默认 dialog。 */
28
+ role?: "dialog" | "alertdialog";
29
+ /** 初始焦点策略;对象形式提供 selector,由 core 翻译成 zag 的 initialFocusEl。 */
30
+ initialFocus?: "autofocus" | "first" | "none" | {
31
+ selector: string;
32
+ };
33
+ /** 关闭回焦策略;对应 zag 的 restoreFocus + finalFocusEl。 */
34
+ returnFocus?: "previous" | "none" | {
35
+ selector: string;
36
+ };
37
+ /** 状态变化回调;zag 原生 onOpenChange。 */
38
+ onOpenChange?: (e: {
39
+ open: boolean;
40
+ }) => void;
41
+ /**
42
+ * 禁用 trigger:禁用后点击/键盘都不打开。
43
+ * adapter 层声明式属性(落到原生 button[disabled])——zag dialog 无此 context,不进 machine。
44
+ */
45
+ disabled?: boolean;
46
+ }
47
+ /**
48
+ * 直接 re-export zag 的 dialog machine 与 connect —— 不再包一层。
49
+ * machine 由各框架 useMachine 消费;connect 把 service 接成 prop-getter。
50
+ * 用 re-export 而非 `const x = dialog.x` 以保留原始可移植类型 (避免 TS2742)。
51
+ */
52
+ export { machine as dialogMachine, connect } from "@zag-js/dialog";
53
+ /** rebrand zag 的 DialogApi 类型对外。 */
54
+ export type { Api as QwDialogApi } from "@zag-js/dialog";
55
+ /**
56
+ * 把 QwDialogProps 转成 zag dialog machine 的 context (默认值收口 + 命名 rebrand)。
57
+ * 用法:`useMachine(dialogMachine, createDialogProps(props))`。
58
+ */
59
+ export declare function createDialogProps(props?: QwDialogProps): Partial<ZagDialogProps>;
@@ -1,56 +1 @@
1
- import { Props } from '@zag-js/dialog';
2
- export { Api as QwDialogApi, connect, machine as dialogMachine } from '@zag-js/dialog';
3
-
4
- /**
5
- * QwDialogProps — Dialog 的用户输入。
6
- *
7
- * 对 zag.js 输入做两件事 (§06):
8
- * 1. 默认值收口:closeOnEsc / closeOnOutside / scrollLock 默认全 true;
9
- * 2. 命名 rebrand:把 zag 的 closeOnInteractOutside / preventScroll 改成业务易懂命名;
10
- * 3. 业务 props 透出:onOpenChange / initialFocus / returnFocus 在 React/Vue 同名。
11
- *
12
- * 业务方只需 import 本类型,不需要直接 import `@zag-js/*`。
13
- */
14
- interface QwDialogProps {
15
- /** 唯一 id 前缀;不传时由 zag 安全生成 (SSR/CSR 一致)。 */
16
- id?: string;
17
- /** 受控开关。 */
18
- open?: boolean;
19
- /** 非受控初值。 */
20
- defaultOpen?: boolean;
21
- /** ESC 关闭,默认 true (zag 原名 closeOnEscape)。 */
22
- closeOnEsc?: boolean;
23
- /** 点击 backdrop 关闭,默认 true (zag 原名 closeOnInteractOutside)。 */
24
- closeOnOutside?: boolean;
25
- /** 滚动锁,默认 true (zag 原名 preventScroll)。 */
26
- scrollLock?: boolean;
27
- /** 模态遮蔽,默认 true。 */
28
- modal?: boolean;
29
- /** 角色,默认 dialog。 */
30
- role?: "dialog" | "alertdialog";
31
- /** 初始焦点策略;对象形式提供 selector,由 core 翻译成 zag 的 initialFocusEl。 */
32
- initialFocus?: "autofocus" | "first" | "none" | {
33
- selector: string;
34
- };
35
- /** 关闭回焦策略;对应 zag 的 restoreFocus + finalFocusEl。 */
36
- returnFocus?: "previous" | "none" | {
37
- selector: string;
38
- };
39
- /** 状态变化回调;zag 原生 onOpenChange。 */
40
- onOpenChange?: (e: {
41
- open: boolean;
42
- }) => void;
43
- /**
44
- * 禁用 trigger:禁用后点击/键盘都不打开。
45
- * adapter 层声明式属性(落到原生 button[disabled])——zag dialog 无此 context,不进 machine。
46
- */
47
- disabled?: boolean;
48
- }
49
-
50
- /**
51
- * 把 QwDialogProps 转成 zag dialog machine 的 context (默认值收口 + 命名 rebrand)。
52
- * 用法:`useMachine(dialogMachine, createDialogProps(props))`。
53
- */
54
- declare function createDialogProps(props?: QwDialogProps): Partial<Props>;
55
-
56
- export { type QwDialogProps, createDialogProps };
1
+ export * from "./dialog.js";