@qw-ui/core 0.3.0-next.3 → 0.3.0-next.30

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 (39) hide show
  1. package/README.md +1 -1
  2. package/dist/badge/badge.d.ts +76 -0
  3. package/dist/badge/index.d.ts +1 -0
  4. package/dist/badge/index.js +75 -0
  5. package/dist/badge/index.js.map +1 -0
  6. package/dist/dialog/dialog.d.ts +31 -42
  7. package/dist/dialog/index.js +18 -19
  8. package/dist/dialog/index.js.map +1 -1
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +7 -1
  11. package/dist/overlay-panel/index.d.ts +2 -0
  12. package/dist/overlay-panel/index.js +2 -0
  13. package/dist/overlay-panel/overlay-panel.d.ts +20 -0
  14. package/dist/overlay-panel-Z_qdKeBj.js +26 -0
  15. package/dist/overlay-panel-Z_qdKeBj.js.map +1 -0
  16. package/dist/search-bar/index.js +1 -1
  17. package/dist/search-bar/index.js.map +1 -1
  18. package/dist/search-bar/search-bar.d.ts +2 -0
  19. package/dist/side-nav/index.d.ts +1 -0
  20. package/dist/side-nav/index.js +99 -0
  21. package/dist/side-nav/index.js.map +1 -0
  22. package/dist/side-nav/side-nav.d.ts +94 -0
  23. package/dist/stepper/index.d.ts +1 -0
  24. package/dist/stepper/index.js +113 -0
  25. package/dist/stepper/index.js.map +1 -0
  26. package/dist/stepper/stepper.d.ts +121 -0
  27. package/dist/switch/index.d.ts +1 -0
  28. package/dist/switch/index.js +43 -0
  29. package/dist/switch/index.js.map +1 -0
  30. package/dist/switch/switch.d.ts +55 -0
  31. package/dist/tabbar/index.d.ts +1 -0
  32. package/dist/tabbar/index.js +50 -0
  33. package/dist/tabbar/index.js.map +1 -0
  34. package/dist/tabbar/tabbar.d.ts +69 -0
  35. package/dist/textarea/index.js +2 -2
  36. package/dist/textarea/index.js.map +1 -1
  37. package/dist/textarea/textarea.d.ts +4 -0
  38. package/dist/visual-manifest.d.ts +4 -0
  39. package/package.json +28 -4
package/README.md CHANGED
@@ -50,7 +50,7 @@ index.ts + __test__/ + docs/{overview.md, accessibility.md, demos.ts, visual.ts}
50
50
  | `latest`(稳定) | `pnpm add @qw-ui/core` | `main` 通道,Release PR review 后发布 |
51
51
  | `next`(预发布) | `pnpm add @qw-ui/core@next` | `release/next` 通道,高频自增 `x.y.z-next.N` |
52
52
 
53
- 8 个公开包 `fixed` 锁步同版本号。npm 发布固定走 `registry.npmjs.org`;内网装依赖走 `registry.anpm.alibaba-inc.com`(tnpm 代理),发布 registry 不要指向内网。流程详见 [development-workflow.md](../../docs/development-workflow.md)。
53
+ 9 个公开包 `fixed` 锁步同版本号。npm 发布固定走 `registry.npmjs.org`;内网装依赖走 `registry.anpm.alibaba-inc.com`(tnpm 代理),发布 registry 不要指向内网。流程详见 [development-workflow.md](../../docs/development-workflow.md)。
54
54
 
55
55
  ## 仓库 & License
