@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,252 @@
1
+ import { createMachine } from "@zag-js/core";
2
+ import { compact } from "@zag-js/utils";
3
+ //#region src/search-bar/search-bar.ts
4
+ /**
5
+ * 解析 clearable 配置为统一对象。
6
+ */
7
+ function normalizeClearable(clearable) {
8
+ if (clearable === false) return { showWhen: "never" };
9
+ if (clearable === true || clearable == null) return { showWhen: "non-empty" };
10
+ return { showWhen: clearable.showWhen ?? "non-empty" };
11
+ }
12
+ /**
13
+ * SearchBar zag.js machine。
14
+ * 所有交互逻辑唯一来源:value、focus、clear、action、keyboard。
15
+ */
16
+ const machine = createMachine({
17
+ props({ props }) {
18
+ return {
19
+ defaultValue: "",
20
+ disabled: false,
21
+ readOnly: false,
22
+ ...props
23
+ };
24
+ },
25
+ initialState() {
26
+ return "idle";
27
+ },
28
+ context({ bindable, prop }) {
29
+ return {
30
+ value: bindable(() => {
31
+ const controlledValue = prop("value");
32
+ return {
33
+ defaultValue: prop("defaultValue") ?? "",
34
+ ...controlledValue !== void 0 ? { value: controlledValue } : {},
35
+ onChange(value, prev) {
36
+ if (value !== prev) prop("onChange")?.(value);
37
+ }
38
+ };
39
+ }),
40
+ focused: bindable(() => ({ defaultValue: false }))
41
+ };
42
+ },
43
+ computed: {
44
+ clearableConfig({ prop }) {
45
+ return normalizeClearable(prop("clearable"));
46
+ },
47
+ showClear({ context, computed }) {
48
+ const cfg = computed("clearableConfig");
49
+ if (cfg.showWhen === "always") return true;
50
+ if (cfg.showWhen === "never") return false;
51
+ if (cfg.showWhen === "focus") return context.get("focused");
52
+ return context.get("value").length > 0;
53
+ }
54
+ },
55
+ watch({ track, action, prop, context }) {
56
+ track([() => prop("value")], () => {
57
+ const external = prop("value");
58
+ if (external !== void 0 && external !== context.get("value")) action(["setValue"]);
59
+ });
60
+ },
61
+ states: { idle: { on: {
62
+ "VALUE.SET": { actions: ["setValue"] },
63
+ "VALUE.CLEAR": { actions: ["clearValue", "invokeOnClear"] },
64
+ "FOCUS.SET": { actions: ["setFocused"] },
65
+ SEARCH: { actions: ["invokeOnSearch"] },
66
+ CANCEL: { actions: ["invokeOnCancel"] }
67
+ } } },
68
+ implementations: { actions: {
69
+ setValue({ context, event, prop }) {
70
+ if (event.type === "VALUE.SET") {
71
+ const maxLength = prop("maxLength") ?? 0;
72
+ const current = context.get("value");
73
+ let next = event.value;
74
+ if (maxLength > 0 && next.length > maxLength) next = current;
75
+ context.set("value", next);
76
+ }
77
+ },
78
+ clearValue({ context }) {
79
+ context.set("value", "");
80
+ },
81
+ setFocused({ context, event, prop }) {
82
+ if (event.type === "FOCUS.SET") {
83
+ const next = event.focused;
84
+ const prev = context.get("focused");
85
+ context.set("focused", next);
86
+ if (next && !prev) prop("onFocus")?.();
87
+ if (!next && prev) prop("onBlur")?.();
88
+ }
89
+ },
90
+ invokeOnSearch({ context, prop }) {
91
+ prop("onSearch")?.(context.get("value"));
92
+ },
93
+ invokeOnClear({ prop }) {
94
+ prop("onClear")?.();
95
+ },
96
+ invokeOnCancel({ context, prop, event }) {
97
+ const config = event.src === "prefix" ? prop("prefix") : prop("action");
98
+ if (config?.type === "cancel" && config.clearOnCancel && !prop("readOnly")) context.set("value", "");
99
+ prop("onCancel")?.();
100
+ },
101
+ invokeOnFocus() {},
102
+ invokeOnBlur() {}
103
+ } }
104
+ });
105
+ /**
106
+ * connect:把 service 接成业务友好的 prop-getter。
107
+ * 适配层只需调用 connect(service, normalizeProps)。
108
+ */
109
+ function connect(service, normalizeProps) {
110
+ const { context, computed, prop, send } = service;
111
+ const value = context.get("value");
112
+ const focused = context.get("focused");
113
+ const showClear = computed("showClear");
114
+ const disabled = !!prop("disabled");
115
+ const readOnly = !!prop("readOnly");
116
+ const maxLength = prop("maxLength");
117
+ const prefix = prop("prefix");
118
+ const action = prop("action");
119
+ return {
120
+ value,
121
+ focused,
122
+ showClear,
123
+ clear() {
124
+ send({ type: "VALUE.CLEAR" });
125
+ },
126
+ search() {
127
+ send({ type: "SEARCH" });
128
+ },
129
+ getRootProps() {
130
+ return normalizeProps.element(compact({
131
+ "data-scope": "search-bar",
132
+ "data-part": "root",
133
+ "data-focused": focused ? "true" : void 0,
134
+ "data-disabled": disabled ? "true" : void 0,
135
+ "data-readonly": readOnly ? "true" : void 0
136
+ }));
137
+ },
138
+ getFieldProps() {
139
+ return normalizeProps.element(compact({
140
+ "data-scope": "search-bar",
141
+ "data-part": "field"
142
+ }));
143
+ },
144
+ getInputProps() {
145
+ return normalizeProps.input(compact({
146
+ "data-scope": "search-bar",
147
+ "data-part": "input",
148
+ type: "search",
149
+ role: "searchbox",
150
+ value,
151
+ placeholder: prop("placeholder"),
152
+ disabled,
153
+ readOnly,
154
+ maxLength: maxLength && maxLength > 0 ? maxLength : void 0,
155
+ "aria-disabled": disabled ? "true" : void 0,
156
+ "aria-readonly": readOnly ? "true" : void 0,
157
+ onFocus() {
158
+ send({
159
+ type: "FOCUS.SET",
160
+ focused: true
161
+ });
162
+ },
163
+ onBlur() {
164
+ send({
165
+ type: "FOCUS.SET",
166
+ focused: false
167
+ });
168
+ },
169
+ onChange(event) {
170
+ const next = event.target.value;
171
+ send({
172
+ type: "VALUE.SET",
173
+ value: next
174
+ });
175
+ },
176
+ onKeyDown(event) {
177
+ if (event.key === "Enter") send({ type: "SEARCH" });
178
+ }
179
+ }));
180
+ },
181
+ getIconProps() {
182
+ return normalizeProps.element(compact({
183
+ "data-scope": "search-bar",
184
+ "data-part": "icon",
185
+ "aria-hidden": "true"
186
+ }));
187
+ },
188
+ getClearButtonProps() {
189
+ return normalizeProps.button(compact({
190
+ "data-scope": "search-bar",
191
+ "data-part": "clear-button",
192
+ type: "button",
193
+ disabled: disabled || readOnly,
194
+ "aria-label": "清除搜索内容",
195
+ "aria-hidden": !showClear,
196
+ hidden: !showClear,
197
+ onClick() {
198
+ send({ type: "VALUE.CLEAR" });
199
+ }
200
+ }));
201
+ },
202
+ getPrefixButtonProps() {
203
+ return normalizeProps.button(compact({
204
+ "data-scope": "search-bar",
205
+ "data-part": "prefix-button",
206
+ type: "button",
207
+ disabled,
208
+ "aria-label": prefix?.ariaLabel,
209
+ "data-action": prefix?.type,
210
+ onClick() {
211
+ if (prefix?.type === "cancel") send({
212
+ type: "CANCEL",
213
+ src: "prefix"
214
+ });
215
+ else if (prefix?.type === "search") send({ type: "SEARCH" });
216
+ }
217
+ }));
218
+ },
219
+ getActionButtonProps() {
220
+ return normalizeProps.button(compact({
221
+ "data-scope": "search-bar",
222
+ "data-part": "action-button",
223
+ type: "button",
224
+ disabled,
225
+ "aria-label": action?.ariaLabel,
226
+ "data-action": action?.type,
227
+ onClick() {
228
+ if (action?.type === "cancel") send({
229
+ type: "CANCEL",
230
+ src: "action"
231
+ });
232
+ else if (action?.type === "search") send({ type: "SEARCH" });
233
+ }
234
+ }));
235
+ }
236
+ };
237
+ }
238
+ /**
239
+ * 把 QwSearchBarProps 转成 machine context(默认值收口)。
240
+ */
241
+ function createSearchBarProps(props = {}) {
242
+ return {
243
+ defaultValue: props.defaultValue ?? "",
244
+ disabled: props.disabled ?? false,
245
+ readOnly: props.readOnly ?? false,
246
+ ...props
247
+ };
248
+ }
249
+ //#endregion
250
+ export { connect, createSearchBarProps, machine };
251
+
252
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/search-bar/search-bar.ts"],"sourcesContent":["import { createMachine } from \"@zag-js/core\";\nimport type { MachineSchema, Service } from \"@zag-js/core\";\nimport type { PropTypes, NormalizeProps } from \"@zag-js/types\";\nimport type { JSX } from \"@zag-js/types\";\nimport { compact } from \"@zag-js/utils\";\n\n/**\n * 清除按钮显示策略。\n */\nexport type SearchBarClearable = boolean | { showWhen?: \"always\" | \"focus\" | \"non-empty\" };\n\n/**\n * 内部归一化后的显示策略(包含 `never`,表示 `clearable={false}`)。\n */\nexport type SearchBarClearableMode = \"always\" | \"focus\" | \"non-empty\" | \"never\";\n\nexport interface SearchBarClearableConfig {\n showWhen: SearchBarClearableMode;\n}\n\n/**\n * 右侧 action 按钮角色。\n */\nexport type SearchBarActionType = \"cancel\" | \"search\";\n\n/**\n * 右侧 action 按钮配置。\n */\nexport interface SearchBarAction {\n /** 按钮角色。 */\n type: SearchBarActionType;\n /** 展示内容:文案或自定义节点。 */\n content: string | unknown;\n /** 取消时是否清空输入。 */\n clearOnCancel?: boolean;\n /** 按钮可访问名称;当 content 为纯图标时必填。 */\n ariaLabel?: string;\n}\n\n/**\n * SearchBar 公共 props 契约(双栈共享)。\n */\nexport interface QwSearchBarProps {\n /** 唯一 id 前缀。 */\n id?: string;\n /** 受控值。 */\n value?: string;\n /** 非受控初始值。 */\n defaultValue?: string;\n /** 占位符。 */\n placeholder?: string;\n /** 最大字符数。 */\n maxLength?: number;\n /** 禁用态。 */\n disabled?: boolean;\n /** 只读态。 */\n readOnly?: boolean;\n /** 清除按钮配置。 */\n clearable?: SearchBarClearable;\n /** 左侧搜索图标:字符串文案或自定义节点。 */\n searchIcon?: string | unknown;\n /** 左侧按钮配置。 */\n prefix?: SearchBarAction;\n /** 右侧按钮配置。 */\n action?: SearchBarAction;\n /** 输入变化回调。 */\n onChange?: (value: string) => void;\n /** 搜索确认回调(Enter 或点击搜索按钮)。 */\n onSearch?: (value: string) => void;\n /** 清空回调。 */\n onClear?: () => void;\n /** 取消回调。 */\n onCancel?: () => void;\n /** 聚焦回调。 */\n onFocus?: () => void;\n /** 失焦回调。 */\n onBlur?: () => void;\n}\n\n/**\n * 内部 schema,用于 createMachine 类型推导。\n */\ninterface SearchBarSchema extends MachineSchema {\n props: QwSearchBarProps;\n context: {\n value: string;\n focused: boolean;\n };\n computed: {\n showClear: boolean;\n clearableConfig: SearchBarClearableConfig;\n };\n state: \"idle\";\n event:\n | { type: \"VALUE.SET\"; value: string; src?: string }\n | { type: \"VALUE.CLEAR\" }\n | { type: \"FOCUS.SET\"; focused: boolean }\n | { type: \"SEARCH\" }\n | { type: \"CANCEL\"; src?: \"prefix\" | \"action\" };\n action:\n | \"setValue\"\n | \"clearValue\"\n | \"setFocused\"\n | \"invokeOnSearch\"\n | \"invokeOnClear\"\n | \"invokeOnCancel\"\n | \"invokeOnFocus\"\n | \"invokeOnBlur\";\n}\n\n/**\n * 解析 clearable 配置为统一对象。\n */\nfunction normalizeClearable(clearable?: SearchBarClearable): SearchBarClearableConfig {\n if (clearable === false) return { showWhen: \"never\" };\n if (clearable === true || clearable == null) return { showWhen: \"non-empty\" };\n return { showWhen: clearable.showWhen ?? \"non-empty\" };\n}\n\n/**\n * SearchBar zag.js machine。\n * 所有交互逻辑唯一来源:value、focus、clear、action、keyboard。\n */\nexport const machine = createMachine<SearchBarSchema>({\n props({ props }) {\n return {\n defaultValue: \"\",\n disabled: false,\n readOnly: false,\n ...props,\n };\n },\n\n initialState() {\n return \"idle\";\n },\n\n context({ bindable, prop }) {\n return {\n value: bindable<string>(() => {\n const controlledValue = prop(\"value\");\n return {\n defaultValue: prop(\"defaultValue\") ?? \"\",\n ...(controlledValue !== undefined ? { value: controlledValue } : {}),\n onChange(value, prev) {\n if (value !== prev) {\n prop(\"onChange\")?.(value);\n }\n },\n };\n }),\n focused: bindable(() => ({\n defaultValue: false,\n })),\n };\n },\n\n computed: {\n clearableConfig({ prop }) {\n return normalizeClearable(prop(\"clearable\"));\n },\n showClear({ context, computed }) {\n const cfg = computed(\"clearableConfig\");\n if (cfg.showWhen === \"always\") return true;\n if (cfg.showWhen === \"never\") return false;\n if (cfg.showWhen === \"focus\") return context.get(\"focused\");\n return context.get(\"value\").length > 0;\n },\n },\n\n watch({ track, action, prop, context }) {\n track([() => prop(\"value\")], () => {\n const external = prop(\"value\");\n if (external !== undefined && external !== context.get(\"value\")) {\n action([\"setValue\"]);\n }\n });\n },\n\n states: {\n idle: {\n on: {\n \"VALUE.SET\": {\n actions: [\"setValue\"],\n },\n \"VALUE.CLEAR\": {\n actions: [\"clearValue\", \"invokeOnClear\"],\n },\n \"FOCUS.SET\": {\n actions: [\"setFocused\"],\n },\n SEARCH: {\n actions: [\"invokeOnSearch\"],\n },\n CANCEL: {\n actions: [\"invokeOnCancel\"],\n },\n },\n },\n },\n\n implementations: {\n actions: {\n setValue({ context, event, prop }) {\n if (event.type === \"VALUE.SET\") {\n const maxLength = prop(\"maxLength\") ?? 0;\n const current = context.get(\"value\");\n let next = event.value;\n if (maxLength > 0 && next.length > maxLength) {\n // 达到 maxLength 后阻止继续输入,保留旧值\n next = current;\n }\n context.set(\"value\", next);\n }\n },\n clearValue({ context }) {\n context.set(\"value\", \"\");\n },\n setFocused({ context, event, prop }) {\n if (event.type === \"FOCUS.SET\") {\n const next = event.focused;\n const prev = context.get(\"focused\");\n context.set(\"focused\", next);\n if (next && !prev) prop(\"onFocus\")?.();\n if (!next && prev) prop(\"onBlur\")?.();\n }\n },\n invokeOnSearch({ context, prop }) {\n prop(\"onSearch\")?.(context.get(\"value\"));\n },\n invokeOnClear({ prop }) {\n prop(\"onClear\")?.();\n },\n invokeOnCancel({ context, prop, event }) {\n const config = event.src === \"prefix\" ? prop(\"prefix\") : prop(\"action\");\n if (config?.type === \"cancel\" && config.clearOnCancel && !prop(\"readOnly\")) {\n context.set(\"value\", \"\");\n }\n prop(\"onCancel\")?.();\n },\n invokeOnFocus() {\n // focus 回调在 setFocused 中已触发\n },\n invokeOnBlur() {\n // blur 回调在 setFocused 中已触发\n },\n },\n },\n});\n\n/**\n * SearchBar api 类型(由 connect 返回)。\n */\nexport interface SearchBarApi<T extends PropTypes = PropTypes> {\n /** 当前输入值。 */\n value: string;\n /** 当前是否聚焦。 */\n focused: boolean;\n /** 是否显示清除按钮。 */\n showClear: boolean;\n /** 清空输入。 */\n clear(): void;\n /** 触发搜索。 */\n search(): void;\n /** 根容器 prop-getter。 */\n getRootProps(): T[\"element\"];\n /** 输入区容器 prop-getter(包含图标、输入框、清除按钮)。 */\n getFieldProps(): T[\"element\"];\n /** 输入框 prop-getter。 */\n getInputProps(): T[\"input\"];\n /** 左侧图标 prop-getter。 */\n getIconProps(): T[\"element\"];\n /** 清除按钮 prop-getter。 */\n getClearButtonProps(): T[\"button\"];\n /** 左侧 prefix 按钮 prop-getter。 */\n getPrefixButtonProps(): T[\"button\"];\n /** 右侧 action 按钮 prop-getter。 */\n getActionButtonProps(): T[\"button\"];\n}\n\n/**\n * connect:把 service 接成业务友好的 prop-getter。\n * 适配层只需调用 connect(service, normalizeProps)。\n */\nexport function connect<T extends PropTypes>(service: Service<SearchBarSchema>, normalizeProps: NormalizeProps<T>): SearchBarApi<T> {\n const { context, computed, prop, send } = service;\n\n const value = context.get(\"value\");\n const focused = context.get(\"focused\");\n const showClear = computed(\"showClear\");\n const disabled = !!prop(\"disabled\");\n const readOnly = !!prop(\"readOnly\");\n const maxLength = prop(\"maxLength\");\n const prefix = prop(\"prefix\");\n const action = prop(\"action\");\n\n return {\n value,\n focused,\n showClear,\n\n clear() {\n send({ type: \"VALUE.CLEAR\" });\n },\n\n search() {\n send({ type: \"SEARCH\" });\n },\n\n getRootProps() {\n return normalizeProps.element(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"root\",\n \"data-focused\": focused ? \"true\" : undefined,\n \"data-disabled\": disabled ? \"true\" : undefined,\n \"data-readonly\": readOnly ? \"true\" : undefined,\n }),\n );\n },\n\n getFieldProps() {\n return normalizeProps.element(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"field\",\n }),\n );\n },\n\n getInputProps() {\n return normalizeProps.input(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"input\",\n type: \"search\" as const,\n role: \"searchbox\" as const,\n value,\n placeholder: prop(\"placeholder\"),\n disabled,\n readOnly,\n maxLength: maxLength && maxLength > 0 ? maxLength : undefined,\n \"aria-disabled\": disabled ? (\"true\" as const) : undefined,\n \"aria-readonly\": readOnly ? (\"true\" as const) : undefined,\n onFocus() {\n send({ type: \"FOCUS.SET\", focused: true });\n },\n onBlur() {\n send({ type: \"FOCUS.SET\", focused: false });\n },\n onChange(event: JSX.ChangeEvent<HTMLInputElement>) {\n const target = event.target as HTMLInputElement;\n const next = target.value;\n send({ type: \"VALUE.SET\", value: next });\n },\n onKeyDown(event: JSX.KeyboardEvent<HTMLInputElement>) {\n if (event.key === \"Enter\") {\n send({ type: \"SEARCH\" });\n }\n },\n }),\n );\n },\n\n getIconProps() {\n return normalizeProps.element(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"icon\",\n \"aria-hidden\": \"true\" as const,\n }),\n );\n },\n\n getClearButtonProps() {\n return normalizeProps.button(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"clear-button\",\n type: \"button\" as const,\n disabled: disabled || readOnly,\n \"aria-label\": \"清除搜索内容\" as const,\n \"aria-hidden\": !showClear,\n hidden: !showClear,\n onClick() {\n send({ type: \"VALUE.CLEAR\" });\n },\n }),\n );\n },\n\n getPrefixButtonProps() {\n return normalizeProps.button(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"prefix-button\",\n type: \"button\" as const,\n disabled,\n \"aria-label\": prefix?.ariaLabel,\n \"data-action\": prefix?.type,\n onClick() {\n if (prefix?.type === \"cancel\") {\n send({ type: \"CANCEL\", src: \"prefix\" });\n } else if (prefix?.type === \"search\") {\n send({ type: \"SEARCH\" });\n }\n },\n }),\n );\n },\n\n getActionButtonProps() {\n return normalizeProps.button(\n compact({\n \"data-scope\": \"search-bar\",\n \"data-part\": \"action-button\",\n type: \"button\" as const,\n disabled,\n \"aria-label\": action?.ariaLabel,\n \"data-action\": action?.type,\n onClick() {\n if (action?.type === \"cancel\") {\n send({ type: \"CANCEL\", src: \"action\" });\n } else if (action?.type === \"search\") {\n send({ type: \"SEARCH\" });\n }\n },\n }),\n );\n },\n };\n}\n\n/**\n * 把 QwSearchBarProps 转成 machine context(默认值收口)。\n */\nexport function createSearchBarProps(props: QwSearchBarProps = {}): Partial<QwSearchBarProps> {\n return {\n defaultValue: props.defaultValue ?? \"\",\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n ...props,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import type { MachineSchema, Service } from "@zag-js/core";
2
+ import type { PropTypes, NormalizeProps } from "@zag-js/types";
3
+ /**
4
+ * 清除按钮显示策略。
5
+ */
6
+ export type SearchBarClearable = boolean | {
7
+ showWhen?: "always" | "focus" | "non-empty";
8
+ };
9
+ /**
10
+ * 内部归一化后的显示策略(包含 `never`,表示 `clearable={false}`)。
11
+ */
12
+ export type SearchBarClearableMode = "always" | "focus" | "non-empty" | "never";
13
+ export interface SearchBarClearableConfig {
14
+ showWhen: SearchBarClearableMode;
15
+ }
16
+ /**
17
+ * 右侧 action 按钮角色。
18
+ */
19
+ export type SearchBarActionType = "cancel" | "search";
20
+ /**
21
+ * 右侧 action 按钮配置。
22
+ */
23
+ export interface SearchBarAction {
24
+ /** 按钮角色。 */
25
+ type: SearchBarActionType;
26
+ /** 展示内容:文案或自定义节点。 */
27
+ content: string | unknown;
28
+ /** 取消时是否清空输入。 */
29
+ clearOnCancel?: boolean;
30
+ /** 按钮可访问名称;当 content 为纯图标时必填。 */
31
+ ariaLabel?: string;
32
+ }
33
+ /**
34
+ * SearchBar 公共 props 契约(双栈共享)。
35
+ */
36
+ export interface QwSearchBarProps {
37
+ /** 唯一 id 前缀。 */
38
+ id?: string;
39
+ /** 受控值。 */
40
+ value?: string;
41
+ /** 非受控初始值。 */
42
+ defaultValue?: string;
43
+ /** 占位符。 */
44
+ placeholder?: string;
45
+ /** 最大字符数。 */
46
+ maxLength?: number;
47
+ /** 禁用态。 */
48
+ disabled?: boolean;
49
+ /** 只读态。 */
50
+ readOnly?: boolean;
51
+ /** 清除按钮配置。 */
52
+ clearable?: SearchBarClearable;
53
+ /** 左侧搜索图标:字符串文案或自定义节点。 */
54
+ searchIcon?: string | unknown;
55
+ /** 左侧按钮配置。 */
56
+ prefix?: SearchBarAction;
57
+ /** 右侧按钮配置。 */
58
+ action?: SearchBarAction;
59
+ /** 输入变化回调。 */
60
+ onChange?: (value: string) => void;
61
+ /** 搜索确认回调(Enter 或点击搜索按钮)。 */
62
+ onSearch?: (value: string) => void;
63
+ /** 清空回调。 */
64
+ onClear?: () => void;
65
+ /** 取消回调。 */
66
+ onCancel?: () => void;
67
+ /** 聚焦回调。 */
68
+ onFocus?: () => void;
69
+ /** 失焦回调。 */
70
+ onBlur?: () => void;
71
+ }
72
+ /**
73
+ * 内部 schema,用于 createMachine 类型推导。
74
+ */
75
+ interface SearchBarSchema extends MachineSchema {
76
+ props: QwSearchBarProps;
77
+ context: {
78
+ value: string;
79
+ focused: boolean;
80
+ };
81
+ computed: {
82
+ showClear: boolean;
83
+ clearableConfig: SearchBarClearableConfig;
84
+ };
85
+ state: "idle";
86
+ event: {
87
+ type: "VALUE.SET";
88
+ value: string;
89
+ src?: string;
90
+ } | {
91
+ type: "VALUE.CLEAR";
92
+ } | {
93
+ type: "FOCUS.SET";
94
+ focused: boolean;
95
+ } | {
96
+ type: "SEARCH";
97
+ } | {
98
+ type: "CANCEL";
99
+ src?: "prefix" | "action";
100
+ };
101
+ action: "setValue" | "clearValue" | "setFocused" | "invokeOnSearch" | "invokeOnClear" | "invokeOnCancel" | "invokeOnFocus" | "invokeOnBlur";
102
+ }
103
+ /**
104
+ * SearchBar zag.js machine。
105
+ * 所有交互逻辑唯一来源:value、focus、clear、action、keyboard。
106
+ */
107
+ export declare const machine: import("@zag-js/core").Machine<SearchBarSchema>;
108
+ /**
109
+ * SearchBar api 类型(由 connect 返回)。
110
+ */
111
+ export interface SearchBarApi<T extends PropTypes = PropTypes> {
112
+ /** 当前输入值。 */
113
+ value: string;
114
+ /** 当前是否聚焦。 */
115
+ focused: boolean;
116
+ /** 是否显示清除按钮。 */
117
+ showClear: boolean;
118
+ /** 清空输入。 */
119
+ clear(): void;
120
+ /** 触发搜索。 */
121
+ search(): void;
122
+ /** 根容器 prop-getter。 */
123
+ getRootProps(): T["element"];
124
+ /** 输入区容器 prop-getter(包含图标、输入框、清除按钮)。 */
125
+ getFieldProps(): T["element"];
126
+ /** 输入框 prop-getter。 */
127
+ getInputProps(): T["input"];
128
+ /** 左侧图标 prop-getter。 */
129
+ getIconProps(): T["element"];
130
+ /** 清除按钮 prop-getter。 */
131
+ getClearButtonProps(): T["button"];
132
+ /** 左侧 prefix 按钮 prop-getter。 */
133
+ getPrefixButtonProps(): T["button"];
134
+ /** 右侧 action 按钮 prop-getter。 */
135
+ getActionButtonProps(): T["button"];
136
+ }
137
+ /**
138
+ * connect:把 service 接成业务友好的 prop-getter。
139
+ * 适配层只需调用 connect(service, normalizeProps)。
140
+ */
141
+ export declare function connect<T extends PropTypes>(service: Service<SearchBarSchema>, normalizeProps: NormalizeProps<T>): SearchBarApi<T>;
142
+ /**
143
+ * 把 QwSearchBarProps 转成 machine context(默认值收口)。
144
+ */
145
+ export declare function createSearchBarProps(props?: QwSearchBarProps): Partial<QwSearchBarProps>;
146
+ export {};
@@ -0,0 +1 @@
1
+ export * from "./skeleton.js";
@@ -0,0 +1,28 @@
1
+ //#region src/skeleton/skeleton.ts
2
+ /**
3
+ * Skeleton 契约 — 原型 A(无状态),core 无 machine,只承载双栈共享的类型契约。
4
+ * 渲染契约:`data-scope="skeleton"`,`aria-hidden="true"`;
5
+ * data-part 为 root / line;流光动效纯 CSS,尊重 `prefers-reduced-motion`。
6
+ *
7
+ * 形状 / 动效 / 圆角词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
8
+ */
9
+ /** 形状全集:text 文本条 / circle 头像 / rect 图片卡片块。 */
10
+ const SKELETON_VARIANTS = [
11
+ "text",
12
+ "circle",
13
+ "rect"
14
+ ];
15
+ /** 动效全集:wave 流光(默认)/ none 静态。 */
16
+ const SKELETON_ANIMATIONS = ["wave", "none"];
17
+ /** 圆角档位全集。 */
18
+ const SKELETON_RADII = [
19
+ "control",
20
+ "card",
21
+ "full"
22
+ ];
23
+ /** Skeleton 各渲染部位全集(data-part 取值)。 */
24
+ const SKELETON_PARTS = ["root", "line"];
25
+ //#endregion
26
+ export { SKELETON_ANIMATIONS, SKELETON_PARTS, SKELETON_RADII, SKELETON_VARIANTS };
27
+
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/skeleton/skeleton.ts"],"sourcesContent":["/**\n * Skeleton 契约 — 原型 A(无状态),core 无 machine,只承载双栈共享的类型契约。\n * 渲染契约:`data-scope=\"skeleton\"`,`aria-hidden=\"true\"`;\n * data-part 为 root / line;流光动效纯 CSS,尊重 `prefers-reduced-motion`。\n *\n * 形状 / 动效 / 圆角词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。\n */\n\n/** 形状全集:text 文本条 / circle 头像 / rect 图片卡片块。 */\nexport const SKELETON_VARIANTS = [\"text\", \"circle\", \"rect\"] as const;\n\n/** 动效全集:wave 流光(默认)/ none 静态。 */\nexport const SKELETON_ANIMATIONS = [\"wave\", \"none\"] as const;\n\n/** 圆角档位全集。 */\nexport const SKELETON_RADII = [\"control\", \"card\", \"full\"] as const;\n\n/** Skeleton 各渲染部位全集(data-part 取值)。 */\nexport const SKELETON_PARTS = [\"root\", \"line\"] as const;\n\nexport type SkeletonVariant = (typeof SKELETON_VARIANTS)[number];\nexport type SkeletonAnimation = (typeof SKELETON_ANIMATIONS)[number];\nexport type SkeletonRadius = (typeof SKELETON_RADII)[number];\nexport type SkeletonPart = (typeof SKELETON_PARTS)[number];\n\n/**\n * QwSkeletonProps — 双栈共享的行为契约。\n * 几何 width/height 的 number|string 形式是框架无关的;\n * 富内容不涉及(骨架不承载文本)。\n */\nexport interface QwSkeletonProps {\n /** 形状,默认 text。 */\n variant?: SkeletonVariant;\n /** 动效,默认 wave。 */\n animation?: SkeletonAnimation;\n /** 宽度,数值按 px 处理。 */\n width?: number | string;\n /** 高度,数值按 px 处理。 */\n height?: number | string;\n /** 圆角档位(circle 恒为正圆,忽略此项)。 */\n radius?: SkeletonRadius;\n /** 仅 text:一次渲染多行文本条,末行更短。默认 1。 */\n lines?: number;\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,oBAAoB;CAAC;CAAQ;CAAU;AAAM;;AAG1D,MAAa,sBAAsB,CAAC,QAAQ,MAAM;;AAGlD,MAAa,iBAAiB;CAAC;CAAW;CAAQ;AAAM;;AAGxD,MAAa,iBAAiB,CAAC,QAAQ,MAAM"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Skeleton 契约 — 原型 A(无状态),core 无 machine,只承载双栈共享的类型契约。
3
+ * 渲染契约:`data-scope="skeleton"`,`aria-hidden="true"`;
4
+ * data-part 为 root / line;流光动效纯 CSS,尊重 `prefers-reduced-motion`。
5
+ *
6
+ * 形状 / 动效 / 圆角词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
7
+ */
8
+ /** 形状全集:text 文本条 / circle 头像 / rect 图片卡片块。 */
9
+ export declare const SKELETON_VARIANTS: readonly ["text", "circle", "rect"];
10
+ /** 动效全集:wave 流光(默认)/ none 静态。 */
11
+ export declare const SKELETON_ANIMATIONS: readonly ["wave", "none"];
12
+ /** 圆角档位全集。 */
13
+ export declare const SKELETON_RADII: readonly ["control", "card", "full"];
14
+ /** Skeleton 各渲染部位全集(data-part 取值)。 */
15
+ export declare const SKELETON_PARTS: readonly ["root", "line"];
16
+ export type SkeletonVariant = (typeof SKELETON_VARIANTS)[number];
17
+ export type SkeletonAnimation = (typeof SKELETON_ANIMATIONS)[number];
18
+ export type SkeletonRadius = (typeof SKELETON_RADII)[number];
19
+ export type SkeletonPart = (typeof SKELETON_PARTS)[number];
20
+ /**
21
+ * QwSkeletonProps — 双栈共享的行为契约。
22
+ * 几何 width/height 的 number|string 形式是框架无关的;
23
+ * 富内容不涉及(骨架不承载文本)。
24
+ */
25
+ export interface QwSkeletonProps {
26
+ /** 形状,默认 text。 */
27
+ variant?: SkeletonVariant;
28
+ /** 动效,默认 wave。 */
29
+ animation?: SkeletonAnimation;
30
+ /** 宽度,数值按 px 处理。 */
31
+ width?: number | string;
32
+ /** 高度,数值按 px 处理。 */
33
+ height?: number | string;
34
+ /** 圆角档位(circle 恒为正圆,忽略此项)。 */
35
+ radius?: SkeletonRadius;
36
+ /** 仅 text:一次渲染多行文本条,末行更短。默认 1。 */
37
+ lines?: number;
38
+ }
@@ -1,36 +1 @@
1
- import { Props } from '@zag-js/tabs';
2
- export { Api as QwTabsApi, connect, machine as tabsMachine } from '@zag-js/tabs';
3
-
4
- /**
5
- * QwTabsProps — Tabs 的用户输入。对 zag.js 输入做默认值收口 + 命名 rebrand:
6
- * - loop(默认 true)→ zag loopFocus;
7
- * - value / defaultValue / orientation / activationMode 透传;
8
- * - onValueChange 适配 zag details。
9
- * 业务方只 import 本类型,不直接 import `@zag-js/*`。
10
- */
11
- interface QwTabsProps {
12
- /** 唯一 id 前缀;不传由适配层生成 (SSR/CSR 一致)。 */
13
- id?: string;
14
- /** 受控当前项。 */
15
- value?: string | null;
16
- /** 非受控初值。 */
17
- defaultValue?: string | null;
18
- /** 方向,默认 horizontal。 */
19
- orientation?: "horizontal" | "vertical";
20
- /** 激活模式,默认 automatic(聚焦即激活)。 */
21
- activationMode?: "manual" | "automatic";
22
- /** 方向键首尾循环,默认 true (zag 原名 loopFocus)。 */
23
- loop?: boolean;
24
- /** 选中项变化回调;zag 原生 onValueChange。 */
25
- onValueChange?: (e: {
26
- value: string;
27
- }) => void;
28
- }
29
-
30
- /**
31
- * 把 QwTabsProps 转成 zag tabs machine 的 props (默认值收口 + 命名 rebrand)。
32
- * 用法:`useMachine(tabsMachine, createTabsProps(props))`。
33
- */
34
- declare function createTabsProps(props?: QwTabsProps): Partial<Props>;
35
-
36
- export { type QwTabsProps, createTabsProps };
1
+ export * from "./tabs.js";
@@ -1,22 +1,38 @@
1
- export { connect, machine as tabsMachine } from '@zag-js/tabs';
2
-
3
- // src/tabs/index.ts
1
+ import { connect, machine as tabsMachine } from "@zag-js/tabs";
2
+ //#region src/tabs/tabs.ts
3
+ /**
4
+ * Tabs 契约 — 原型 B(有状态),core 包裹 zag.js tabs machine。
5
+ * 行为 props 进 createTabsProps → zag context;视觉 props(level/variant/size)
6
+ * 不进 machine,由适配层挂 data-* 属性驱动 CSS。
7
+ *
8
+ * 枚举以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死词表。
9
+ */
10
+ /** 导航层级全集:primary 一级导航(默认)/ secondary 二级导航。 */
11
+ const TABS_LEVELS = ["primary", "secondary"];
12
+ /** 视觉形态全集:text 纯文本(默认)/ button 按钮。button 仅 secondary 支持。 */
13
+ const TABS_VARIANTS = ["text", "button"];
14
+ /** 字号全集:仅 primary 生效,"14" / "16"(默认)。 */
15
+ const TABS_SIZES = ["14", "16"];
16
+ /**
17
+ * 把 QwTabsProps 的行为 props 转成 zag tabs machine 的 props (默认值收口 + 命名 rebrand)。
18
+ * 视觉 props(level/variant/size)不出现在返回值中——它们是适配层 data-* 属性。
19
+ * 用法:`useMachine(tabsMachine, createTabsProps(props))`。
20
+ */
4
21
  function createTabsProps(props = {}) {
5
- const ctx = {
6
- id: props.id,
7
- value: props.value,
8
- defaultValue: props.defaultValue,
9
- orientation: props.orientation,
10
- activationMode: props.activationMode,
11
- loopFocus: props.loop !== false
12
- };
13
- if (props.onValueChange) {
14
- const cb = props.onValueChange;
15
- ctx.onValueChange = (d) => cb({ value: d.value });
16
- }
17
- return ctx;
22
+ const ctx = {
23
+ id: props.id,
24
+ value: props.value,
25
+ defaultValue: props.defaultValue,
26
+ activationMode: props.activationMode,
27
+ loopFocus: props.loop !== false
28
+ };
29
+ if (props.onValueChange) {
30
+ const cb = props.onValueChange;
31
+ ctx.onValueChange = (d) => cb({ value: d.value });
32
+ }
33
+ return ctx;
18
34
  }
35
+ //#endregion
36
+ export { TABS_LEVELS, TABS_SIZES, TABS_VARIANTS, connect, createTabsProps, tabsMachine };
19
37
 
20
- export { createTabsProps };
21
- //# sourceMappingURL=index.js.map
22
38
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tabs/index.ts"],"names":[],"mappings":";;;AAuCO,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 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"]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/tabs/tabs.ts"],"sourcesContent":["import type { Props as ZagTabsProps, ValueChangeDetails } from \"@zag-js/tabs\";\n\n/**\n * Tabs 契约 — 原型 B(有状态),core 包裹 zag.js tabs machine。\n * 行为 props 进 createTabsProps → zag context;视觉 props(level/variant/size)\n * 不进 machine,由适配层挂 data-* 属性驱动 CSS。\n *\n * 枚举以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死词表。\n */\n\n/** 导航层级全集:primary 一级导航(默认)/ secondary 二级导航。 */\nexport const TABS_LEVELS = [\"primary\", \"secondary\"] as const;\nexport type TabsLevel = (typeof TABS_LEVELS)[number];\n\n/** 视觉形态全集:text 纯文本(默认)/ button 按钮。button 仅 secondary 支持。 */\nexport const TABS_VARIANTS = [\"text\", \"button\"] as const;\nexport type TabsVariant = (typeof TABS_VARIANTS)[number];\n\n/** 字号全集:仅 primary 生效,\"14\" / \"16\"(默认)。 */\nexport const TABS_SIZES = [\"14\", \"16\"] as const;\nexport type TabsSize = (typeof TABS_SIZES)[number];\n\n/**\n * QwTabsProps — 双栈共享的行为 + 视觉契约。\n * 行为 props(进 createTabsProps → zag machine):\n * - loop(默认 true)→ zag loopFocus;\n * - value / defaultValue / activationMode 透传;\n * - onValueChange 适配 zag details。\n * 视觉 props(不进 machine,适配层挂 data-*):\n * - level / variant / size。\n */\nexport interface QwTabsProps {\n /** 唯一 id 前缀;不传由适配层生成 (SSR/CSR 一致)。 */\n id?: string;\n /** 受控当前项。 */\n value?: string | null;\n /** 非受控初值。 */\n defaultValue?: string | null;\n /** 激活模式,默认 automatic(聚焦即激活)。 */\n activationMode?: \"manual\" | \"automatic\";\n /** 方向键首尾循环,默认 true (zag 原名 loopFocus)。 */\n loop?: boolean;\n /** 选中项变化回调;zag 原生 onValueChange。 */\n onValueChange?: (e: { value: string }) => void;\n /** 导航层级,默认 primary。 */\n level?: TabsLevel;\n /** 视觉形态,默认 text。level=primary 时强制 text。 */\n variant?: TabsVariant;\n /** 字号,默认 \"16\"。仅 level=primary 生效。 */\n size?: TabsSize;\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 的行为 props 转成 zag tabs machine 的 props (默认值收口 + 命名 rebrand)。\n * 视觉 props(level/variant/size)不出现在返回值中——它们是适配层 data-* 属性。\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 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"],"mappings":";;;;;;;;;;AAWA,MAAa,cAAc,CAAC,WAAW,WAAW;;AAIlD,MAAa,gBAAgB,CAAC,QAAQ,QAAQ;;AAI9C,MAAa,aAAa,CAAC,MAAM,IAAI;;;;;;AA+CrC,SAAgB,gBAAgB,QAAqB,CAAC,GAA0B;CAC9E,MAAM,MAA6B;EACjC,IAAI,MAAM;EACV,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,gBAAgB,MAAM;EACtB,WAAW,MAAM,SAAS;CAC5B;CAEA,IAAI,MAAM,eAAe;EACvB,MAAM,KAAK,MAAM;EACjB,IAAI,iBAAiB,MAA0B,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC;CACtE;CAEA,OAAO;AACT"}