@qw-ui/core 0.1.0 → 0.2.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 (61) 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 +24 -4
  30. package/dist/index.js +13 -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/textarea/index.d.ts +1 -0
  48. package/dist/textarea/index.js +231 -0
  49. package/dist/textarea/index.js.map +1 -0
  50. package/dist/textarea/textarea.d.ts +113 -0
  51. package/dist/toast/index.d.ts +1 -0
  52. package/dist/toast/index.js +44 -0
  53. package/dist/toast/index.js.map +1 -0
  54. package/dist/toast/toast.d.ts +52 -0
  55. package/dist/top-bar/index.d.ts +1 -0
  56. package/dist/top-bar/index.js +43 -0
  57. package/dist/top-bar/index.js.map +1 -0
  58. package/dist/top-bar/top-bar.d.ts +86 -0
  59. package/dist/visual-manifest.d.ts +142 -0
  60. package/package.json +67 -6
  61. package/dist/index.js.map +0 -1
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Top Bar 契约 — 原型 A(无状态),core 无 machine,只承载双栈共享的类型契约。
3
+ * React/Vue 适配层从这里 import 类型与 createTopBarProps,不允许各自再定义一份。
4
+ *
5
+ * Top Bar 是内容面板的头部组件,通过 `variant` prop 选择三种互斥结构形式:
6
+ * basic(标题 + 收起 icon)、tab(tablist + 收起 icon)、extended(返回箭头 + 自定义中间 + 关闭 icon)。
7
+ * Tab 切换复用 @qw-ui/core/tabs。
8
+ *
9
+ * 枚举以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死词表。
10
+ */
11
+ /** variant 全集:basic 基础 / tab 标签页 / extended 拓展。 */
12
+ export declare const TOPBAR_VARIANTS: readonly ["basic", "tab", "extended"];
13
+ /** 结构形式。 */
14
+ export type TopBarVariant = (typeof TOPBAR_VARIANTS)[number];
15
+ /**
16
+ * TopBarItem — Tab 项契约,与 @qw-ui/react/tabs 和 @qw-ui/vue/tabs 的 TabItem 同构。
17
+ * core 定义最小形状(label/content 为 string),适配层各自扩展为 ReactNode / slot。
18
+ */
19
+ export interface TopBarItem {
20
+ /** 选项唯一值。 */
21
+ value: string;
22
+ /** 选项标签文本。 */
23
+ label: string;
24
+ /** 选项内容(简单文本)。 */
25
+ content?: string;
26
+ /** 禁用该选项:跳过键盘漫游、不可点击。 */
27
+ disabled?: boolean;
28
+ }
29
+ /**
30
+ * QwTopBarProps — 双栈共享的行为 + 视觉契约。
31
+ * Tab 相关 props(items/value/defaultValue/onValueChange)透传给 @qw-ui/core/tabs。
32
+ * variant 为必填,其余 props 按 variant 条件可选(flat interface,非 discriminated union)。
33
+ */
34
+ export interface QwTopBarProps {
35
+ /** 结构形式(必填)。 */
36
+ variant: TopBarVariant;
37
+ /** 标题名称(basic 专用)。 */
38
+ title?: string;
39
+ /** Tab 切换模式的数据项。 */
40
+ items?: TopBarItem[];
41
+ /** Tab 非受控初值。 */
42
+ defaultValue?: string | null;
43
+ /** Tab 受控当前项。 */
44
+ value?: string | null;
45
+ /** Tab 选中项变化回调。 */
46
+ onValueChange?: (e: {
47
+ value: string;
48
+ }) => void;
49
+ /** 收起 icon 点击回调(关闭内容面板)。 */
50
+ onCollapse?: () => void;
51
+ /** 收起 icon 的 aria-label,默认「收起」。 */
52
+ collapseLabel?: string;
53
+ /** 返回箭头点击回调(面板内导航回退)。 */
54
+ onBack?: () => void;
55
+ /** 返回箭头的 aria-label,默认「返回」。 */
56
+ backLabel?: string;
57
+ /** 关闭 icon 点击回调(关闭面板)。 */
58
+ onClose?: () => void;
59
+ /** 关闭 icon 的 aria-label,默认「关闭」。 */
60
+ closeLabel?: string;
61
+ }
62
+ /**
63
+ * ResolvedTopBarProps — createTopBarProps 返回值,适配层消费此对象渲染。
64
+ */
65
+ export interface ResolvedTopBarProps {
66
+ variant: TopBarVariant;
67
+ title: string | undefined;
68
+ items: TopBarItem[] | undefined;
69
+ defaultValue: string | null;
70
+ value: string | null;
71
+ onValueChange: ((e: {
72
+ value: string;
73
+ }) => void) | undefined;
74
+ onCollapse: (() => void) | undefined;
75
+ collapseLabel: string;
76
+ onBack: (() => void) | undefined;
77
+ backLabel: string;
78
+ onClose: (() => void) | undefined;
79
+ closeLabel: string;
80
+ hasTabs: boolean;
81
+ }
82
+ /**
83
+ * 把 QwTopBarProps 收口默认值,返回适配层配置对象。
84
+ * 不进 machine(原型 A)。纯函数,SSR-safe。
85
+ */
86
+ export declare function createTopBarProps(props: QwTopBarProps): ResolvedTopBarProps;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * 组件视觉契约清单类型 — workspace 内部使用(不进 npm 产物、不进 core 公开 API)。
3
+ *
4
+ * 每个组件在 `src/<slug>/docs/visual.ts` 维护一份 `QwComponentVisualMeta`,
5
+ * 它是确定性视觉契约的唯一事实源:React/Vue 共用同一份场景声明,
6
+ * `tools/visual-check` 按清单展开矩阵并在真实浏览器内做运行时自比较
7
+ *(状态差异 / token 绑定 / 主题切换 / 双栈样式 parity / 几何关系)。
8
+ *
9
+ * Demo 层通过 `data-visual-target="<target>"` 标记契约锚点(不进组件公共 API)。
10
+ *
11
+ * 非目标:禁止落盘任何截图或 computed-style 指纹制品作为跨运行基线。
12
+ */
13
+ /** 受支持的视觉状态词表(封闭集合;新增状态须改此类型并更新共享 driver)。 */
14
+ export type QwVisualState = "default" | "hover" | "active" | "focus-visible" | "disabled" | "loading" | "open" | "closed" | "selected" | "checked" | "expanded";
15
+ /** 主题轴。 */
16
+ export type QwVisualTheme = "light" | "dark";
17
+ /** 框架轴。 */
18
+ export type QwVisualFramework = "react" | "vue";
19
+ /** 视口配置(预留扩展;默认 mobile = 390×844 @2x,与 G3 一致)。 */
20
+ export type QwVisualViewport = "mobile";
21
+ /**
22
+ * 语义视觉通道——状态变化的抽象分组,不是 CSS 属性字面量。
23
+ * 状态差异断言要求 delta 至少命中该状态通道词表中的一项。
24
+ */
25
+ export type QwVisualChannel = "fill" | "content" | "edge" | "opacity" | "transform" | "cursor" | "presence";
26
+ /** 声明式前置动作(进入 open/selected 等状态)。 */
27
+ export type QwVisualAction = {
28
+ action: "click";
29
+ target: string;
30
+ } | {
31
+ action: "press";
32
+ target: string;
33
+ keys: string;
34
+ } | {
35
+ action: "tab-to";
36
+ target: string;
37
+ } | {
38
+ action: "click-role";
39
+ role: string;
40
+ name?: string;
41
+ index?: number;
42
+ };
43
+ /**
44
+ * 几何关系谓词——只表达相对关系,不写死绝对像素。
45
+ * 封闭小词表;按需求增长,不预设。
46
+ */
47
+ export type QwGeometryRelation = {
48
+ rel: "contains";
49
+ outer: string;
50
+ inner: string;
51
+ } | {
52
+ rel: "centered";
53
+ item: string;
54
+ within: string;
55
+ axis?: "block" | "inline";
56
+ } | {
57
+ rel: "monotonic";
58
+ axis: "block-size" | "inline-size";
59
+ targets: string[];
60
+ } | {
61
+ rel: "equal";
62
+ axis: "block-size" | "inline-size";
63
+ targets: string[];
64
+ tolerancePx?: number;
65
+ } | {
66
+ rel: "token-size";
67
+ target: string;
68
+ axis: "block-size" | "inline-size";
69
+ /** T3 token 短名,如 "size-control-height-m";运行时从 tokens.json 解析 */
70
+ token: string;
71
+ };
72
+ /** 场景级可选强契约;省略时仍享有零声明基础保障。 */
73
+ export interface QwVisualExpect {
74
+ /** 覆盖库级默认通道(极少用,如某状态刻意不改 fill)。 */
75
+ channels?: Partial<Record<QwVisualState, QwVisualChannel[]>>;
76
+ /**
77
+ * 强契约:状态下某属性必须解析为指定 T3 token 的值。
78
+ * key = "state.property"(state 可省略,默认 default),value = token 短名(如 "border-focus")。
79
+ */
80
+ tokens?: Record<string, string>;
81
+ /** 几何关系谓词。 */
82
+ geometry?: QwGeometryRelation[];
83
+ /** 该场景颜色随主题不变,显式豁免主题 delta 检查。 */
84
+ themeInvariant?: boolean;
85
+ /** 动画契约。 */
86
+ motion?: {
87
+ /** data-visual-target 或 data-part 选择器别名;解析为动画宿主 */
88
+ animatedPart: string;
89
+ respectsReducedMotion?: boolean;
90
+ };
91
+ /** Icon 等:双栈 SVG 结构归一化哈希一致。 */
92
+ svgParity?: boolean;
93
+ /** target 允许溢出 demo 画布(Dialog backdrop / Toast overlay 等)。 */
94
+ allowOverflow?: boolean;
95
+ }
96
+ /** 单个视觉场景。 */
97
+ export interface QwVisualScenario {
98
+ /** kebab-case 场景名,进入 case id。 */
99
+ name: string;
100
+ /** 引用 demos.ts 中的 demo id。 */
101
+ demo: string;
102
+ /** 对应 demo 中 `data-visual-target` 的值。 */
103
+ target: string;
104
+ /** 本场景要验证的视觉状态列表。 */
105
+ states: QwVisualState[];
106
+ /** 主题列表,默认 light + dark(主题 delta 使用;parity 仍跑双主题)。 */
107
+ themes?: QwVisualTheme[];
108
+ /** 框架列表,默认 react + vue。 */
109
+ frameworks?: QwVisualFramework[];
110
+ /** 进入特定状态前的动作序列。 */
111
+ setup?: QwVisualAction[];
112
+ /** 视口配置,默认 mobile。 */
113
+ viewport?: QwVisualViewport;
114
+ /** 可选强契约;零声明场景仍有基础保障。 */
115
+ expect?: QwVisualExpect;
116
+ }
117
+ /** 组件视觉契约元数据。 */
118
+ export interface QwComponentVisualMeta {
119
+ slug: string;
120
+ scenarios: QwVisualScenario[];
121
+ /** 软预算提示阈值(契约 case 数);超出时 verify 警告但不阻塞。 */
122
+ budget?: number;
123
+ }
124
+ /** 默认主题轴。 */
125
+ export declare const QW_VISUAL_DEFAULT_THEMES: readonly QwVisualTheme[];
126
+ /** 默认框架轴。 */
127
+ export declare const QW_VISUAL_DEFAULT_FRAMEWORKS: readonly QwVisualFramework[];
128
+ /** 软预算默认值(契约 case 数)。 */
129
+ export declare const QW_VISUAL_DEFAULT_BUDGET = 120;
130
+ /**
131
+ * 库级默认:状态 → 期望变化的视觉通道。
132
+ * 通道命中即可(OR),不要求全部命中。
133
+ */
134
+ export declare const QW_STATE_CHANNELS: Readonly<Record<Exclude<QwVisualState, "default" | "closed">, readonly QwVisualChannel[]>>;
135
+ /** Case id:`{slug}-{scenario}--{state}--{theme}-{framework}` */
136
+ export declare function qwVisualCaseId(slug: string, scenario: string, state: QwVisualState, theme: QwVisualTheme, framework: QwVisualFramework): string;
137
+ /** @deprecated 使用 qwVisualCaseId;保留别名以兼容过渡期引用。 */
138
+ export declare const qwVisualSnapshotName: typeof qwVisualCaseId;
139
+ /** 展开场景为契约 case id 列表。 */
140
+ export declare function expandVisualCases(meta: QwComponentVisualMeta): string[];
141
+ /** @deprecated 使用 expandVisualCases。 */
142
+ export declare const expandVisualSnapshots: typeof expandVisualCases;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qw-ui/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "L2 · Headless Core — zag.js machine 薄包装,纯 TS / SSR-safe,零样式。",
5
5
  "license": "MIT",