56
56
 
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Badge 契约 — 原型 A(无状态),core 无 machine,
3
+ * 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。
4
+ * 渲染契约:`data-scope="badge"`,`data-part="root"`;
5
+ * `data-variant` / `data-kind` 摊平枚举。
6
+ *
7
+ * 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
8
+ */
9
+ /** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */
10
+ export declare const BADGE_VARIANTS: readonly ["solid", "subtle"];
11
+ /** 形态全集:number 数字(默认)/ dot 纯红点。 */
12
+ export declare const BADGE_KINDS: readonly ["number", "dot"];
13
+ /** Badge 各渲染部位全集(data-part 取值)。 */
14
+ export declare const BADGE_PARTS: readonly ["root"];
15
+ /** 默认溢出阈值:数值超过时收敛为「99+」。 */
16
+ export declare const DEFAULT_BADGE_MAX_COUNT = 99;
17
+ export type BadgeVariant = (typeof BADGE_VARIANTS)[number];
18
+ export type BadgeKind = (typeof BADGE_KINDS)[number];
19
+ export type BadgePart = (typeof BADGE_PARTS)[number];
20
+ /**
21
+ * QwBadgeProps — 双栈共享的行为契约(全字段可选)。
22
+ * 视觉完全由语义令牌驱动,组件不开放自定义色值入口。
23
+ */
24
+ export interface QwBadgeProps {
25
+ /** 视觉变体,默认 solid;dot 形态强制 solid。 */
26
+ variant?: BadgeVariant;
27
+ /** 纯红点形态,默认 false;为 true 时优先于 count。 */
28
+ dot?: boolean;
29
+ /** 未读数量;≤0 / 非有限数值不渲染。 */
30
+ count?: number;
31
+ /** 溢出阈值,默认 99;非法值(≤0 或非整数)回退默认。 */
32
+ maxCount?: number;
33
+ /** 自定义无障碍播报文案,全量覆盖默认文案。 */
34
+ ariaLabel?: string;
35
+ }
36
+ /** 适配层从 locale 传入的默认播报文案。 */
37
+ export interface BadgeAriaTexts {
38
+ /** 数字形态播报模板,含 {count} 占位符。 */
39
+ unreadAriaTemplate: string;
40
+ /** 纯红点形态播报文案。 */
41
+ dotAria: string;
42
+ }
43
+ /** resolveBadgeState 的解析结果,适配层据此摊平渲染。 */
44
+ export interface ResolvedBadgeState {
45
+ /** 是否渲染徽标本体;false 时双栈一致返回空渲染。 */
46
+ visible: boolean;
47
+ /** 形态。 */
48
+ kind: BadgeKind;
49
+ /** 解析后的视觉变体(dot + subtle 已降级为 solid)。 */
50
+ variant: BadgeVariant;
51
+ /** 可见文本(溢出为「<阈值>+」;dot / 不可见为空串)。 */
52
+ label: string;
53
+ /** 数值是否超过阈值。 */
54
+ overflow: boolean;
55
+ /** 解析后的生效阈值。 */
56
+ maxCount: number;
57
+ /** 生效的无障碍播报文案。 */
58
+ ariaLabel: string;
59
+ }
60
+ /**
61
+ * 纯函数:props + 文案 → 解析结果。
62
+ * 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;
63
+ * ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。
64
+ */
65
+ export declare function resolveBadgeState(props: QwBadgeProps, texts: BadgeAriaTexts): ResolvedBadgeState;
66
+ /** 根元素 prop-getter 返回的 DOM 属性集。 */
67
+ export interface BadgeRootProps {
68
+ "data-scope": "badge";
69
+ "data-part": "root";
70
+ "data-variant": BadgeVariant;
71
+ "data-kind": BadgeKind;
72
+ role: "status";
73
+ "aria-label": string;
74
+ }
75
+ /** 根元素 prop-getter:摊平 data 状态属性 + role="status" + 播报文案。 */
76
+ export declare function getBadgeRootProps(state: ResolvedBadgeState): BadgeRootProps;
@@ -0,0 +1 @@
1
+ export * from "./badge.js";
@@ -0,0 +1,75 @@
1
+ //#region src/badge/badge.ts
2
+ /**
3
+ * Badge 契约 — 原型 A(无状态),core 无 machine,
4
+ * 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。
5
+ * 渲染契约:`data-scope="badge"`,`data-part="root"`;
6
+ * `data-variant` / `data-kind` 摊平枚举。
7
+ *
8
+ * 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
9
+ */
10
+ /** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */
11
+ const BADGE_VARIANTS = ["solid", "subtle"];
12
+ /** 形态全集:number 数字(默认)/ dot 纯红点。 */
13
+ const BADGE_KINDS = ["number", "dot"];
14
+ /** Badge 各渲染部位全集(data-part 取值)。 */
15
+ const BADGE_PARTS = ["root"];
16
+ /** 默认溢出阈值:数值超过时收敛为「99+」。 */
17
+ const DEFAULT_BADGE_MAX_COUNT = 99;
18
+ /** 非法阈值(≤0 或非整数)一律回退默认值,避免非法配置导致空渲染。 */
19
+ function resolveMaxCount(maxCount) {
20
+ return typeof maxCount === "number" && Number.isInteger(maxCount) && maxCount > 0 ? maxCount : 99;
21
+ }
22
+ /**
23
+ * 纯函数:props + 文案 → 解析结果。
24
+ * 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;
25
+ * ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。
26
+ */
27
+ function resolveBadgeState(props, texts) {
28
+ const { variant = "solid", dot = false, count, maxCount, ariaLabel } = props;
29
+ const safeMax = resolveMaxCount(maxCount);
30
+ if (dot) return {
31
+ visible: true,
32
+ kind: "dot",
33
+ variant: "solid",
34
+ label: "",
35
+ overflow: false,
36
+ maxCount: safeMax,
37
+ ariaLabel: ariaLabel ?? texts.dotAria
38
+ };
39
+ const normalized = typeof count === "number" && Number.isFinite(count) && count > 0 ? Math.round(count) : 0;
40
+ if (normalized === 0) return {
41
+ visible: false,
42
+ kind: "number",
43
+ variant,
44
+ label: "",
45
+ overflow: false,
46
+ maxCount: safeMax,
47
+ ariaLabel: ""
48
+ };
49
+ const overflow = normalized > safeMax;
50
+ const label = overflow ? `${safeMax}+` : `${normalized}`;
51
+ return {
52
+ visible: true,
53
+ kind: "number",
54
+ variant,
55
+ label,
56
+ overflow,
57
+ maxCount: safeMax,
58
+ ariaLabel: ariaLabel ?? texts.unreadAriaTemplate.replaceAll("{count}", label)
59
+ };
60
+ }
61
+ /** 根元素 prop-getter:摊平 data 状态属性 + role="status" + 播报文案。 */
62
+ function getBadgeRootProps(state) {
63
+ return {
64
+ "data-scope": "badge",
65
+ "data-part": "root",
66
+ "data-variant": state.variant,
67
+ "data-kind": state.kind,
68
+ role: "status",
69
+ "aria-label": state.ariaLabel
70
+ };
71
+ }
72
+ //#endregion
73
+ export { BADGE_KINDS, BADGE_PARTS, BADGE_VARIANTS, DEFAULT_BADGE_MAX_COUNT, getBadgeRootProps, resolveBadgeState };
74
+
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/badge/badge.ts"],"sourcesContent":["/**\n * Badge 契约 — 原型 A(无状态),core 无 machine,\n * 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。\n * 渲染契约:`data-scope=\"badge\"`,`data-part=\"root\"`;\n * `data-variant` / `data-kind` 摊平枚举。\n *\n * 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。\n */\n\n/** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */\nexport const BADGE_VARIANTS = [\"solid\", \"subtle\"] as const;\n\n/** 形态全集:number 数字(默认)/ dot 纯红点。 */\nexport const BADGE_KINDS = [\"number\", \"dot\"] as const;\n\n/** Badge 各渲染部位全集(data-part 取值)。 */\nexport const BADGE_PARTS = [\"root\"] as const;\n\n/** 默认溢出阈值:数值超过时收敛为「99+」。 */\nexport const DEFAULT_BADGE_MAX_COUNT = 99;\n\nexport type BadgeVariant = (typeof BADGE_VARIANTS)[number];\nexport type BadgeKind = (typeof BADGE_KINDS)[number];\nexport type BadgePart = (typeof BADGE_PARTS)[number];\n\n/**\n * QwBadgeProps — 双栈共享的行为契约(全字段可选)。\n * 视觉完全由语义令牌驱动,组件不开放自定义色值入口。\n */\nexport interface QwBadgeProps {\n /** 视觉变体,默认 solid;dot 形态强制 solid。 */\n variant?: BadgeVariant;\n /** 纯红点形态,默认 false;为 true 时优先于 count。 */\n dot?: boolean;\n /** 未读数量;≤0 / 非有限数值不渲染。 */\n count?: number;\n /** 溢出阈值,默认 99;非法值(≤0 或非整数)回退默认。 */\n maxCount?: number;\n /** 自定义无障碍播报文案,全量覆盖默认文案。 */\n ariaLabel?: string;\n}\n\n/** 适配层从 locale 传入的默认播报文案。 */\nexport interface BadgeAriaTexts {\n /** 数字形态播报模板,含 {count} 占位符。 */\n unreadAriaTemplate: string;\n /** 纯红点形态播报文案。 */\n dotAria: string;\n}\n\n/** resolveBadgeState 的解析结果,适配层据此摊平渲染。 */\nexport interface ResolvedBadgeState {\n /** 是否渲染徽标本体;false 时双栈一致返回空渲染。 */\n visible: boolean;\n /** 形态。 */\n kind: BadgeKind;\n /** 解析后的视觉变体(dot + subtle 已降级为 solid)。 */\n variant: BadgeVariant;\n /** 可见文本(溢出为「<阈值>+」;dot / 不可见为空串)。 */\n label: string;\n /** 数值是否超过阈值。 */\n overflow: boolean;\n /** 解析后的生效阈值。 */\n maxCount: number;\n /** 生效的无障碍播报文案。 */\n ariaLabel: string;\n}\n\n/** 非法阈值(≤0 或非整数)一律回退默认值,避免非法配置导致空渲染。 */\nfunction resolveMaxCount(maxCount: number | undefined): number {\n return typeof maxCount === \"number\" && Number.isInteger(maxCount) && maxCount > 0\n ? maxCount\n : DEFAULT_BADGE_MAX_COUNT;\n}\n\n/**\n * 纯函数:props + 文案 → 解析结果。\n * 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;\n * ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。\n */\nexport function resolveBadgeState(\n props: QwBadgeProps,\n texts: BadgeAriaTexts,\n): ResolvedBadgeState {\n const { variant = \"solid\", dot = false, count, maxCount, ariaLabel } = props;\n const safeMax = resolveMaxCount(maxCount);\n\n if (dot) {\n return {\n visible: true,\n kind: \"dot\",\n variant: \"solid\",\n label: \"\",\n overflow: false,\n maxCount: safeMax,\n ariaLabel: ariaLabel ?? texts.dotAria,\n };\n }\n\n const normalized =\n typeof count === \"number\" && Number.isFinite(count) && count > 0\n ? Math.round(count)\n : 0;\n\n if (normalized === 0) {\n return {\n visible: false,\n kind: \"number\",\n variant,\n label: \"\",\n overflow: false,\n maxCount: safeMax,\n ariaLabel: \"\",\n };\n }\n\n const overflow = normalized > safeMax;\n const label = overflow ? `${safeMax}+` : `${normalized}`;\n return {\n visible: true,\n kind: \"number\",\n variant,\n label,\n overflow,\n maxCount: safeMax,\n ariaLabel: ariaLabel ?? texts.unreadAriaTemplate.replaceAll(\"{count}\", label),\n };\n}\n\n/** 根元素 prop-getter 返回的 DOM 属性集。 */\nexport interface BadgeRootProps {\n \"data-scope\": \"badge\";\n \"data-part\": \"root\";\n \"data-variant\": BadgeVariant;\n \"data-kind\": BadgeKind;\n role: \"status\";\n \"aria-label\": string;\n}\n\n/** 根元素 prop-getter:摊平 data 状态属性 + role=\"status\" + 播报文案。 */\nexport function getBadgeRootProps(state: ResolvedBadgeState): BadgeRootProps {\n return {\n \"data-scope\": \"badge\",\n \"data-part\": \"root\",\n \"data-variant\": state.variant,\n \"data-kind\": state.kind,\n role: \"status\",\n \"aria-label\": state.ariaLabel,\n };\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,iBAAiB,CAAC,SAAS,QAAQ;;AAGhD,MAAa,cAAc,CAAC,UAAU,KAAK;;AAG3C,MAAa,cAAc,CAAC,MAAM;;AAGlC,MAAa,0BAA0B;;AAkDvC,SAAS,gBAAgB,UAAsC;CAC7D,OAAO,OAAO,aAAa,YAAY,OAAO,UAAU,QAAQ,KAAK,WAAW,IAC5E,WAAA;AAEN;;;;;;AAOA,SAAgB,kBACd,OACA,OACoB;CACpB,MAAM,EAAE,UAAU,SAAS,MAAM,OAAO,OAAO,UAAU,cAAc;CACvE,MAAM,UAAU,gBAAgB,QAAQ;CAExC,IAAI,KACF,OAAO;EACL,SAAS;EACT,MAAM;EACN,SAAS;EACT,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW,aAAa,MAAM;CAChC;CAGF,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,IAC3D,KAAK,MAAM,KAAK,IAChB;CAEN,IAAI,eAAe,GACjB,OAAO;EACL,SAAS;EACT,MAAM;EACN;EACA,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW;CACb;CAGF,MAAM,WAAW,aAAa;CAC9B,MAAM,QAAQ,WAAW,GAAG,QAAQ,KAAK,GAAG;CAC5C,OAAO;EACL,SAAS;EACT,MAAM;EACN;EACA;EACA;EACA,UAAU;EACV,WAAW,aAAa,MAAM,mBAAmB,WAAW,WAAW,KAAK;CAC9E;AACF;;AAaA,SAAgB,kBAAkB,OAA2C;CAC3E,OAAO;EACL,cAAc;EACd,aAAa;EACb,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACnB,MAAM;EACN,cAAc,MAAM;CACtB;AACF"}
@@ -1,59 +1,48 @@
1
1
  import type { Props as ZagDialogProps } from "@zag-js/dialog";
