@zerodep-dev/vue-tsx-pro-mobile 0.0.0-stage → 0.4.1

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 (209) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -2
  3. package/dist/area/data.d.ts +10 -0
  4. package/dist/area/data.js +3899 -0
  5. package/dist/area/data.js.map +1 -0
  6. package/dist/area/index.d.ts +22 -0
  7. package/dist/area/index.js +41 -0
  8. package/dist/area/index.js.map +1 -0
  9. package/dist/base/Button.d.ts +170 -0
  10. package/dist/base/Button.js +537 -0
  11. package/dist/base/Button.js.map +1 -0
  12. package/dist/base/Icon.d.ts +38 -0
  13. package/dist/base/Icon.js +65 -0
  14. package/dist/base/Icon.js.map +1 -0
  15. package/dist/capability/PrivacyPrompt.d.ts +1 -0
  16. package/dist/capability/PrivacyPrompt.js +73 -0
  17. package/dist/capability/PrivacyPrompt.js.map +1 -0
  18. package/dist/capability/types.d.ts +92 -0
  19. package/dist/capability/usePermission.d.ts +23 -0
  20. package/dist/capability/usePermission.js +52 -0
  21. package/dist/capability/usePermission.js.map +1 -0
  22. package/dist/capability/useStorage.d.ts +8 -0
  23. package/dist/capability/useStorage.js +19 -0
  24. package/dist/capability/useStorage.js.map +1 -0
  25. package/dist/capability/web.d.ts +18 -0
  26. package/dist/capability/web.js +109 -0
  27. package/dist/capability/web.js.map +1 -0
  28. package/dist/capacitor/index.d.ts +9 -0
  29. package/dist/capacitor/index.js +143 -0
  30. package/dist/capacitor/index.js.map +1 -0
  31. package/dist/config/ConfigProvider.d.ts +37 -0
  32. package/dist/config/ConfigProvider.js +64 -0
  33. package/dist/config/ConfigProvider.js.map +1 -0
  34. package/dist/config/context.d.ts +16 -0
  35. package/dist/config/context.js +20 -0
  36. package/dist/config/context.js.map +1 -0
  37. package/dist/config/lang.d.ts +85 -0
  38. package/dist/config/lang.js +138 -0
  39. package/dist/config/lang.js.map +1 -0
  40. package/dist/display/Badge.d.ts +39 -0
  41. package/dist/display/Badge.js +108 -0
  42. package/dist/display/Badge.js.map +1 -0
  43. package/dist/display/Cell.d.ts +92 -0
  44. package/dist/display/Cell.js +204 -0
  45. package/dist/display/Cell.js.map +1 -0
  46. package/dist/display/Collapse.d.ts +47 -0
  47. package/dist/display/Collapse.js +173 -0
  48. package/dist/display/Collapse.js.map +1 -0
  49. package/dist/display/Empty.d.ts +42 -0
  50. package/dist/display/Empty.js +79 -0
  51. package/dist/display/Empty.js.map +1 -0
  52. package/dist/display/Grid.d.ts +49 -0
  53. package/dist/display/Grid.js +136 -0
  54. package/dist/display/Grid.js.map +1 -0
  55. package/dist/display/Image.d.ts +70 -0
  56. package/dist/display/Image.js +138 -0
  57. package/dist/display/Image.js.map +1 -0
  58. package/dist/display/IndexBar.d.ts +34 -0
  59. package/dist/display/IndexBar.js +158 -0
  60. package/dist/display/IndexBar.js.map +1 -0
  61. package/dist/display/List.d.ts +34 -0
  62. package/dist/display/List.js +105 -0
  63. package/dist/display/List.js.map +1 -0
  64. package/dist/display/NoticeBar.d.ts +57 -0
  65. package/dist/display/NoticeBar.js +172 -0
  66. package/dist/display/NoticeBar.js.map +1 -0
  67. package/dist/display/Steps.d.ts +59 -0
  68. package/dist/display/Steps.js +158 -0
  69. package/dist/display/Steps.js.map +1 -0
  70. package/dist/display/SwipeCell.d.ts +37 -0
  71. package/dist/display/SwipeCell.js +147 -0
  72. package/dist/display/SwipeCell.js.map +1 -0
  73. package/dist/display/Swiper.d.ts +47 -0
  74. package/dist/display/Swiper.js +173 -0
  75. package/dist/display/Swiper.js.map +1 -0
  76. package/dist/display/Tag.d.ts +99 -0
  77. package/dist/display/Tag.js +320 -0
  78. package/dist/display/Tag.js.map +1 -0
  79. package/dist/feedback/Dialog.d.ts +79 -0
  80. package/dist/feedback/Dialog.js +186 -0
  81. package/dist/feedback/Dialog.js.map +1 -0
  82. package/dist/feedback/FeedbackOutlet.d.ts +2 -0
  83. package/dist/feedback/FeedbackOutlet.js +31 -0
  84. package/dist/feedback/FeedbackOutlet.js.map +1 -0
  85. package/dist/feedback/Loading.d.ts +26 -0
  86. package/dist/feedback/Loading.js +68 -0
  87. package/dist/feedback/Loading.js.map +1 -0
  88. package/dist/feedback/Notify.d.ts +48 -0
  89. package/dist/feedback/Notify.js +116 -0
  90. package/dist/feedback/Notify.js.map +1 -0
  91. package/dist/feedback/PullRefresh.d.ts +58 -0
  92. package/dist/feedback/PullRefresh.js +178 -0
  93. package/dist/feedback/PullRefresh.js.map +1 -0
  94. package/dist/feedback/Skeleton.d.ts +56 -0
  95. package/dist/feedback/Skeleton.js +99 -0
  96. package/dist/feedback/Skeleton.js.map +1 -0
  97. package/dist/feedback/Toast.d.ts +89 -0
  98. package/dist/feedback/Toast.js +186 -0
  99. package/dist/feedback/Toast.js.map +1 -0
  100. package/dist/form/Checkbox.d.ts +52 -0
  101. package/dist/form/Checkbox.js +107 -0
  102. package/dist/form/Checkbox.js.map +1 -0
  103. package/dist/form/Field.d.ts +91 -0
  104. package/dist/form/Field.js +296 -0
  105. package/dist/form/Field.js.map +1 -0
  106. package/dist/form/Form.d.ts +50 -0
  107. package/dist/form/Form.js +96 -0
  108. package/dist/form/Form.js.map +1 -0
  109. package/dist/form/FormItem.d.ts +57 -0
  110. package/dist/form/FormItem.js +142 -0
  111. package/dist/form/FormItem.js.map +1 -0
  112. package/dist/form/Radio.d.ts +41 -0
  113. package/dist/form/Radio.js +85 -0
  114. package/dist/form/Radio.js.map +1 -0
  115. package/dist/form/Rate.d.ts +45 -0
  116. package/dist/form/Rate.js +162 -0
  117. package/dist/form/Rate.js.map +1 -0
  118. package/dist/form/Search.d.ts +50 -0
  119. package/dist/form/Search.js +152 -0
  120. package/dist/form/Search.js.map +1 -0
  121. package/dist/form/Slider.d.ts +43 -0
  122. package/dist/form/Slider.js +213 -0
  123. package/dist/form/Slider.js.map +1 -0
  124. package/dist/form/Stepper.d.ts +61 -0
  125. package/dist/form/Stepper.js +222 -0
  126. package/dist/form/Stepper.js.map +1 -0
  127. package/dist/form/Switch.d.ts +33 -0
  128. package/dist/form/Switch.js +116 -0
  129. package/dist/form/Switch.js.map +1 -0
  130. package/dist/form/Uploader.d.ts +67 -0
  131. package/dist/form/Uploader.js +207 -0
  132. package/dist/form/Uploader.js.map +1 -0
  133. package/dist/form/choice.d.ts +42 -0
  134. package/dist/form/choice.js +109 -0
  135. package/dist/form/choice.js.map +1 -0
  136. package/dist/form/context.d.ts +83 -0
  137. package/dist/form/context.js +89 -0
  138. package/dist/form/context.js.map +1 -0
  139. package/dist/index.d.ts +66 -0
  140. package/dist/index.js +59 -0
  141. package/dist/layout/Divider.d.ts +34 -0
  142. package/dist/layout/Divider.js +55 -0
  143. package/dist/layout/Divider.js.map +1 -0
  144. package/dist/layout/Space.d.ts +66 -0
  145. package/dist/layout/Space.js +65 -0
  146. package/dist/layout/Space.js.map +1 -0
  147. package/dist/navigation/BackTop.d.ts +29 -0
  148. package/dist/navigation/BackTop.js +89 -0
  149. package/dist/navigation/BackTop.js.map +1 -0
  150. package/dist/navigation/NavBar.d.ts +46 -0
  151. package/dist/navigation/NavBar.js +141 -0
  152. package/dist/navigation/NavBar.js.map +1 -0
  153. package/dist/navigation/Sticky.d.ts +19 -0
  154. package/dist/navigation/Sticky.js +28 -0
  155. package/dist/navigation/Sticky.js.map +1 -0
  156. package/dist/navigation/TabBar.d.ts +54 -0
  157. package/dist/navigation/TabBar.js +138 -0
  158. package/dist/navigation/TabBar.js.map +1 -0
  159. package/dist/navigation/Tabs.d.ts +45 -0
  160. package/dist/navigation/Tabs.js +206 -0
  161. package/dist/navigation/Tabs.js.map +1 -0
  162. package/dist/overlay/ActionSheet.d.ts +80 -0
  163. package/dist/overlay/ActionSheet.js +164 -0
  164. package/dist/overlay/ActionSheet.js.map +1 -0
  165. package/dist/overlay/Overlay.d.ts +35 -0
  166. package/dist/overlay/Overlay.js +85 -0
  167. package/dist/overlay/Overlay.js.map +1 -0
  168. package/dist/overlay/Popup.d.ts +76 -0
  169. package/dist/overlay/Popup.js +191 -0
  170. package/dist/overlay/Popup.js.map +1 -0
  171. package/dist/picker/Calendar.d.ts +69 -0
  172. package/dist/picker/Calendar.js +213 -0
  173. package/dist/picker/Calendar.js.map +1 -0
  174. package/dist/picker/Cascader.d.ts +50 -0
  175. package/dist/picker/Cascader.js +199 -0
  176. package/dist/picker/Cascader.js.map +1 -0
  177. package/dist/picker/DatePicker.d.ts +52 -0
  178. package/dist/picker/DatePicker.js +135 -0
  179. package/dist/picker/DatePicker.js.map +1 -0
  180. package/dist/picker/DropdownMenu.d.ts +39 -0
  181. package/dist/picker/DropdownMenu.js +242 -0
  182. package/dist/picker/DropdownMenu.js.map +1 -0
  183. package/dist/picker/Picker.d.ts +67 -0
  184. package/dist/picker/Picker.js +185 -0
  185. package/dist/picker/Picker.js.map +1 -0
  186. package/dist/picker/PickerColumn.d.ts +36 -0
  187. package/dist/picker/PickerColumn.js +175 -0
  188. package/dist/picker/PickerColumn.js.map +1 -0
  189. package/dist/theme/dark.d.ts +121 -0
  190. package/dist/theme/dark.js +77 -0
  191. package/dist/theme/dark.js.map +1 -0
  192. package/dist/theme/divider.d.ts +6 -0
  193. package/dist/theme/divider.js +18 -0
  194. package/dist/theme/divider.js.map +1 -0
  195. package/dist/theme/token-names.d.ts +1389 -0
  196. package/dist/theme/tokens.d.ts +549 -0
  197. package/dist/theme/tokens.js +312 -0
  198. package/dist/theme/tokens.js.map +1 -0
  199. package/dist/utils/host.d.ts +97 -0
  200. package/dist/utils/host.js +98 -0
  201. package/dist/utils/host.js.map +1 -0
  202. package/dist/utils/presence.d.ts +11 -0
  203. package/dist/utils/presence.js +34 -0
  204. package/dist/utils/presence.js.map +1 -0
  205. package/dist/utils/props.d.ts +38 -0
  206. package/dist/utils/props.js +115 -0
  207. package/dist/utils/props.js.map +1 -0
  208. package/dist/utils/scales.d.ts +48 -0
  209. package/package.json +106 -3