6
6
  "author": "qw-ui contributors",
@@ -35,12 +35,63 @@
35
35
  "./tabs": {
36
36
  "types": "./dist/tabs/index.d.ts",
37
37
  "import": "./dist/tabs/index.js"
38
+ },
39
+ "./toast": {
40
+ "types": "./dist/toast/index.d.ts",
41
+ "import": "./dist/toast/index.js"
42
+ },
43
+ "./button": {
44
+ "types": "./dist/button/index.d.ts",
45
+ "import": "./dist/button/index.js"
46
+ },
47
+ "./empty": {
48
+ "types": "./dist/empty/index.d.ts",
49
+ "import": "./dist/empty/index.js"
50
+ },
51
+ "./divider": {
52
+ "types": "./dist/divider/index.d.ts",
53
+ "import": "./dist/divider/index.js"
54
+ },
55
+ "./loading": {
56
+ "types": "./dist/loading/index.d.ts",
57
+ "import": "./dist/loading/index.js"
58
+ },
59
+ "./skeleton": {
60
+ "types": "./dist/skeleton/index.d.ts",
61
+ "import": "./dist/skeleton/index.js"
62
+ },
63
+ "./top-bar": {
64
+ "types": "./dist/top-bar/index.d.ts",
65
+ "import": "./dist/top-bar/index.js"
66
+ },
67
+ "./icon": {
68
+ "types": "./dist/icon/index.d.ts",
69
+ "import": "./dist/icon/index.js"
70
+ },
71
+ "./search-bar": {
72
+ "types": "./dist/search-bar/index.d.ts",
73
+ "import": "./dist/search-bar/index.js"
74
+ },
75
+ "./avatar": {
76
+ "types": "./dist/avatar/index.d.ts",
77
+ "import": "./dist/avatar/index.js"
78
+ },
79
+ "./image": {
80
+ "types": "./dist/image/index.d.ts",
81
+ "import": "./dist/image/index.js"
82
+ },
83
+ "./textarea": {
84
+ "types": "./dist/textarea/index.d.ts",
85
+ "import": "./dist/textarea/index.js"
38
86
  }