2
2
  /**
3
- * QwDialogProps — Dialog 的用户输入。
3
+ * QwDialogProps — H5 系统 Dialog 的跨框架行为输入。
4
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/*`。
5
+ * 只暴露业务能理解的开合、遮罩点击、body 滚动控制;modal / role / focus
6
+ * 策略是组件内部无障碍政策,不作为业务 API。
11
7
  */
12
8
  export interface QwDialogProps {
13
- /** 唯一 id 前缀;不传时由 zag 安全生成 (SSR/CSR 一致)。 */
9
+ /** 唯一 id 前缀;不传时由适配层提供 SSR/CSR 稳定 id。 */
14
10
  id?: string;
15
11
  /** 受控开关。 */
16
12
  open?: boolean;
17
13
  /** 非受控初值。 */
18
14
  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;
15
+ /** 点击遮罩关闭,默认 true。 */
16
+ closeOnMaskClick?: boolean;
17
+ /** Dialog 打开时禁止 body 滚动,默认 true。 */
18
+ disableBodyScroll?: boolean;
19
+ /** 状态变化回调。 */
20
+ onOpenChange?: (open: boolean) => void;
21
+ }
22
+ export interface QwDialogActionProps {
23
+ /** 是否展示取消按钮,默认 true。 */
24
+ showCancel?: boolean;
25
+ /** 取消按钮禁用。 */
26
+ cancelDisabled?: boolean;
27
+ /** 确认按钮禁用。 */
28
+ confirmDisabled?: boolean;
29
+ /** 确认按钮忙碌;忙碌时视为禁用。 */
30
+ confirmLoading?: boolean;
31
+ }
32
+ export interface QwDialogActionState {
33
+ showCancel: boolean;
34
+ cancelDisabled: boolean;
35
+ confirmDisabled: boolean;
36
+ confirmLoading: boolean;
46
37
  }