@@ -0,0 +1,19 @@
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import type { VNodeChild } from 'vue';
3
+ import { type PartProps } from '../utils/props';
4
+ /** 未声明的属性落到根元素(div)上 */
5
+ export interface StickyProps extends PartProps<'div'> {
6
+ /**
7
+ * 停住时离顶部多远(CSS 长度)
8
+ * @default 0
9
+ */
10
+ offsetTop?: string;
11
+ /** 吸顶的内容 */
12
+ children?: VNodeChild;
13
+ }
14
+ /** Sticky 的样式:root */
15
+ export declare const stickyStyles: Readonly<{
16
+ root: css.CompiledStyles;
17
+ }>;
18
+ /** 吸顶(div) */
19
+ export declare const Sticky: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<StickyProps>;
@@ -0,0 +1,28 @@
1
+ import { mergeAttrs } from "../utils/props.js";
2
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
3
+ import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
+ import { createVNode } from "vue";
5
+ //#region src/navigation/Sticky.tsx
6
+ /** 未声明的属性落到根元素(div)上 */
7
+ /** Sticky 的样式:root */
8
+ var stickyStyles = css.create({ root: {
9
+ position: "sticky",
10
+ zIndex: 100
11
+ } });
12
+ /** 吸顶(div) */
13
+ var Sticky = /*#__PURE__*/ _component((_props, _ctx) => {
14
+ const offsetTop = readonlyProp(_props, "offsetTop", "0px");
15
+ const children = childrenProp(_props);
16
+ const rest = restProps(_props, _ctx, false);
17
+ return () => createVNode("div", mergeAttrs({
18
+ sx: stickyStyles.root,
19
+ style: { insetBlockStart: offsetTop.value }
20
+ }, rest), [children.value]);
21
+ }, {
22
+ name: "Sticky",
23
+ props: ["offsetTop"]
24
+ });
25
+ //#endregion
26
+ export { Sticky, stickyStyles };
27
+
28
+ //# sourceMappingURL=Sticky.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sticky.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/navigation/Sticky.tsx"],"sourcesContent":["/**\n * 吸顶:内容随页面滚动,滚到顶部(或离顶部 offsetTop)时停住,直到所在的容器滚出去。用 CSS 的 position: sticky,\n * 两端都不用监听滚动。\n *\n * <Sticky><Tabs …/></Sticky>\n * <Sticky offsetTop=\"3.15em\">…</Sticky> 停在固定的导航栏下面\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { mergeAttrs, type PartProps } from '../utils/props';\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface StickyProps extends PartProps<'div'> {\n /**\n * 停住时离顶部多远(CSS 长度)\n * @default 0\n */\n offsetTop?: string;\n /** 吸顶的内容 */\n children?: VNodeChild;\n}\n\n/** Sticky 的样式:root */\nexport const stickyStyles = css.create({\n root: { position: 'sticky', zIndex: 100 },\n});\n\n/** 吸顶(div) */\nexport const Sticky = _component(({ offsetTop = '0px', children, ...rest }: StickyProps) => () => (\n <div\n {...mergeAttrs<'div'>({ sx: stickyStyles.root, style: { insetBlockStart: offsetTop } }, rest)}\n >\n {children}\n </div>\n));\n"],"mappings":";;;;;;;AAwBA,IAAa,eAAe,IAAI,OAAO,EACrC,MAAM;CAAE,UAAU;CAAU,QAAQ;AAAI,EAC1C,CAAC;;AAGD,IAAa,SAAS,0BAAW,QAAA,SAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,aAAe,KAAK;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAe,OAAIC,UAAA,QAAA,MAAA,KAAA;CAAA,aAAoBC,YAAA,OAEpF,WAAkB;EAAE,IAAI,aAAa;EAAM,OAAO,EAAE,iBAAe,UAAA,MAAY;CAAE,GAAG,IAAI,GAAC,CAAA,SAAA,KAAA,CAAA;AAIhG,GAAA;CAAA,MAAA;CAAA,OAAA,CAAA,WAAA;AAAA,CAAA"}
@@ -0,0 +1,54 @@
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import type { VNodeChild } from 'vue';
3
+ import { type IconData } from '../base/Icon';
4
+ import { type PartProps } from '../utils/props';
5
+ /** 未声明的属性落到栏(div)上 */
6
+ export interface TabBarProps extends Omit<PartProps<'div', 'role' | 'placeholder'>, 'onChange'> {
7
+ /** 选中的项;双向绑定写 `_value={x}` */
8
+ _value?: string;
9
+ /**
10
+ * 固定在页面底部
11
+ * @default true
12
+ */
13
+ fixed?: boolean;
14
+ /**
15
+ * 固定时在原位置留出同样高的空
16
+ * @default true
17
+ */
18
+ placeholder?: boolean;
19
+ /**
20
+ * 顶部的细线
21
+ * @default true
22
+ */
23
+ border?: boolean;
24
+ /** 换了一项 */
25
+ onChange?: (name: string) => void;
26
+ /** 各个 TabBarItem */
27
+ children?: VNodeChild;
28
+ }
29
+ /** TabBar、TabBarItem 的样式 */
30
+ export declare const tabBarStyles: Readonly<{
31
+ border: css.CompiledStyles;
32
+ fixed: css.CompiledStyles;
33
+ icon: css.CompiledStyles;
34
+ item: css.CompiledStyles;
35
+ placeholder: css.CompiledStyles;
36
+ root: css.CompiledStyles;
37
+ }>;
38
+ /** 标签栏(div[role=tablist]) */
39
+ export declare const TabBar: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<TabBarProps>;
40
+ /** 未声明的属性落到按钮上 */
41
+ export interface TabBarItemProps extends PartProps<'button', 'role' | 'aria-selected' | 'type' | 'name'> {
42
+ /** 名字:选中的状态按它记 */
43
+ name: string;
44
+ /** 图标 */
45
+ icon?: IconData;
46
+ /** 选中时的图标(不给时用 icon,只换成主色) */
47
+ activeIcon?: IconData;
48
+ /** 图标右上角的徽标:数字、文字,true 是小红点 */
49
+ badge?: number | string | boolean;
50
+ /** 文字 */
51
+ children?: VNodeChild;
52
+ }
53
+ /** 标签栏的一项(button[role=tab]) */
54
+ export declare const TabBarItem: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<TabBarItemProps>;
@@ -0,0 +1,138 @@
1
+ import { hasContent, mergeAttrs } from "../utils/props.js";
2
+ import { Icon } from "../base/Icon.js";
3
+ import { Badge } from "../display/Badge.js";
4
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
5
+ import { _component, bindable, childrenProp, createContext, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode, isVNode } from "vue";
7
+ //#region src/navigation/TabBar.tsx
8
+ /** 标签栏提供给各项的 */
9
+ function _isSlot(s) {
10
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
11
+ }
12
+ var TabBarContext = createContext("TabBar");
13
+ /** 未声明的属性落到栏(div)上 */
14
+ /** TabBar、TabBarItem 的样式 */
15
+ var tabBarStyles = css.create({
16
+ root: {
17
+ boxSizing: "content-box",
18
+ display: "flex",
19
+ height: "3.5em",
20
+ paddingBlockEnd: "env(safe-area-inset-bottom)",
21
+ backgroundColor: "_surface",
22
+ fontSize: "_md"
23
+ },
24
+ fixed: {
25
+ position: "fixed",
26
+ insetBlockEnd: 0,
27
+ insetInline: 0,
28
+ zIndex: 1e3
29
+ },
30
+ border: {
31
+ borderBlockStartWidth: "_hairline",
32
+ borderBlockStartStyle: "solid",
33
+ borderBlockStartColor: "_border"
34
+ },
35
+ placeholder: {
36
+ height: "calc(3.5em + env(safe-area-inset-bottom))",
37
+ fontSize: "_md"
38
+ },
39
+ item: {
40
+ flex: "1 1 0",
41
+ display: "flex",
42
+ flexDirection: "column",
43
+ alignItems: "center",
44
+ justifyContent: "center",
45
+ gap: "0.2em",
46
+ margin: 0,
47
+ padding: 0,
48
+ borderWidth: 0,
49
+ backgroundColor: "transparent",
50
+ color: {
51
+ default: "_textMuted",
52
+ "[aria-selected=\"true\"]": "_accentText"
53
+ },
54
+ fontFamily: "inherit",
55
+ fontSize: "_xs",
56
+ cursor: "pointer",
57
+ userSelect: "none"
58
+ },
59
+ icon: { fontSize: "1.65em" }
60
+ });
61
+ /** 标签栏(div[role=tablist]) */
62
+ var TabBar = /*#__PURE__*/ _component((_props, _ctx) => {
63
+ const value = bindable(_props, "_value", () => void 0, _ctx.emit);
64
+ const fixed = readonlyProp(_props, "fixed", true);
65
+ const placeholder = readonlyProp(_props, "placeholder", true);
66
+ const border = readonlyProp(_props, "border", true);
67
+ const onChange = readonlyProp(_props, "onChange");
68
+ const children = childrenProp(_props);
69
+ const rest = restProps(_props, _ctx, false);
70
+ TabBarContext.provide({
71
+ get value() {
72
+ return value.value;
73
+ },
74
+ select(name) {
75
+ if (name === value.value) return;
76
+ value.value = name;
77
+ onChange.value?.(name);
78
+ }
79
+ });
80
+ return () => {
81
+ const bar = createVNode("div", mergeAttrs({ sx: [
82
+ tabBarStyles.root,
83
+ fixed.value && tabBarStyles.fixed,
84
+ border.value && tabBarStyles.border
85
+ ] }, rest, { role: "tablist" }), [children.value]);
86
+ return fixed.value && placeholder.value ? [createVNode("div", mergeAttrs({ sx: tabBarStyles.placeholder }), null), bar] : bar;
87
+ };
88
+ }, {
89
+ name: "TabBar",
90
+ props: [
91
+ "_value",
92
+ "onUpdate:_value",
93
+ "fixed",
94
+ "placeholder",
95
+ "border",
96
+ "onChange"
97
+ ]
98
+ });
99
+ /** 未声明的属性落到按钮上 */
100
+ /** 标签栏的一项(button[role=tab]) */
101
+ var TabBarItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
102
+ const name = readonlyProp(_props2, "name");
103
+ const icon = readonlyProp(_props2, "icon");
104
+ const activeIcon = readonlyProp(_props2, "activeIcon");
105
+ const badge = readonlyProp(_props2, "badge");
106
+ const children = childrenProp(_props2);
107
+ const rest = restProps(_props2, _ctx2, false);
108
+ const bar = TabBarContext.inject();
109
+ return () => {
110
+ const selected = bar.value === name.value;
111
+ const current = selected && activeIcon.value || icon.value;
112
+ const glyph = current && createVNode(Icon, {
113
+ "icon": current,
114
+ "sx": tabBarStyles.icon
115
+ }, null);
116
+ return createVNode("button", mergeAttrs({ sx: tabBarStyles.item }, rest, {
117
+ type: "button",
118
+ role: "tab",
119
+ "aria-selected": selected ? "true" : "false",
120
+ onClick: () => bar.select(name.value)
121
+ }), [glyph && (badge.value === void 0 || badge.value === false ? glyph : createVNode(Badge, {
122
+ "content": badge.value === true ? void 0 : badge.value,
123
+ "dot": badge.value === true
124
+ }, _isSlot(glyph) ? glyph : { default: () => [glyph] })), hasContent(children.value) && createVNode("span", null, [children.value])]);
125
+ };
126
+ }, {
127
+ name: "TabBarItem",
128
+ props: [
129
+ "name",
130
+ "icon",
131
+ "activeIcon",
132
+ "badge"
133
+ ]
134
+ });
135
+ //#endregion
136
+ export { TabBar, TabBarItem, tabBarStyles };
137
+
138
+ //# sourceMappingURL=TabBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBar.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/navigation/TabBar.tsx"],"sourcesContent":["/**\n * 标签栏:页面底部的一排入口(首页、分类、购物车、我的),图标加文字,选中的用主色,可带徽标。\n *\n * <TabBar _value={tab}>\n * <TabBarItem name=\"home\" icon={House}>首页</TabBarItem>\n * <TabBarItem name=\"cart\" icon={ShoppingCart} badge={3}>购物车</TabBarItem>\n * </TabBar>\n *\n * 默认固定在底部、让出全面屏的安全区,并在原位置留出同样高的空。小程序也有原生的 tabBar(app.json),\n * 这一个是页面里自己画的,样式与 H5 一致。\n */\nimport { _component, createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { Badge } from '../display/Badge';\nimport { hasContent, mergeAttrs, type PartProps } from '../utils/props';\n\n/** 标签栏提供给各项的 */\ninterface TabBarState {\n readonly value: string | undefined;\n select(name: string): void;\n}\n\nconst TabBarContext = createContext<TabBarState>('TabBar');\n\n/** 未声明的属性落到栏(div)上 */\nexport interface TabBarProps extends Omit<PartProps<'div', 'role' | 'placeholder'>, 'onChange'> {\n /** 选中的项;双向绑定写 `_value={x}` */\n _value?: string;\n /**\n * 固定在页面底部\n * @default true\n */\n fixed?: boolean;\n /**\n * 固定时在原位置留出同样高的空\n * @default true\n */\n placeholder?: boolean;\n /**\n * 顶部的细线\n * @default true\n */\n border?: boolean;\n /** 换了一项 */\n onChange?: (name: string) => void;\n /** 各个 TabBarItem */\n children?: VNodeChild;\n}\n\n/** TabBar、TabBarItem 的样式 */\nexport const tabBarStyles = css.create({\n root: {\n boxSizing: 'content-box',\n display: 'flex',\n height: '3.5em',\n paddingBlockEnd: 'env(safe-area-inset-bottom)',\n backgroundColor: '_surface',\n fontSize: '_md',\n },\n fixed: { position: 'fixed', insetBlockEnd: 0, insetInline: 0, zIndex: 1000 },\n border: {\n borderBlockStartWidth: '_hairline',\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_border',\n },\n placeholder: { height: 'calc(3.5em + env(safe-area-inset-bottom))', fontSize: '_md' },\n item: {\n flex: '1 1 0',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '0.2em',\n margin: 0,\n padding: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n color: { default: '_textMuted', '[aria-selected=\"true\"]': '_accentText' },\n fontFamily: 'inherit',\n fontSize: '_xs',\n cursor: 'pointer',\n userSelect: 'none',\n },\n icon: { fontSize: '1.65em' },\n});\n\n/** 标签栏(div[role=tablist]) */\nexport const TabBar = _component(\n ({\n _value: value = _bindable<string | undefined>(undefined),\n fixed = true,\n placeholder = true,\n border = true,\n onChange,\n children,\n ...rest\n }: TabBarProps) => {\n TabBarContext.provide({\n get value() {\n return value;\n },\n select(name) {\n if (name === value) return;\n value = name;\n onChange?.(name);\n },\n });\n return () => {\n const bar = (\n <div\n {...mergeAttrs<'div'>(\n { sx: [tabBarStyles.root, fixed && tabBarStyles.fixed, border && tabBarStyles.border] },\n rest,\n { role: 'tablist' },\n )}\n >\n {children}\n </div>\n );\n return fixed && placeholder\n ? [<div {...mergeAttrs<'div'>({ sx: tabBarStyles.placeholder })} />, bar]\n : bar;\n };\n },\n);\n\n/** 未声明的属性落到按钮上 */\nexport interface TabBarItemProps extends PartProps<\n 'button',\n 'role' | 'aria-selected' | 'type' | 'name'\n> {\n /** 名字:选中的状态按它记 */\n name: string;\n /** 图标 */\n icon?: IconData;\n /** 选中时的图标(不给时用 icon,只换成主色) */\n activeIcon?: IconData;\n /** 图标右上角的徽标:数字、文字,true 是小红点 */\n badge?: number | string | boolean;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** 标签栏的一项(button[role=tab]) */\nexport const TabBarItem = _component(\n ({ name, icon, activeIcon, badge, children, ...rest }: TabBarItemProps) => {\n const bar = TabBarContext.inject();\n return () => {\n const selected = bar.value === name;\n const current = (selected && activeIcon) || icon;\n const glyph = current && <Icon icon={current} sx={tabBarStyles.icon} />;\n return (\n <button\n {...mergeAttrs<'button'>({ sx: tabBarStyles.item }, rest, {\n type: 'button',\n role: 'tab',\n 'aria-selected': selected ? 'true' : 'false',\n onClick: () => bar.select(name),\n })}\n >\n {glyph &&\n (badge === undefined || badge === false ? (\n glyph\n ) : (\n <Badge content={badge === true ? undefined : badge} dot={badge === true}>\n {glyph}\n </Badge>\n ))}\n {hasContent(children) && <span>{children}</span>}\n </button>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import { type VNodeChild } from 'vue';
3
+ import { type PartProps } from '../utils/props';
4
+ /** 未声明的属性落到根元素(div)上 */
5
+ export interface TabsProps extends Omit<PartProps<'div'>, 'onChange'> {
6
+ /** 选中的标签;双向绑定写 `_value={x}`。不给时选第一个 */
7
+ _value?: string;
8
+ /** 左右滑内容切换标签 */
9
+ swipeable?: boolean;
10
+ /** 标题栏吸顶 */
11
+ sticky?: boolean;
12
+ /** 吸顶时离顶部多远(CSS 长度) */
13
+ offsetTop?: string;
14
+ /** 换了标签 */
15
+ onChange?: (name: string) => void;
16
+ /** 各个 Tab */
17
+ children?: VNodeChild;
18
+ /** 标题栏的部件属性 */
19
+ propsNav?: PartProps<'div'>;
20
+ }
21
+ /** Tabs、Tab 的样式 */
22
+ export declare const tabsStyles: Readonly<{
23
+ line: css.CompiledStyles;
24
+ nav: css.CompiledStyles;
25
+ panel: css.CompiledStyles;
26
+ scrollable: css.CompiledStyles;
27
+ tab: css.CompiledStyles;
28
+ }>;
29
+ /** 标签页(div > 标题栏 + 内容) */
30
+ export declare const Tabs: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<TabsProps>;
31
+ /** 未声明的属性落到内容(div)上 */
32
+ export interface TabProps extends PartProps<'div', 'role' | 'title' | 'hidden'> {
33
+ /** 名字:选中的状态按它记 */
34
+ name: string;
35
+ /** 标题 */
36
+ title: VNodeChild;
37
+ /** 不能选 */
38
+ disabled?: boolean;
39
+ /** 标题右上角的徽标:数字、文字,true 是小红点 */
40
+ badge?: number | string | boolean;
41
+ /** 内容 */
42
+ children?: VNodeChild;
43
+ }
44
+ /** 标签(div[role=tabpanel]):第一次选中时才渲染内容,切走后藏起来 */
45
+ export declare const Tab: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<TabProps>;
@@ -0,0 +1,206 @@
1
+ import { dataAttrs, mergeAttrs } from "../utils/props.js";
2
+ import { Badge } from "../display/Badge.js";
3
+ import { Sticky } from "./Sticky.js";
4
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
5
+ import { _component, bindable, childrenProp, createContext, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode, isVNode, onBeforeUnmount, shallowReactive } from "vue";
7
+ //#region src/navigation/Tabs.tsx
8
+ /** 一个标签登记给标签页的 */
9
+ /** 标签页提供给各个标签的 */
10
+ function _isSlot(s) {
11
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
12
+ }
13
+ var TabsContext = createContext("Tabs");
14
+ /** 未声明的属性落到根元素(div)上 */
15
+ /** Tabs、Tab 的样式 */
16
+ var tabsStyles = css.create({
17
+ nav: {
18
+ display: "flex",
19
+ overflowX: "auto",
20
+ backgroundColor: "_surface",
21
+ borderBlockEndWidth: "_hairline",
22
+ borderBlockEndStyle: "solid",
23
+ borderBlockEndColor: "_border",
24
+ scrollbarWidth: "none"
25
+ },
26
+ tab: {
27
+ position: "relative",
28
+ flex: "1 0 auto",
29
+ display: "inline-flex",
30
+ alignItems: "center",
31
+ justifyContent: "center",
32
+ minWidth: "4.5em",
33
+ height: "2.9em",
34
+ margin: 0,
35
+ paddingBlock: 0,
36
+ paddingInline: "_md",
37
+ borderWidth: 0,
38
+ backgroundColor: "transparent",
39
+ color: {
40
+ default: "_textMuted",
41
+ "[aria-selected=\"true\"]": "_text",
42
+ "[disabled]": "_textDisabled"
43
+ },
44
+ fontFamily: "inherit",
45
+ fontSize: "_md",
46
+ fontWeight: {
47
+ default: "_normal",
48
+ "[aria-selected=\"true\"]": "_semibold"
49
+ },
50
+ whiteSpace: "nowrap",
51
+ cursor: {
52
+ default: "pointer",
53
+ "[disabled]": "not-allowed"
54
+ }
55
+ },
56
+ scrollable: { flex: "none" },
57
+ line: {
58
+ position: "absolute",
59
+ insetBlockEnd: 0,
60
+ insetInlineStart: "50%",
61
+ width: "1.6em",
62
+ height: "0.2em",
63
+ borderRadius: "_full",
64
+ backgroundColor: "_accent",
65
+ transform: {
66
+ default: "translateX(-50%) scaleX(0)",
67
+ "[data-selected]": "translateX(-50%) scaleX(1)"
68
+ },
69
+ transitionProperty: "transform",
70
+ transitionDuration: "_md",
71
+ transitionTimingFunction: "_standard"
72
+ },
73
+ panel: { display: {
74
+ default: "block",
75
+ "[hidden]": "none"
76
+ } }
77
+ });
78
+ /** 两次触摸之间横向移动多少(px)算滑动 */
79
+ var SWIPE_DISTANCE = 50;
80
+ /** 标签页(div > 标题栏 + 内容) */
81
+ var Tabs = /*#__PURE__*/ _component((_props, _ctx) => {
82
+ const value = bindable(_props, "_value", () => void 0, _ctx.emit);
83
+ const swipeable = readonlyProp(_props, "swipeable", false);
84
+ const sticky = readonlyProp(_props, "sticky", false);
85
+ const offsetTop = readonlyProp(_props, "offsetTop");
86
+ const onChange = readonlyProp(_props, "onChange");
87
+ const children = childrenProp(_props);
88
+ const propsNav = readonlyProp(_props, "propsNav");
89
+ const rest = restProps(_props, _ctx, false);
90
+ const entries = shallowReactive([]);
91
+ const current = () => value.value ?? entries.find((entry) => !entry.disabled)?.name;
92
+ const select = (name) => {
93
+ if (name === current()) return;
94
+ value.value = name;
95
+ onChange.value?.(name);
96
+ };
97
+ TabsContext.provide({
98
+ get value() {
99
+ return current();
100
+ },
101
+ register(entry) {
102
+ entries.push(entry);
103
+ return () => entries.splice(entries.indexOf(entry), 1);
104
+ }
105
+ });
106
+ let start = null;
107
+ const onTouchstart = (event) => {
108
+ const touch = event.touches[0];
109
+ start = touch ? {
110
+ x: touch.clientX,
111
+ y: touch.clientY
112
+ } : null;
113
+ };
114
+ const onTouchend = (event) => {
115
+ const touch = event.changedTouches[0];
116
+ if (!start || !touch) return;
117
+ const dx = touch.clientX - start.x;
118
+ const dy = touch.clientY - start.y;
119
+ start = null;
120
+ if (Math.abs(dx) < SWIPE_DISTANCE || Math.abs(dx) < Math.abs(dy) * 1.5) return;
121
+ const enabled = entries.filter((entry) => !entry.disabled);
122
+ const next = enabled[enabled.findIndex((entry) => entry.name === current()) + (dx < 0 ? 1 : -1)];
123
+ if (next) select(next.name);
124
+ };
125
+ return () => {
126
+ const active = current();
127
+ const scrollable = entries.length > 4;
128
+ const nav = createVNode("div", mergeAttrs({ sx: tabsStyles.nav }, propsNav.value, { role: "tablist" }), [entries.map((entry) => {
129
+ const selected = entry.name === active;
130
+ const title = entry.badge === void 0 || entry.badge === false ? entry.title : createVNode(Badge, {
131
+ "content": entry.badge === true ? void 0 : entry.badge,
132
+ "dot": entry.badge === true
133
+ }, { default: () => [entry.title] });
134
+ return createVNode("button", mergeAttrs({ sx: [tabsStyles.tab, scrollable && tabsStyles.scrollable] }, {
135
+ type: "button",
136
+ role: "tab",
137
+ "aria-selected": selected ? "true" : "false",
138
+ disabled: entry.disabled,
139
+ onClick: () => select(entry.name)
140
+ }), [title, createVNode("span", mergeAttrs({ sx: tabsStyles.line }, dataAttrs({ "data-selected": selected })), null)]);
141
+ })]);
142
+ return createVNode("div", mergeAttrs({}, rest, swipeable.value ? {
143
+ onTouchstart,
144
+ onTouchend
145
+ } : {}), [sticky.value ? createVNode(Sticky, { "offsetTop": offsetTop.value }, _isSlot(nav) ? nav : { default: () => [nav] }) : nav, children.value]);
146
+ };
147
+ }, {
148
+ name: "Tabs",
149
+ props: [
150
+ "_value",
151
+ "onUpdate:_value",
152
+ "swipeable",
153
+ "sticky",
154
+ "offsetTop",
155
+ "onChange",
156
+ "propsNav"
157
+ ]
158
+ });
159
+ /** 未声明的属性落到内容(div)上 */
160
+ /** 标签(div[role=tabpanel]):第一次选中时才渲染内容,切走后藏起来 */
161
+ var Tab = /*#__PURE__*/ _component((_props2, _ctx2) => {
162
+ const name = readonlyProp(_props2, "name");
163
+ const title = readonlyProp(_props2, "title");
164
+ const disabled = readonlyProp(_props2, "disabled", false);
165
+ const badge = readonlyProp(_props2, "badge");
166
+ const children = childrenProp(_props2);
167
+ const rest = restProps(_props2, _ctx2, false);
168
+ const tabs = TabsContext.inject();
169
+ const unregister = tabs.register({
170
+ get name() {
171
+ return name.value;
172
+ },
173
+ get title() {
174
+ return title.value;
175
+ },
176
+ get disabled() {
177
+ return disabled.value;
178
+ },
179
+ get badge() {
180
+ return badge.value;
181
+ }
182
+ });
183
+ onBeforeUnmount(unregister);
184
+ let visited = false;
185
+ return () => {
186
+ const active = tabs.value === name.value;
187
+ if (active) visited = true;
188
+ if (!visited) return null;
189
+ return createVNode("div", mergeAttrs({ sx: tabsStyles.panel }, rest, {
190
+ role: "tabpanel",
191
+ hidden: !active
192
+ }), [children.value]);
193
+ };
194
+ }, {
195
+ name: "Tab",
196
+ props: [
197
+ "name",
198
+ "title",
199
+ "disabled",
200
+ "badge"
201
+ ]
202
+ });
203
+ //#endregion
204
+ export { Tab, Tabs, tabsStyles };
205
+
206
+ //# sourceMappingURL=Tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/navigation/Tabs.tsx"],"sourcesContent":["/**\n * 标签页:一排标题切换下面的内容(全部、待付款、待收货)。选中的标题下面一条主色短线;可以左右滑内容切换,标题栏可以吸顶。\n *\n * <Tabs _value={status} swipeable sticky>\n * <Tab name=\"all\" title=\"全部\">…</Tab>\n * <Tab name=\"unpaid\" title=\"待付款\" badge={2}>…</Tab>\n * </Tabs>\n *\n * 内容在第一次切到时才渲染,之后切走只是藏起来(保留滚动、输入的状态)。标题多于 4 个时标题栏可以横向滚动。\n */\nimport { _component, createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, shallowReactive, type VNodeChild } from 'vue';\nimport { Badge } from '../display/Badge';\nimport { dataAttrs, mergeAttrs, type PartProps } from '../utils/props';\nimport { Sticky } from './Sticky';\n\n/** 一个标签登记给标签页的 */\ninterface TabEntry {\n readonly name: string;\n readonly title: VNodeChild;\n readonly disabled: boolean;\n readonly badge: number | string | boolean | undefined;\n}\n\n/** 标签页提供给各个标签的 */\ninterface TabsState {\n readonly value: string | undefined;\n register(entry: TabEntry): () => void;\n}\n\nconst TabsContext = createContext<TabsState>('Tabs');\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface TabsProps extends Omit<PartProps<'div'>, 'onChange'> {\n /** 选中的标签;双向绑定写 `_value={x}`。不给时选第一个 */\n _value?: string;\n /** 左右滑内容切换标签 */\n swipeable?: boolean;\n /** 标题栏吸顶 */\n sticky?: boolean;\n /** 吸顶时离顶部多远(CSS 长度) */\n offsetTop?: string;\n /** 换了标签 */\n onChange?: (name: string) => void;\n /** 各个 Tab */\n children?: VNodeChild;\n /** 标题栏的部件属性 */\n propsNav?: PartProps<'div'>;\n}\n\n/** Tabs、Tab 的样式 */\nexport const tabsStyles = css.create({\n nav: {\n display: 'flex',\n overflowX: 'auto',\n backgroundColor: '_surface',\n borderBlockEndWidth: '_hairline',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_border',\n scrollbarWidth: 'none',\n },\n tab: {\n position: 'relative',\n flex: '1 0 auto',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: '4.5em',\n height: '2.9em',\n margin: 0,\n paddingBlock: 0,\n paddingInline: '_md',\n borderWidth: 0,\n backgroundColor: 'transparent',\n color: {\n default: '_textMuted',\n '[aria-selected=\"true\"]': '_text',\n '[disabled]': '_textDisabled',\n },\n fontFamily: 'inherit',\n fontSize: '_md',\n fontWeight: { default: '_normal', '[aria-selected=\"true\"]': '_semibold' },\n whiteSpace: 'nowrap',\n cursor: { default: 'pointer', '[disabled]': 'not-allowed' },\n },\n // 少于 5 个时平分整行;多了按内容宽度排、可以横向滚动\n scrollable: { flex: 'none' },\n line: {\n position: 'absolute',\n insetBlockEnd: 0,\n insetInlineStart: '50%',\n width: '1.6em',\n height: '0.2em',\n borderRadius: '_full',\n backgroundColor: '_accent',\n transform: {\n default: 'translateX(-50%) scaleX(0)',\n '[data-selected]': 'translateX(-50%) scaleX(1)',\n },\n transitionProperty: 'transform',\n transitionDuration: '_md',\n transitionTimingFunction: '_standard',\n },\n panel: { display: { default: 'block', '[hidden]': 'none' } },\n});\n\n/** 两次触摸之间横向移动多少(px)算滑动 */\nconst SWIPE_DISTANCE = 50;\n\n/** 标签页(div > 标题栏 + 内容) */\nexport const Tabs = _component(\n ({\n _value: value = _bindable<string | undefined>(undefined),\n swipeable = false,\n sticky = false,\n offsetTop,\n onChange,\n children,\n propsNav,\n ...rest\n }: TabsProps) => {\n const entries = shallowReactive<TabEntry[]>([]);\n const current = () => value ?? entries.find((entry) => !entry.disabled)?.name;\n const select = (name: string) => {\n if (name === current()) return;\n value = name;\n onChange?.(name);\n };\n TabsContext.provide({\n get value() {\n return current();\n },\n register(entry) {\n entries.push(entry);\n return () => entries.splice(entries.indexOf(entry), 1);\n },\n });\n\n // 左右滑内容:按下与松手的位置比较(滑动不需要 touchmove,页面照常竖着滚)\n let start: { x: number; y: number } | null = null;\n const onTouchstart = (event: TouchEvent) => {\n const touch = event.touches[0];\n start = touch ? { x: touch.clientX, y: touch.clientY } : null;\n };\n const onTouchend = (event: TouchEvent) => {\n const touch = event.changedTouches[0];\n if (!start || !touch) return;\n const dx = touch.clientX - start.x;\n const dy = touch.clientY - start.y;\n start = null;\n if (Math.abs(dx) < SWIPE_DISTANCE || Math.abs(dx) < Math.abs(dy) * 1.5) return;\n const enabled = entries.filter((entry) => !entry.disabled);\n const index = enabled.findIndex((entry) => entry.name === current());\n const next = enabled[index + (dx < 0 ? 1 : -1)];\n if (next) select(next.name);\n };\n\n return () => {\n const active = current();\n const scrollable = entries.length > 4;\n const nav = (\n <div {...mergeAttrs<'div'>({ sx: tabsStyles.nav }, propsNav, { role: 'tablist' })}>\n {entries.map((entry) => {\n const selected = entry.name === active;\n const title =\n entry.badge === undefined || entry.badge === false ? (\n entry.title\n ) : (\n <Badge\n content={entry.badge === true ? undefined : entry.badge}\n dot={entry.badge === true}\n >\n {entry.title}\n </Badge>\n );\n return (\n <button\n {...mergeAttrs<'button'>(\n { sx: [tabsStyles.tab, scrollable && tabsStyles.scrollable] },\n {\n type: 'button',\n role: 'tab',\n 'aria-selected': selected ? 'true' : 'false',\n disabled: entry.disabled,\n onClick: () => select(entry.name),\n },\n )}\n >\n {title}\n <span\n {...mergeAttrs<'span'>(\n { sx: tabsStyles.line },\n dataAttrs({ 'data-selected': selected }),\n )}\n />\n </button>\n );\n })}\n </div>\n );\n return (\n <div {...mergeAttrs<'div'>({}, rest, swipeable ? { onTouchstart, onTouchend } : {})}>\n {sticky ? <Sticky offsetTop={offsetTop}>{nav}</Sticky> : nav}\n {children}\n </div>\n );\n };\n },\n);\n\n/** 未声明的属性落到内容(div)上 */\nexport interface TabProps extends PartProps<'div', 'role' | 'title' | 'hidden'> {\n /** 名字:选中的状态按它记 */\n name: string;\n /** 标题 */\n title: VNodeChild;\n /** 不能选 */\n disabled?: boolean;\n /** 标题右上角的徽标:数字、文字,true 是小红点 */\n badge?: number | string | boolean;\n /** 内容 */\n children?: VNodeChild;\n}\n\n/** 标签(div[role=tabpanel]):第一次选中时才渲染内容,切走后藏起来 */\nexport const Tab = _component(\n ({ name, title, disabled = false, badge, children, ...rest }: TabProps) => {\n const tabs = TabsContext.inject();\n const unregister = tabs.register({\n get name() {\n return name;\n },\n get title() {\n return title;\n },\n get disabled() {\n return disabled;\n },\n get badge() {\n return badge;\n },\n });\n onBeforeUnmount(unregister);\n let visited = false;\n return () => {\n const active = tabs.value === name;\n if (active) visited = true;\n if (!visited) return null;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: tabsStyles.panel }, rest, {\n role: 'tabpanel',\n hidden: !active,\n })}\n >\n {children}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import type { VNodeChild } from 'vue';
3
+ import { type IconData } from '../base/Icon';
4
+ import { type PartProps } from '../utils/props';
5
+ import { type PopupProps } from './Popup';
6
+ /** 一个操作项 */
7
+ export interface ActionSheetAction {
8
+ /** 名称 */
9
+ name: VNodeChild;
10
+ /** 名称下的说明 */
11
+ description?: VNodeChild;
12
+ /** 名称前的图标 */
13
+ icon?: IconData;
14
+ /** 色调:删除这类操作用 danger */
15
+ tone?: 'accent' | 'danger';
16
+ /** 禁用 */
17
+ disabled?: boolean;
18
+ /** 加载中:显示转圈,不能选 */
19
+ loading?: boolean;
20
+ }
21
+ /** 关闭的原因 */
22
+ export type ActionSheetCloseReason = 'select' | 'cancel' | 'overlay';
23
+ /** 未声明的属性落到面板(弹出层的 div)上 */
24
+ export interface ActionSheetProps extends Omit<PartProps<'div', 'role'>, 'title' | 'onSelect'> {
25
+ /** 是否打开;双向绑定写 `_open={x}` */
26
+ _open?: boolean;
27
+ /** 操作项 */
28
+ actions?: ActionSheetAction[];
29
+ /** 标题 */
30
+ title?: VNodeChild;
31
+ /** 标题下的说明 */
32
+ description?: VNodeChild;
33
+ /**
34
+ * 显示取消
35
+ * @default true
36
+ */
37
+ showCancel?: boolean;
38
+ /** 取消的文字;不给时用语言包的"取消" */
39
+ cancelText?: VNodeChild;
40
+ /**
41
+ * 选了之后关闭
42
+ * @default true
43
+ */
44
+ closeOnSelect?: boolean;
45
+ /**
46
+ * 点遮罩关闭(等于取消)
47
+ * @default true
48
+ */
49
+ closeOnOverlay?: boolean;
50
+ /** 选了一项 */
51
+ onSelect?: (action: ActionSheetAction, index: number) => void;
52
+ /** 点了取消(或点遮罩关闭) */
53
+ onCancel?: () => void;
54
+ /** 关闭时带原因 */
55
+ onOpenChange?: (open: boolean, details: {
56
+ reason: ActionSheetCloseReason;
57
+ }) => void;
58
+ /** 自定义内容(代替操作项) */
59
+ children?: VNodeChild;
60
+ /** 弹出层的部件属性 */
61
+ propsPopup?: Partial<PopupProps>;
62
+ /** 每个操作项(button)的部件属性 */
63
+ propsAction?: PartProps<'button'>;
64
+ /** 取消(button)的部件属性 */
65
+ propsCancel?: PartProps<'button'>;
66
+ }
67
+ /** ActionSheet 的样式:header、title、description、action、各色调、actionDescription、gap、cancel */
68
+ export declare const actionSheetStyles: Readonly<{
69
+ accent: css.CompiledStyles;
70
+ action: css.CompiledStyles;
71
+ actionDescription: css.CompiledStyles;
72
+ danger: css.CompiledStyles;
73
+ description: css.CompiledStyles;
74
+ gap: css.CompiledStyles;
75
+ header: css.CompiledStyles;
76
+ name: css.CompiledStyles;
77
+ title: css.CompiledStyles;
78
+ }>;
79
+ /** 动作面板(弹出层 > 标题 + 操作项 + 取消) */
80
+ export declare const ActionSheet: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<ActionSheetProps>;