39
87
  },
40
88
  "sideEffects": false,
41
89
  "dependencies": {
90
+ "@zag-js/core": "1.42.0",
42
91
  "@zag-js/dialog": "^1.42.0",
43
- "@zag-js/tabs": "^1.42.0"
92
+ "@zag-js/tabs": "^1.42.0",
93
+ "@zag-js/utils": "1.42.0",
94
+ "@qw-ui/icons": "^0.2.0"
44
95
  },
45
96
  "devDependencies": {
46
97
  "@microsoft/api-extractor": "^7.58.9",
@@ -50,11 +101,12 @@
50
101
  "@zag-js/vanilla": "^1.42.0",
51
102
  "jsdom": "^29.1.1",
52
103
  "size-limit": "^12.1.0",
53
- "tsup": "^8.5.1",
104
+ "tsdown": "^0.22.4",
54
105
  "typescript": "^6.0.3",
106
+ "unrun": "^0.3.1",
55
107
  "vitest": "^4.1.9",
56
- "@qw-ui/eslint-config": "0.0.0",
57
- "@qw-ui/tsconfig": "0.0.0"
108
+ "@qw-ui/eslint-config": "0.0.1",
109
+ "@qw-ui/tsconfig": "0.0.1"
58
110
  },
59
111
  "size-limit": [
60
112
  {
@@ -70,6 +122,14 @@
70
122
  "ignore": [
71
123
  "@zag-js/tabs"
72
124
  ]
125
+ },
126
+ {
127
+ "path": "dist/top-bar/index.js",
128
+ "limit": "4 kB"
129
+ },
130
+ {
131
+ "path": "dist/toast/index.js",
132
+ "limit": "2 kB"
73
133
  }
74
134
  ],