47
38
  /**
48
- * 直接 re-export zag 的 dialog machine 与 connect —— 不再包一层。
49
- * machine 由各框架 useMachine 消费;connect 把 service 接成 prop-getter。
50
- * 用 re-export 而非 `const x = dialog.x` 以保留原始可移植类型 (避免 TS2742)。
39
+ * 直接 re-export zag 的 dialog machine 与 connect。
40
+ * 各框架适配层只实例化 service 并摊 prop-getter。
51
41
  */
52
42
  export { machine as dialogMachine, connect } from "@zag-js/dialog";
53
43
  /** rebrand zag 的 DialogApi 类型对外。 */
54
44
  export type { Api as QwDialogApi } from "@zag-js/dialog";
55
- /**
56
- * 把 QwDialogProps 转成 zag dialog machine 的 context (默认值收口 + 命名 rebrand)。
57
- * 用法:`useMachine(dialogMachine, createDialogProps(props))`。
58
- */
45
+ /** 把 H5 Dialog 公开 props 转成 zag dialog machine context。 */
59
46
  export declare function createDialogProps(props?: QwDialogProps): Partial<ZagDialogProps>;
47
+ /** 双栈共享的 Dialog 操作区状态归一化。 */
48
+ export declare function resolveDialogActionState(props?: QwDialogActionProps): QwDialogActionState;
@@ -1,35 +1,34 @@
1
1
  import { connect, machine as dialogMachine } from "@zag-js/dialog";
2
2
  //#region src/dialog/dialog.ts
3
- /**
4
- * 把 QwDialogProps 转成 zag dialog machine 的 context (默认值收口 + 命名 rebrand)。
5
- * 用法:`useMachine(dialogMachine, createDialogProps(props))`。
6
- */
3
+ /** 把 H5 Dialog 公开 props 转成 zag dialog machine context。 */
7
4
  function createDialogProps(props = {}) {
8
5
  const ctx = {
9
6
  id: props.id,
10
7
  open: props.open,
11
8
  defaultOpen: props.defaultOpen,
12
- role: props.role,
13
- closeOnEscape: props.closeOnEsc !== false,
14
- closeOnInteractOutside: props.closeOnOutside !== false,
15
- preventScroll: props.scrollLock !== false
9
+ role: "dialog",
10
+ modal: true,
11
+ closeOnEscape: true,
12
+ closeOnInteractOutside: props.closeOnMaskClick !== false,
13
+ preventScroll: props.disableBodyScroll !== false
16
14
  };
17
- if (props.modal !== void 0) ctx.modal = props.modal;
18
15
  if (props.onOpenChange) {
19
16
  const cb = props.onOpenChange;
20
- ctx.onOpenChange = (d) => cb({ open: d.open });
17
+ ctx.onOpenChange = (d) => cb(d.open);
21
18
  }
22
- if (typeof props.initialFocus === "object") {
23
- const sel = props.initialFocus.selector;
24
- ctx.initialFocusEl = () => document.querySelector(sel);
25
- }
26
- if (typeof props.returnFocus === "object") {
27
- const sel = props.returnFocus.selector;
28
- ctx.finalFocusEl = () => document.querySelector(sel);
29
- } else if (props.returnFocus === "none") ctx.restoreFocus = false;
30
19
  return ctx;
31
20
  }
21
+ /** 双栈共享的 Dialog 操作区状态归一化。 */
22
+ function resolveDialogActionState(props = {}) {
23
+ const confirmLoading = props.confirmLoading ?? false;
24
+ return {
25
+ showCancel: props.showCancel !== false,
26
+ cancelDisabled: props.cancelDisabled ?? false,
27
+ confirmDisabled: (props.confirmDisabled ?? false) || confirmLoading,
28
+ confirmLoading
29
+ };
30
+ }
32
31
  //#endregion
33
- export { connect, createDialogProps, dialogMachine };
32
+ export { connect, createDialogProps, dialogMachine, resolveDialogActionState };
34
33
 
35
34
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/dialog/dialog.ts"],"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"],"mappings":";;;;;;AAwDA,SAAgB,kBAAkB,QAAuB,CAAC,GAA4B;CACpF,MAAM,MAA+B;EACnC,IAAI,MAAM;EACV,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,MAAM,MAAM;EACZ,eAAe,MAAM,eAAe;EACpC,wBAAwB,MAAM,mBAAmB;EACjD,eAAe,MAAM,eAAe;CACtC;CAEA,IAAI,MAAM,UAAU,KAAA,GAAW,IAAI,QAAQ,MAAM;CAEjD,IAAI,MAAM,cAAc;EACtB,MAAM,KAAK,MAAM;EACjB,IAAI,gBAAgB,MAAyB,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC;CAClE;CAGA,IAAI,OAAO,MAAM,iBAAiB,UAAU;EAC1C,MAAM,MAAM,MAAM,aAAa;EAC/B,IAAI,uBAAuB,SAAS,cAA2B,GAAG;CACpE;CAGA,IAAI,OAAO,MAAM,gBAAgB,UAAU;EACzC,MAAM,MAAM,MAAM,YAAY;EAC9B,IAAI,qBAAqB,SAAS,cAA2B,GAAG;CAClE,OAAO,IAAI,MAAM,gBAAgB,QAC/B,IAAI,eAAe;CAGrB,OAAO;AACT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/dialog/dialog.ts"],"sourcesContent":["import type { OpenChangeDetails, Props as ZagDialogProps } from \"@zag-js/dialog\";\n\n/**\n * QwDialogProps — H5 系统 Dialog 的跨框架行为输入。\n *\n * 只暴露业务能理解的开合、遮罩点击、body 滚动控制;modal / role / focus\n * 策略是组件内部无障碍政策,不作为业务 API。\n */\nexport interface QwDialogProps {\n /** 唯一 id 前缀;不传时由适配层提供 SSR/CSR 稳定 id。 */\n id?: string;\n /** 受控开关。 */\n open?: boolean;\n /** 非受控初值。 */\n defaultOpen?: boolean;\n /** 点击遮罩关闭,默认 true。 */\n closeOnMaskClick?: boolean;\n /** Dialog 打开时禁止 body 滚动,默认 true。 */\n disableBodyScroll?: boolean;\n /** 状态变化回调。 */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport interface QwDialogActionProps {\n /** 是否展示取消按钮,默认 true。 */\n showCancel?: boolean;\n /** 取消按钮禁用。 */\n cancelDisabled?: boolean;\n /** 确认按钮禁用。 */\n confirmDisabled?: boolean;\n /** 确认按钮忙碌;忙碌时视为禁用。 */\n confirmLoading?: boolean;\n}\n\nexport interface QwDialogActionState {\n showCancel: boolean;\n cancelDisabled: boolean;\n confirmDisabled: boolean;\n confirmLoading: boolean;\n}\n\n/**\n * 直接 re-export zag 的 dialog machine 与 connect。\n * 各框架适配层只实例化 service 并摊 prop-getter。\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/** 把 H5 Dialog 公开 props 转成 zag dialog machine context。 */\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: \"dialog\",\n modal: true,\n closeOnEscape: true,\n closeOnInteractOutside: props.closeOnMaskClick !== false,\n preventScroll: props.disableBodyScroll !== false,\n };\n\n if (props.onOpenChange) {\n const cb = props.onOpenChange;\n ctx.onOpenChange = (d: OpenChangeDetails) => cb(d.open);\n }\n\n return ctx;\n}\n\n/** 双栈共享的 Dialog 操作区状态归一化。 */\nexport function resolveDialogActionState(\n props: QwDialogActionProps = {},\n): QwDialogActionState {\n const confirmLoading = props.confirmLoading ?? false;\n return {\n showCancel: props.showCancel !== false,\n cancelDisabled: props.cancelDisabled ?? false,\n confirmDisabled: (props.confirmDisabled ?? false) || confirmLoading,\n confirmLoading,\n };\n}\n"],"mappings":";;;AAmDA,SAAgB,kBAAkB,QAAuB,CAAC,GAA4B;CACpF,MAAM,MAA+B;EACnC,IAAI,MAAM;EACV,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,MAAM;EACN,OAAO;EACP,eAAe;EACf,wBAAwB,MAAM,qBAAqB;EACnD,eAAe,MAAM,sBAAsB;CAC7C;CAEA,IAAI,MAAM,cAAc;EACtB,MAAM,KAAK,MAAM;EACjB,IAAI,gBAAgB,MAAyB,GAAG,EAAE,IAAI;CACxD;CAEA,OAAO;AACT;;AAGA,SAAgB,yBACd,QAA6B,CAAC,GACT;CACrB,MAAM,iBAAiB,MAAM,kBAAkB;CAC/C,OAAO;EACL,YAAY,MAAM,eAAe;EACjC,gBAAgB,MAAM,kBAAkB;EACxC,kBAAkB,MAAM,mBAAmB,UAAU;EACrD;CACF;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { dialogMachine, connect, createDialogProps, } from "./dialog/index.js";
2
2
  export type { QwDialogProps, QwDialogApi } from "./dialog/index.js";
3
+ export { DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT, OVERLAY_PANEL_PARTS, resolveOverlayPanelHeight, } from "./overlay-panel/index.js";
4
+ export type { OverlayPanelHeight, OverlayPanelPart, QwOverlayPanelProps, } from "./overlay-panel/index.js";
3
5
  export { tabsMachine, createTabsProps } from "./tabs/index.js";