75
135
  "publishConfig": {
@@ -77,9 +137,10 @@
77
137
  "registry": "https://registry.npmjs.org/"
78
138
  },
79
139
  "scripts": {
80
- "build": "tsup",
140
+ "build": "tsdown && tsgo -p tsconfig.build.json",
81
141
  "test": "vitest run",
82
142
  "lint": "eslint .",
143
+ "typecheck": "tsgo --noEmit -p tsconfig.build.json",
83
144
  "size": "size-limit",
84
145
  "api": "api-extractor run --local",
85
146
  "clean": "rm -rf dist .turbo etc/*.api.json temp"
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dialog/index.ts","../src/tabs/index.ts"],"names":[],"mappings":";;;;AAwDO,SAAS,iBAAA,CAAkB,KAAA,GAAuB,EAAC,EAA4B;AACpF,EAAA,MAAM,GAAA,GAA+B;AAAA,IACnC,IAAI,KAAA,CAAM,EAAA;AAAA,IACV,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,aAAa,KAAA,CAAM,WAAA;AAAA,IACnB,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,aAAA,EAAe,MAAM,UAAA,KAAe,KAAA;AAAA,IACpC,sBAAA,EAAwB,MAAM,cAAA,KAAmB,KAAA;AAAA,IACjD,aAAA,EAAe,MAAM,UAAA,KAAe;AAAA,GACtC;AAEA,EAAA,IAAI,KAAA,CAAM,KAAA,KAAU,MAAA,EAAW,GAAA,CAAI,QAAQ,KAAA,CAAM,KAAA;AAEjD,EAAA,IAAI,MAAM,YAAA,EAAc;AACtB,IAAA,MAAM,KAAK,KAAA,CAAM,YAAA;AACjB,IAAA,GAAA,CAAI,YAAA,GAAe,CAAC,CAAA,KAAyB,EAAA,CAAG,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,CAAA;AAAA,EAClE;AAGA,EAAA,IAAI,OAAO,KAAA,CAAM,YAAA,KAAiB,QAAA,EAAU;AAC1C,IAAA,MAAM,GAAA,GAAM,MAAM,YAAA,CAAa,QAAA;AAC/B,IAAA,GAAA,CAAI,cAAA,GAAiB,MAAM,QAAA,CAAS,aAAA,CAA2B,GAAG,CAAA;AAAA,EACpE;AAGA,EAAA,IAAI,OAAO,KAAA,CAAM,WAAA,KAAgB,QAAA,EAAU;AACzC,IAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,QAAA;AAC9B,IAAA,GAAA,CAAI,YAAA,GAAe,MAAM,QAAA,CAAS,aAAA,CAA2B,GAAG,CAAA;AAAA,EAClE,CAAA,MAAA,IAAW,KAAA,CAAM,WAAA,KAAgB,MAAA,EAAQ;AACvC,IAAA,GAAA,CAAI,YAAA,GAAe,KAAA;AAAA,EACrB;AAEA,EAAA,OAAO,GAAA;AACT;AClDO,SAAS,eAAA,CAAgB,KAAA,GAAqB,EAAC,EAA0B;AAC9E,EAAA,MAAM,GAAA,GAA6B;AAAA,IACjC,IAAI,KAAA,CAAM,EAAA;AAAA,IACV,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,cAAc,KAAA,CAAM,YAAA;AAAA,IACpB,aAAa,KAAA,CAAM,WAAA;AAAA,IACnB,gBAAgB,KAAA,CAAM,cAAA;AAAA,IACtB,SAAA,EAAW,MAAM,IAAA,KAAS;AAAA,GAC5B;AAEA,EAAA,IAAI,MAAM,aAAA,EAAe;AACvB,IAAA,MAAM,KAAK,KAAA,CAAM,aAAA;AACjB,IAAA,GAAA,CAAI,aAAA,GAAgB,CAAC,CAAA,KAA0B,EAAA,CAAG,EAAE,KAAA,EAAO,CAAA,CAAE,OAAO,CAAA;AAAA,EACtE;AAEA,EAAA,OAAO,GAAA;AACT","file":"index.js","sourcesContent":["import type { Props as ZagDialogProps, OpenChangeDetails } from \"@zag-js/dialog\";\n\n/**\n * QwDialogProps — Dialog 的用户输入。\n *\n * 对 zag.js 输入做两件事 (§06):\n * 1. 默认值收口:closeOnEsc / closeOnOutside / scrollLock 默认全 true;\n * 2. 命名 rebrand:把 zag 的 closeOnInteractOutside / preventScroll 改成业务易懂命名;\n * 3. 业务 props 透出:onOpenChange / initialFocus / returnFocus 在 React/Vue 同名。\n *\n * 业务方只需 import 本类型,不需要直接 import `@zag-js/*`。\n */\nexport interface QwDialogProps {\n /** 唯一 id 前缀;不传时由 zag 安全生成 (SSR/CSR 一致)。 */\n id?: string;\n /** 受控开关。 */\n open?: boolean;\n /** 非受控初值。 */\n defaultOpen?: boolean;\n /** ESC 关闭,默认 true (zag 原名 closeOnEscape)。 */\n closeOnEsc?: boolean;\n /** 点击 backdrop 关闭,默认 true (zag 原名 closeOnInteractOutside)。 */\n closeOnOutside?: boolean;\n /** 滚动锁,默认 true (zag 原名 preventScroll)。 */\n scrollLock?: boolean;\n /** 模态遮蔽,默认 true。 */\n modal?: boolean;\n /** 角色,默认 dialog。 */\n role?: \"dialog\" | \"alertdialog\";\n /** 初始焦点策略;对象形式提供 selector,由 core 翻译成 zag 的 initialFocusEl。 */\n initialFocus?: \"autofocus\" | \"first\" | \"none\" | { selector: string };\n /** 关闭回焦策略;对应 zag 的 restoreFocus + finalFocusEl。 */\n returnFocus?: \"previous\" | \"none\" | { selector: string };\n /** 状态变化回调;zag 原生 onOpenChange。 */\n onOpenChange?: (e: { open: boolean }) => void;\n /**\n * 禁用 trigger:禁用后点击/键盘都不打开。\n * adapter 层声明式属性(落到原生 button[disabled])——zag dialog 无此 context,不进 machine。\n */\n disabled?: boolean;\n}\n\n/**\n * 直接 re-export zag 的 dialog machine 与 connect —— 不再包一层。\n * machine 由各框架 useMachine 消费;connect 把 service 接成 prop-getter。\n * 用 re-export 而非 `const x = dialog.x` 以保留原始可移植类型 (避免 TS2742)。\n */\nexport { machine as dialogMachine, connect } from \"@zag-js/dialog\";\n\n/** rebrand zag 的 DialogApi 类型对外。 */\nexport type { Api as QwDialogApi } from \"@zag-js/dialog\";\n\n/**\n * 把 QwDialogProps 转成 zag dialog machine 的 context (默认值收口 + 命名 rebrand)。\n * 用法:`useMachine(dialogMachine, createDialogProps(props))`。\n */\nexport function createDialogProps(props: QwDialogProps = {}): Partial<ZagDialogProps> {\n const ctx: Partial<ZagDialogProps> = {\n id: props.id,\n open: props.open,\n defaultOpen: props.defaultOpen,\n role: props.role,\n closeOnEscape: props.closeOnEsc !== false,\n closeOnInteractOutside: props.closeOnOutside !== false,\n preventScroll: props.scrollLock !== false,\n };\n\n if (props.modal !== undefined) ctx.modal = props.modal;\n\n if (props.onOpenChange) {\n const cb = props.onOpenChange;\n ctx.onOpenChange = (d: OpenChangeDetails) => cb({ open: d.open });\n }\n\n // initialFocus: { selector } → initialFocusEl 回调;'none' 关闭自动聚焦\n if (typeof props.initialFocus === \"object\") {\n const sel = props.initialFocus.selector;\n ctx.initialFocusEl = () => document.querySelector<HTMLElement>(sel);\n }\n\n // returnFocus: { selector } → finalFocusEl;'none' → restoreFocus=false\n if (typeof props.returnFocus === \"object\") {\n const sel = props.returnFocus.selector;\n ctx.finalFocusEl = () => document.querySelector<HTMLElement>(sel);\n } else if (props.returnFocus === \"none\") {\n ctx.restoreFocus = false;\n }\n\n return ctx;\n}\n","import type { Props as ZagTabsProps, ValueChangeDetails } from \"@zag-js/tabs\";\n\n/**\n * QwTabsProps — Tabs 的用户输入。对 zag.js 输入做默认值收口 + 命名 rebrand:\n * - loop(默认 true)→ zag loopFocus;\n * - value / defaultValue / orientation / activationMode 透传;\n * - onValueChange 适配 zag details。\n * 业务方只 import 本类型,不直接 import `@zag-js/*`。\n */\nexport interface QwTabsProps {\n /** 唯一 id 前缀;不传由适配层生成 (SSR/CSR 一致)。 */\n id?: string;\n /** 受控当前项。 */\n value?: string | null;\n /** 非受控初值。 */\n defaultValue?: string | null;\n /** 方向,默认 horizontal。 */\n orientation?: \"horizontal\" | \"vertical\";\n /** 激活模式,默认 automatic(聚焦即激活)。 */\n activationMode?: \"manual\" | \"automatic\";\n /** 方向键首尾循环,默认 true (zag 原名 loopFocus)。 */\n loop?: boolean;\n /** 选中项变化回调;zag 原生 onValueChange。 */\n onValueChange?: (e: { value: string }) => void;\n}\n\n/**\n * 直接 re-export zag tabs 的 machine 与 connect —— 不包一层。\n * 用 re-export 保留原始可移植类型 (避免 TS2742)。\n */\nexport { machine as tabsMachine, connect } from \"@zag-js/tabs\";\n\n/** rebrand zag 的 TabsApi 类型对外。 */\nexport type { Api as QwTabsApi } from \"@zag-js/tabs\";\n\n/**\n * 把 QwTabsProps 转成 zag tabs machine 的 props (默认值收口 + 命名 rebrand)。\n * 用法:`useMachine(tabsMachine, createTabsProps(props))`。\n */\nexport function createTabsProps(props: QwTabsProps = {}): Partial<ZagTabsProps> {\n const ctx: Partial<ZagTabsProps> = {\n id: props.id,\n value: props.value,\n defaultValue: props.defaultValue,\n orientation: props.orientation,\n activationMode: props.activationMode,\n loopFocus: props.loop !== false,\n };\n\n if (props.onValueChange) {\n const cb = props.onValueChange;\n ctx.onValueChange = (d: ValueChangeDetails) => cb({ value: d.value });\n }\n\n return ctx;\n}\n"]}