4
6
  export type { QwTabsProps, QwTabsApi } from "./tabs/index.js";
5
7
  export { TOAST_POSITIONS, TOAST_ICON_TYPES, TOAST_PARTS, DEFAULT_TOAST_DURATION, DEFAULT_TOAST_POSITION, isToastIconType, resolveToastDuration, } from "./toast/index.js";
@@ -26,3 +28,13 @@ export { TAG_PARTS, TAG_SIZES, TAG_VARIANTS } from "./tag/index.js";
26
28
  export type { TagPart, TagSize, TagVariant, QwTagProps } from "./tag/index.js";
27
29
  export { createInputProps } from "./input/index.js";
28
30
  export type { QwInputProps, InputApi, InputMode, InputReadOnlyOverflow } from "./input/index.js";
31
+ export { SWITCH_PARTS, getSwitchRootProps, getSwitchThumbProps, resolveSwitchState } from "./switch/index.js";
32
+ export type { SwitchPart, QwSwitchProps, ResolvedSwitchState, SwitchRootProps, SwitchThumbProps } from "./switch/index.js";
33
+ export { STEPPER_SIZES, STEPPER_PARTS, clampStepperValue, getStepperRootProps, getStepperDecrementProps, getStepperDecrementValue, getStepperIncrementProps, getStepperIncrementValue, getStepperValueProps, resolveStepperState, } from "./stepper/index.js";
34
+ export type { StepperPart, StepperSize, QwStepperProps, ResolvedStepperState, StepperRootProps, StepperDecrementProps, StepperIncrementProps, StepperValueProps, } from "./stepper/index.js";
35
+ export { BADGE_KINDS, BADGE_PARTS, BADGE_VARIANTS, DEFAULT_BADGE_MAX_COUNT, getBadgeRootProps, resolveBadgeState, } from "./badge/index.js";
36
+ export type { BadgeAriaTexts, BadgeKind, BadgePart, BadgeRootProps, BadgeVariant, QwBadgeProps, ResolvedBadgeState, } from "./badge/index.js";
37
+ export { TABBAR_ITEM_TONES, TABBAR_ITEM_VARIANTS, TABBAR_PARTS, getTabBarItemButtonProps, getTabBarRootProps, resolveTabBarState, } from "./tabbar/index.js";
38
+ export type { QwTabBarItemProps, QwTabBarProps, ResolvedTabBarItemState, ResolvedTabBarState, TabBarItemButtonProps, TabBarItemTone, TabBarItemVariant, TabBarPart, TabBarRootProps, } from "./tabbar/index.js";
39
+ export { SIDENAV_PARTS, getSideNavGroupLabelProps, getSideNavItemProps, getSideNavRootProps, resolveSideNavState, } from "./side-nav/index.js";
40
+ export type { QwSideNavGroupProps, QwSideNavItemProps, QwSideNavProps, ResolvedSideNavGroupState, ResolvedSideNavItemState, ResolvedSideNavState, SideNavGroupLabelProps, SideNavItemAdjacent, SideNavItemProps, SideNavPart, SideNavRootProps, } from "./side-nav/index.js";
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { connect, createDialogProps, dialogMachine } from "./dialog/index.js";
2
+ import { n as OVERLAY_PANEL_PARTS, r as resolveOverlayPanelHeight, t as DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT } from "./overlay-panel-Z_qdKeBj.js";
2
3
  import { createTabsProps, tabsMachine } from "./tabs/index.js";
3
4
  import { DEFAULT_TOAST_DURATION, DEFAULT_TOAST_POSITION, TOAST_ICON_TYPES, TOAST_PARTS, TOAST_POSITIONS, isToastIconType, resolveToastDuration } from "./toast/index.js";
4
5
  import { BUTTON_ICON_POSITIONS, BUTTON_PARTS, BUTTON_SHAPES, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, getButtonRootProps, resolveButtonState } from "./button/index.js";
@@ -12,4 +13,9 @@ import { AVATAR_BADGE_TYPES, AVATAR_LOAD_STATUS, AVATAR_PARTS, AVATAR_SHAPES, AV
12
13
  import { connect as connect$1, createTextAreaProps, machine } from "./textarea/index.js";
13
14
  import { TAG_PARTS, TAG_SIZES, TAG_VARIANTS } from "./tag/index.js";
14
15
  import { createInputProps } from "./input/index.js";
15
- export { AVATAR_BADGE_TYPES, AVATAR_LOAD_STATUS, AVATAR_PARTS, AVATAR_SHAPES, AVATAR_SIZES, BADGE_COUNT_MAX, BUTTON_ICON_POSITIONS, BUTTON_PARTS, BUTTON_SHAPES, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, DEFAULT_TOAST_DURATION, DEFAULT_TOAST_POSITION, DIVIDER_ORIENTATIONS, DIVIDER_PARTS, DIVIDER_WEIGHTS, EMPTY_PARTS, ICON_FALLBACK_NAME, ICON_PARTS, LOADING_SIZES, SKELETON_ANIMATIONS, SKELETON_PARTS, SKELETON_RADII, SKELETON_VARIANTS, TAG_PARTS, TAG_SIZES, TAG_VARIANTS, TOAST_ICON_TYPES, TOAST_PARTS, TOAST_POSITIONS, TOPBAR_VARIANTS, connect, createDialogProps, createInputProps, createTabsProps, createTextAreaProps, createTopBarProps, dialogMachine, extractInitials, getAvatarBadgeProps, getAvatarFallbackProps, getAvatarImageElementProps, getAvatarImageProps, getAvatarRootProps, getButtonRootProps, isToastIconType, resolveAvatarState, resolveButtonState, resolveIconName, resolveToastDuration, tabsMachine, connect$1 as textAreaConnect, machine as textAreaMachine };
16
+ import { SWITCH_PARTS, getSwitchRootProps, getSwitchThumbProps, resolveSwitchState } from "./switch/index.js";
17
+ import { STEPPER_PARTS, STEPPER_SIZES, clampStepperValue, getStepperDecrementProps, getStepperDecrementValue, getStepperIncrementProps, getStepperIncrementValue, getStepperRootProps, getStepperValueProps, resolveStepperState } from "./stepper/index.js";
18
+ import { BADGE_KINDS, BADGE_PARTS, BADGE_VARIANTS, DEFAULT_BADGE_MAX_COUNT, getBadgeRootProps, resolveBadgeState } from "./badge/index.js";
19
+ import { TABBAR_ITEM_TONES, TABBAR_ITEM_VARIANTS, TABBAR_PARTS, getTabBarItemButtonProps, getTabBarRootProps, resolveTabBarState } from "./tabbar/index.js";
20
+ import { SIDENAV_PARTS, getSideNavGroupLabelProps, getSideNavItemProps, getSideNavRootProps, resolveSideNavState } from "./side-nav/index.js";
21
+ export { AVATAR_BADGE_TYPES, AVATAR_LOAD_STATUS, AVATAR_PARTS, AVATAR_SHAPES, AVATAR_SIZES, BADGE_COUNT_MAX, BADGE_KINDS, BADGE_PARTS, BADGE_VARIANTS, BUTTON_ICON_POSITIONS, BUTTON_PARTS, BUTTON_SHAPES, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, DEFAULT_BADGE_MAX_COUNT, DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT, DEFAULT_TOAST_DURATION, DEFAULT_TOAST_POSITION, DIVIDER_ORIENTATIONS, DIVIDER_PARTS, DIVIDER_WEIGHTS, EMPTY_PARTS, ICON_FALLBACK_NAME, ICON_PARTS, LOADING_SIZES, OVERLAY_PANEL_PARTS, SIDENAV_PARTS, SKELETON_ANIMATIONS, SKELETON_PARTS, SKELETON_RADII, SKELETON_VARIANTS, STEPPER_PARTS, STEPPER_SIZES, SWITCH_PARTS, TABBAR_ITEM_TONES, TABBAR_ITEM_VARIANTS, TABBAR_PARTS, TAG_PARTS, TAG_SIZES, TAG_VARIANTS, TOAST_ICON_TYPES, TOAST_PARTS, TOAST_POSITIONS, TOPBAR_VARIANTS, clampStepperValue, connect, createDialogProps, createInputProps, createTabsProps, createTextAreaProps, createTopBarProps, dialogMachine, extractInitials, getAvatarBadgeProps, getAvatarFallbackProps, getAvatarImageElementProps, getAvatarImageProps, getAvatarRootProps, getBadgeRootProps, getButtonRootProps, getSideNavGroupLabelProps, getSideNavItemProps, getSideNavRootProps, getStepperDecrementProps, getStepperDecrementValue, getStepperIncrementProps, getStepperIncrementValue, getStepperRootProps, getStepperValueProps, getSwitchRootProps, getSwitchThumbProps, getTabBarItemButtonProps, getTabBarRootProps, isToastIconType, resolveAvatarState, resolveBadgeState, resolveButtonState, resolveIconName, resolveOverlayPanelHeight, resolveSideNavState, resolveStepperState, resolveSwitchState, resolveTabBarState, resolveToastDuration, tabsMachine, connect$1 as textAreaConnect, machine as textAreaMachine };
@@ -0,0 +1,2 @@
1
+ export { DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT, OVERLAY_PANEL_PARTS, resolveOverlayPanelHeight, } from "./overlay-panel.js";
2
+ export type { OverlayPanelHeight, OverlayPanelPart, QwOverlayPanelProps, } from "./overlay-panel.js";
@@ -0,0 +1,2 @@
1
+ import { n as OVERLAY_PANEL_PARTS, r as resolveOverlayPanelHeight, t as DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT } from "../overlay-panel-Z_qdKeBj.js";
2
+ export { DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT, OVERLAY_PANEL_PARTS, resolveOverlayPanelHeight };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * OverlayPanel 契约 — 原型 A(无状态),core 无 machine。
3
+ * 渲染契约:`data-scope="overlay-panel"`,根/header/title/actions/content/footer
4
+ * 以 data-part 摊平,React/Vue 适配层同名同义。
5
+ */
6
+ /** OverlayPanel 各渲染部位全集(data-part 取值)。 */
7
+ export declare const OVERLAY_PANEL_PARTS: readonly ["root", "header", "title", "actions", "content", "footer"];
8
+ /** 默认 header 高度,对齐 Figma H5 浮层导航。 */
9
+ export declare const DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT = 60;
10
+ export type OverlayPanelPart = (typeof OVERLAY_PANEL_PARTS)[number];
11
+ export type OverlayPanelHeight = number | string;
12
+ /** QwOverlayPanelProps — 双栈共享的容器契约。 */
13
+ export interface QwOverlayPanelProps {
14
+ /** 容器高度;数字按 px 归一化,字符串原样透传。 */
15
+ height?: OverlayPanelHeight;
16
+ /** 默认 header 的标题内容。 */
17
+ title?: unknown;
18
+ }
19
+ /** 将外部传入的 height 归一化为 CSS height 值。 */
20
+ export declare function resolveOverlayPanelHeight(height?: OverlayPanelHeight): string | undefined;
@@ -0,0 +1,26 @@
1
+ //#region src/overlay-panel/overlay-panel.ts
2
+ /**
3
+ * OverlayPanel 契约 — 原型 A(无状态),core 无 machine。
4
+ * 渲染契约:`data-scope="overlay-panel"`,根/header/title/actions/content/footer
5
+ * 以 data-part 摊平,React/Vue 适配层同名同义。
6
+ */
7
+ /** OverlayPanel 各渲染部位全集(data-part 取值)。 */
8
+ const OVERLAY_PANEL_PARTS = [
9
+ "root",
10
+ "header",
11
+ "title",
12
+ "actions",
13
+ "content",
14
+ "footer"
15
+ ];
16
+ /** 默认 header 高度,对齐 Figma H5 浮层导航。 */
17
+ const DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT = 60;
18
+ /** 将外部传入的 height 归一化为 CSS height 值。 */
19
+ function resolveOverlayPanelHeight(height) {
20
+ if (height == null) return void 0;
21
+ return typeof height === "number" ? `${height}px` : height;
22
+ }
23
+ //#endregion
24
+ export { OVERLAY_PANEL_PARTS as n, resolveOverlayPanelHeight as r, DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT as t };
25
+
26
+ //# sourceMappingURL=overlay-panel-Z_qdKeBj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-panel-Z_qdKeBj.js","names":[],"sources":["../src/overlay-panel/overlay-panel.ts"],"sourcesContent":["/**\n * OverlayPanel 契约 — 原型 A(无状态),core 无 machine。\n * 渲染契约:`data-scope=\"overlay-panel\"`,根/header/title/actions/content/footer\n * 以 data-part 摊平,React/Vue 适配层同名同义。\n */\n\n/** OverlayPanel 各渲染部位全集(data-part 取值)。 */\nexport const OVERLAY_PANEL_PARTS = [\n \"root\",\n \"header\",\n \"title\",\n \"actions\",\n \"content\",\n \"footer\",\n] as const;\n\n/** 默认 header 高度,对齐 Figma H5 浮层导航。 */\nexport const DEFAULT_OVERLAY_PANEL_HEADER_HEIGHT = 60;\n\nexport type OverlayPanelPart = (typeof OVERLAY_PANEL_PARTS)[number];\nexport type OverlayPanelHeight = number | string;\n\n/** QwOverlayPanelProps — 双栈共享的容器契约。 */\nexport interface QwOverlayPanelProps {\n /** 容器高度;数字按 px 归一化,字符串原样透传。 */\n height?: OverlayPanelHeight;\n /** 默认 header 的标题内容。 */\n title?: unknown;\n}\n\n/** 将外部传入的 height 归一化为 CSS height 值。 */\nexport function resolveOverlayPanelHeight(height?: OverlayPanelHeight): string | undefined {\n if (height == null) return undefined;\n return typeof height === \"number\" ? `${height}px` : height;\n}\n"],"mappings":";;;;;;;AAOA,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,sCAAsC;;AAcnD,SAAgB,0BAA0B,QAAiD;CACzF,IAAI,UAAU,MAAM,OAAO,KAAA;CAC3B,OAAO,OAAO,WAAW,WAAW,GAAG,OAAO,MAAM;AACtD"}
@@ -195,7 +195,7 @@ function connect(service, normalizeProps) {
195
195
  "data-part": "clear-button",
196
196
  type: "button",
197
197
  disabled: disabled || readOnly,
198
- "aria-label": "清除搜索内容",
198
+ "aria-label": prop("clearLabel") ?? "清除搜索内容",
199
199
  "aria-hidden": !showClear,
200
200
  hidden: !showClear,
201
201
  onClick() {
@@ -1 +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 sync: true,\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, prop, context }) {\n track([() => prop(\"value\")], () => {\n const external = prop(\"value\");\n if (external !== undefined && external !== context.get(\"value\")) {\n context.set(\"value\", external);\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 // readOnly/disabled 时输入区仍可聚焦(readOnly HTML 语义),但不应呈现聚焦视觉态\n \"data-focused\": focused && !readOnly && !disabled ? \"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 nativeEvent = (event as { nativeEvent?: { isComposing?: boolean } }).nativeEvent;\n const isComposing = !!nativeEvent?.isComposing;\n let next = target.value;\n // IME composing 期间跳过 maxLength 截断,允许拼音中间态值流过\n if (!isComposing) {\n const maxLen = prop(\"maxLength\") ?? 0;\n if (maxLen > 0 && next.length > maxLen) {\n next = next.slice(0, maxLen);\n }\n }\n // 直接同步更新,绕过 send() 的 queueMicrotask 延迟\n context.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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"}
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 /** 清除按钮 aria-label,默认「清除搜索内容」。 */\n clearLabel?: string;\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 sync: true,\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, prop, context }) {\n track([() => prop(\"value\")], () => {\n const external = prop(\"value\");\n if (external !== undefined && external !== context.get(\"value\")) {\n context.set(\"value\", external);\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 // readOnly/disabled 时输入区仍可聚焦(readOnly HTML 语义),但不应呈现聚焦视觉态\n \"data-focused\": focused && !readOnly && !disabled ? \"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 nativeEvent = (event as { nativeEvent?: { isComposing?: boolean } }).nativeEvent;\n const isComposing = !!nativeEvent?.isComposing;\n let next = target.value;\n // IME composing 期间跳过 maxLength 截断,允许拼音中间态值流过\n if (!isComposing) {\n const maxLen = prop(\"maxLength\") ?? 0;\n if (maxLen > 0 && next.length > maxLen) {\n next = next.slice(0, maxLen);\n }\n }\n // 直接同步更新,绕过 send() 的 queueMicrotask 延迟\n context.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\": prop(\"clearLabel\") ?? \"清除搜索内容\",\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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"}
@@ -50,6 +50,8 @@ export interface QwSearchBarProps {
50
50
  readOnly?: boolean;
51
51
  /** 清除按钮配置。 */
52
52
  clearable?: SearchBarClearable;
53
+ /** 清除按钮 aria-label,默认「清除搜索内容」。 */
54
+ clearLabel?: string;
53
55
  /** 左侧搜索图标:字符串文案或自定义节点。 */
54
56
  searchIcon?: string | unknown;
55
57
  /** 左侧按钮配置。 */
@@ -0,0 +1 @@
1
+ export * from "./side-nav.js";