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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,164 @@
1
+ import { useConfig } from "../config/context.js";
2
+ import { dataAttrs, hasContent, mergeAttrs, mergePartProps, mergeProps } from "../utils/props.js";
3
+ import { Icon } from "../base/Icon.js";
4
+ import { Loading } from "../feedback/Loading.js";
5
+ import { Popup } from "./Popup.js";
6
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
7
+ import { _component, bindable, childrenProp, childrenStable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { createVNode } from "vue";
9
+ //#region src/overlay/ActionSheet.tsx
10
+ /** 一个操作项 */
11
+ /** 关闭的原因 */
12
+ /** 未声明的属性落到面板(弹出层的 div)上 */
13
+ /** ActionSheet 的样式:header、title、description、action、各色调、actionDescription、gap、cancel */
14
+ var actionSheetStyles = css.create({
15
+ header: {
16
+ paddingBlock: "1em",
17
+ paddingInline: "_lg",
18
+ textAlign: "center",
19
+ borderBlockEndWidth: "_hairline",
20
+ borderBlockEndStyle: "solid",
21
+ borderBlockEndColor: "_border"
22
+ },
23
+ title: {
24
+ fontSize: "_lg",
25
+ fontWeight: "_semibold",
26
+ lineHeight: "_tight",
27
+ color: "_text"
28
+ },
29
+ description: {
30
+ marginBlockStart: "0.4em",
31
+ fontSize: "_sm",
32
+ color: "_textMuted"
33
+ },
34
+ action: {
35
+ boxSizing: "border-box",
36
+ display: "flex",
37
+ flexDirection: "column",
38
+ alignItems: "center",
39
+ justifyContent: "center",
40
+ width: "100%",
41
+ minHeight: "3.5em",
42
+ paddingBlock: "0.7em",
43
+ paddingInline: "_lg",
44
+ margin: 0,
45
+ borderWidth: 0,
46
+ backgroundColor: {
47
+ default: "_surface",
48
+ ":active:not([data-disabled]):not([data-loading])": "_fillActive"
49
+ },
50
+ color: "_text",
51
+ fontFamily: "inherit",
52
+ fontSize: "_lg",
53
+ lineHeight: "1.4",
54
+ textAlign: "center",
55
+ cursor: {
56
+ default: "pointer",
57
+ "[data-disabled]": "not-allowed"
58
+ },
59
+ opacity: {
60
+ default: 1,
61
+ "[data-disabled]": "_disabled"
62
+ },
63
+ transitionProperty: "background-color",
64
+ transitionDuration: "_xs"
65
+ },
66
+ accent: { color: "_accentText" },
67
+ danger: { color: "_dangerText" },
68
+ name: {
69
+ display: "inline-flex",
70
+ alignItems: "center",
71
+ gap: "0.4em"
72
+ },
73
+ actionDescription: {
74
+ marginBlockStart: "0.2em",
75
+ fontSize: "_xs",
76
+ color: "_textMuted"
77
+ },
78
+ gap: {
79
+ height: "0.5em",
80
+ backgroundColor: "_background"
81
+ }
82
+ });
83
+ /** 动作面板(弹出层 > 标题 + 操作项 + 取消) */
84
+ var ActionSheet = /*#__PURE__*/ _component((_props, _ctx) => {
85
+ const open = bindable(_props, "_open", () => false, _ctx.emit);
86
+ const actions = readonlyProp(_props, "actions", () => []);
87
+ const title = readonlyProp(_props, "title");
88
+ const description = readonlyProp(_props, "description");
89
+ const showCancel = readonlyProp(_props, "showCancel", true);
90
+ const cancelText = readonlyProp(_props, "cancelText");
91
+ const closeOnSelect = readonlyProp(_props, "closeOnSelect", true);
92
+ const closeOnOverlay = readonlyProp(_props, "closeOnOverlay", true);
93
+ const onSelect = readonlyProp(_props, "onSelect");
94
+ const onCancel = readonlyProp(_props, "onCancel");
95
+ const onOpenChange = readonlyProp(_props, "onOpenChange");
96
+ const children = childrenProp(_props);
97
+ const propsPopup = readonlyProp(_props, "propsPopup");
98
+ const propsAction = readonlyProp(_props, "propsAction");
99
+ const propsCancel = readonlyProp(_props, "propsCancel");
100
+ const rest = restProps(_props, _ctx, false);
101
+ const config = useConfig();
102
+ const close = (reason) => {
103
+ open.value = false;
104
+ onOpenChange.value?.(false, { reason });
105
+ };
106
+ const cancel = (reason) => {
107
+ onCancel.value?.();
108
+ close(reason);
109
+ };
110
+ const select = (action, index) => {
111
+ if (action.disabled || action.loading) return;
112
+ onSelect.value?.(action, index);
113
+ if (closeOnSelect.value) close("select");
114
+ };
115
+ return () => createVNode(Popup, mergeJsxProps(mergePartProps({
116
+ _open: open.value,
117
+ position: "bottom",
118
+ round: true,
119
+ closeOnOverlay: closeOnOverlay.value,
120
+ onOpenChange: (next, { reason }) => !next && reason === "overlay" && cancel("overlay")
121
+ }, mergeProps(rest, propsPopup.value)), { "key": "__site0" }), {
122
+ default: () => [
123
+ (hasContent(title.value) || hasContent(description.value)) && createVNode("div", mergeAttrs({ sx: actionSheetStyles.header }), [hasContent(title.value) && createVNode("div", mergeAttrs({ sx: actionSheetStyles.title }), [title.value]), hasContent(description.value) && createVNode("div", mergeAttrs({ sx: actionSheetStyles.description }), [description.value])]),
124
+ hasContent(children.value) ? children.value : actions.value.map((action, index) => createVNode("button", mergeAttrs({ sx: [actionSheetStyles.action, css.select(() => action.tone && actionSheetStyles[action.tone])] }, propsAction.value, {
125
+ type: "button",
126
+ "aria-disabled": action.disabled ? "true" : void 0,
127
+ "aria-busy": action.loading ? "true" : void 0,
128
+ onClick: () => select(action, index),
129
+ ...dataAttrs({
130
+ "data-disabled": action.disabled,
131
+ "data-loading": action.loading
132
+ })
133
+ }), [action.loading ? createVNode(Loading, { "size": 20 }, null) : createVNode("span", mergeAttrs({ sx: actionSheetStyles.name }), [action.icon && createVNode(Icon, { "icon": action.icon }, null), action.name]), hasContent(action.description) && !action.loading && createVNode("span", mergeAttrs({ sx: actionSheetStyles.actionDescription }), [action.description])])),
134
+ showCancel.value && [createVNode("div", mergeAttrs({ sx: actionSheetStyles.gap }), null), createVNode("button", mergeAttrs({ sx: actionSheetStyles.action }, propsCancel.value, {
135
+ type: "button",
136
+ onClick: () => cancel("cancel")
137
+ }), [cancelText.value ?? config.lang.cancel])]
138
+ ],
139
+ $stable: childrenStable()
140
+ });
141
+ }, {
142
+ name: "ActionSheet",
143
+ props: [
144
+ "_open",
145
+ "onUpdate:_open",
146
+ "actions",
147
+ "title",
148
+ "description",
149
+ "showCancel",
150
+ "cancelText",
151
+ "closeOnSelect",
152
+ "closeOnOverlay",
153
+ "onSelect",
154
+ "onCancel",
155
+ "onOpenChange",
156
+ "propsPopup",
157
+ "propsAction",
158
+ "propsCancel"
159
+ ]
160
+ });
161
+ //#endregion
162
+ export { ActionSheet, actionSheetStyles };
163
+
164
+ //# sourceMappingURL=ActionSheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionSheet.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps","_vtp_childrenStable"],"sources":["../../src/overlay/ActionSheet.tsx"],"sourcesContent":["/**\n * 动作面板:从底部弹出的一列操作(标题、操作项、隔开的取消),用来让用户从几个操作里选一个。\n *\n * <ActionSheet\n * _open={show}\n * title=\"分享到\"\n * actions={[{ name: '微信' }, { name: '朋友圈' }, { name: '删除', tone: 'danger' }]}\n * onSelect={(action, index) => …}\n * />\n *\n * 选了之后默认关闭;有 children 时显示自定义内容,不渲染操作项。\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 { Icon, type IconData } from '../base/Icon';\nimport { useConfig } from '../config/context';\nimport { Loading } from '../feedback/Loading';\nimport {\n dataAttrs,\n hasContent,\n mergeAttrs,\n mergePartProps,\n mergeProps,\n type PartProps,\n} from '../utils/props';\nimport { Popup, type PopupProps } from './Popup';\n\n/** 一个操作项 */\nexport interface ActionSheetAction {\n /** 名称 */\n name: VNodeChild;\n /** 名称下的说明 */\n description?: VNodeChild;\n /** 名称前的图标 */\n icon?: IconData;\n /** 色调:删除这类操作用 danger */\n tone?: 'accent' | 'danger';\n /** 禁用 */\n disabled?: boolean;\n /** 加载中:显示转圈,不能选 */\n loading?: boolean;\n}\n\n/** 关闭的原因 */\nexport type ActionSheetCloseReason = 'select' | 'cancel' | 'overlay';\n\n/** 未声明的属性落到面板(弹出层的 div)上 */\nexport interface ActionSheetProps extends Omit<PartProps<'div', 'role'>, 'title' | 'onSelect'> {\n /** 是否打开;双向绑定写 `_open={x}` */\n _open?: boolean;\n /** 操作项 */\n actions?: ActionSheetAction[];\n /** 标题 */\n title?: VNodeChild;\n /** 标题下的说明 */\n description?: VNodeChild;\n /**\n * 显示取消\n * @default true\n */\n showCancel?: boolean;\n /** 取消的文字;不给时用语言包的\"取消\" */\n cancelText?: VNodeChild;\n /**\n * 选了之后关闭\n * @default true\n */\n closeOnSelect?: boolean;\n /**\n * 点遮罩关闭(等于取消)\n * @default true\n */\n closeOnOverlay?: boolean;\n /** 选了一项 */\n onSelect?: (action: ActionSheetAction, index: number) => void;\n /** 点了取消(或点遮罩关闭) */\n onCancel?: () => void;\n /** 关闭时带原因 */\n onOpenChange?: (open: boolean, details: { reason: ActionSheetCloseReason }) => void;\n /** 自定义内容(代替操作项) */\n children?: VNodeChild;\n /** 弹出层的部件属性 */\n propsPopup?: Partial<PopupProps>;\n /** 每个操作项(button)的部件属性 */\n propsAction?: PartProps<'button'>;\n /** 取消(button)的部件属性 */\n propsCancel?: PartProps<'button'>;\n}\n\n/** ActionSheet 的样式:header、title、description、action、各色调、actionDescription、gap、cancel */\nexport const actionSheetStyles = css.create({\n header: {\n paddingBlock: '1em',\n paddingInline: '_lg',\n textAlign: 'center',\n borderBlockEndWidth: '_hairline',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_border',\n },\n title: { fontSize: '_lg', fontWeight: '_semibold', lineHeight: '_tight', color: '_text' },\n description: { marginBlockStart: '0.4em', fontSize: '_sm', color: '_textMuted' },\n action: {\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n minHeight: '3.5em',\n paddingBlock: '0.7em',\n paddingInline: '_lg',\n margin: 0,\n borderWidth: 0,\n backgroundColor: {\n default: '_surface',\n ':active:not([data-disabled]):not([data-loading])': '_fillActive',\n },\n color: '_text',\n fontFamily: 'inherit',\n fontSize: '_lg',\n lineHeight: '1.4',\n textAlign: 'center',\n cursor: { default: 'pointer', '[data-disabled]': 'not-allowed' },\n opacity: { default: 1, '[data-disabled]': '_disabled' },\n transitionProperty: 'background-color',\n transitionDuration: '_xs',\n },\n accent: { color: '_accentText' },\n danger: { color: '_dangerText' },\n name: { display: 'inline-flex', alignItems: 'center', gap: '0.4em' },\n actionDescription: { marginBlockStart: '0.2em', fontSize: '_xs', color: '_textMuted' },\n gap: { height: '0.5em', backgroundColor: '_background' },\n});\n\n/** 动作面板(弹出层 > 标题 + 操作项 + 取消) */\nexport const ActionSheet = _component(\n ({\n _open: open = _bindable(false),\n actions = [],\n title,\n description,\n showCancel = true,\n cancelText,\n closeOnSelect = true,\n closeOnOverlay = true,\n onSelect,\n onCancel,\n onOpenChange,\n children,\n propsPopup,\n propsAction,\n propsCancel,\n ...rest\n }: ActionSheetProps) => {\n const config = useConfig();\n const close = (reason: ActionSheetCloseReason) => {\n open = false;\n onOpenChange?.(false, { reason });\n };\n const cancel = (reason: 'cancel' | 'overlay') => {\n onCancel?.();\n close(reason);\n };\n const select = (action: ActionSheetAction, index: number) => {\n if (action.disabled || action.loading) return;\n onSelect?.(action, index);\n if (closeOnSelect) close('select');\n };\n return () => (\n <Popup\n {...mergePartProps<PopupProps>(\n {\n _open: open,\n position: 'bottom',\n round: true,\n closeOnOverlay,\n onOpenChange: (next, { reason }) => !next && reason === 'overlay' && cancel('overlay'),\n },\n mergeProps<PopupProps>(rest as Partial<PopupProps>, propsPopup) as Partial<PopupProps>,\n )}\n >\n {(hasContent(title) || hasContent(description)) && (\n <div {...mergeAttrs<'div'>({ sx: actionSheetStyles.header })}>\n {hasContent(title) && (\n <div {...mergeAttrs<'div'>({ sx: actionSheetStyles.title })}>{title}</div>\n )}\n {hasContent(description) && (\n <div {...mergeAttrs<'div'>({ sx: actionSheetStyles.description })}>{description}</div>\n )}\n </div>\n )}\n {hasContent(children)\n ? children\n : actions.map((action, index) => (\n <button\n {...mergeAttrs<'button'>(\n { sx: [actionSheetStyles.action, action.tone && actionSheetStyles[action.tone]] },\n propsAction,\n {\n type: 'button',\n 'aria-disabled': action.disabled ? 'true' : undefined,\n 'aria-busy': action.loading ? 'true' : undefined,\n onClick: () => select(action, index),\n ...dataAttrs({\n 'data-disabled': action.disabled,\n 'data-loading': action.loading,\n }),\n },\n )}\n >\n {action.loading ? (\n <Loading size={20} />\n ) : (\n <span {...mergeAttrs<'span'>({ sx: actionSheetStyles.name })}>\n {action.icon && <Icon icon={action.icon} />}\n {action.name}\n </span>\n )}\n {hasContent(action.description) && !action.loading && (\n <span {...mergeAttrs<'span'>({ sx: actionSheetStyles.actionDescription })}>\n {action.description}\n </span>\n )}\n </button>\n ))}\n {showCancel && [\n <div {...mergeAttrs<'div'>({ sx: actionSheetStyles.gap })} />,\n <button\n {...mergeAttrs<'button'>({ sx: actionSheetStyles.action }, propsCancel, {\n type: 'button',\n onClick: () => cancel('cancel'),\n })}\n >\n {cancelText ?? config.lang.cancel}\n </button>,\n ]}\n </Popup>\n );\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
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 OverlayProps extends PartProps<'div'> {
6
+ /** 是否显示;双向绑定写 `_open={x}` */
7
+ _open?: boolean;
8
+ /**
9
+ * 点遮罩关闭
10
+ * @default true
11
+ */
12
+ closeOnClick?: boolean;
13
+ /**
14
+ * 打开时锁住页面滚动
15
+ * @default true
16
+ */
17
+ lockScroll?: boolean;
18
+ /**
19
+ * 渲染到宿主的浮层根;弹出层自己已经 Teleport 时传 false
20
+ * @default true
21
+ */
22
+ teleport?: boolean;
23
+ /** 点了遮罩(关闭之前) */
24
+ onClick?: (event: Event) => void;
25
+ /** 遮罩里居中显示的内容 */
26
+ children?: VNodeChild;
27
+ }
28
+ /** Overlay 的样式:root */
29
+ export declare const overlayStyles: Readonly<{
30
+ root: css.CompiledStyles;
31
+ }>;
32
+ /** 在打开期间锁住页面滚动 */
33
+ export declare function useLockScroll(locked: () => boolean): void;
34
+ /** 遮罩(div,渲染到浮层根) */
35
+ export declare const Overlay: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<OverlayProps>;
@@ -0,0 +1,85 @@
1
+ import { useConfig } from "../config/context.js";
2
+ import { dataAttrs, mergeAttrs } from "../utils/props.js";
3
+ import { useHost } from "../utils/host.js";
4
+ import { usePresence } from "../utils/presence.js";
5
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
6
+ import { _component, bindable, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
7
+ import { Teleport, createVNode, isVNode, onBeforeUnmount, watch } from "vue";
8
+ //#region src/overlay/Overlay.tsx
9
+ /** 未声明的属性落到遮罩(div)上 */
10
+ function _isSlot(s) {
11
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
12
+ }
13
+ /** Overlay 的样式:root */
14
+ var overlayStyles = css.create({ root: {
15
+ position: "fixed",
16
+ inset: 0,
17
+ zIndex: 2e3,
18
+ display: "flex",
19
+ alignItems: "center",
20
+ justifyContent: "center",
21
+ backgroundColor: "_overlay",
22
+ opacity: {
23
+ default: 0,
24
+ "[data-state=\"open\"]": 1
25
+ },
26
+ transitionProperty: "opacity",
27
+ transitionDuration: "_lg",
28
+ transitionTimingFunction: "_standard"
29
+ } });
30
+ /** 在打开期间锁住页面滚动 */
31
+ function useLockScroll(locked) {
32
+ const host = useHost();
33
+ let release;
34
+ const update = (next) => {
35
+ if (next && !release) release = host.lockScroll();
36
+ else if (!next && release) {
37
+ release();
38
+ release = void 0;
39
+ }
40
+ };
41
+ watch(locked, update, { immediate: true });
42
+ onBeforeUnmount(() => update(false));
43
+ }
44
+ /** 遮罩(div,渲染到浮层根) */
45
+ var Overlay = /*#__PURE__*/ _component((_props, _ctx) => {
46
+ const open = bindable(_props, "_open", () => false, _ctx.emit);
47
+ const closeOnClick = readonlyProp(_props, "closeOnClick", true);
48
+ const lockScroll = readonlyProp(_props, "lockScroll", true);
49
+ const teleport = readonlyProp(_props, "teleport", true);
50
+ const onClick = readonlyProp(_props, "onClick");
51
+ const children = childrenProp(_props);
52
+ const rest = restProps(_props, _ctx, false);
53
+ const host = useHost();
54
+ const config = useConfig();
55
+ const presence = usePresence(() => open.value);
56
+ useLockScroll(() => open.value && lockScroll.value);
57
+ return () => {
58
+ if (!presence.mounted) return null;
59
+ const mask = createVNode("div", mergeAttrs({ sx: [config.rootSx, overlayStyles.root] }, rest, {
60
+ onClick: (event) => {
61
+ onClick.value?.(event);
62
+ if (closeOnClick.value && !event.defaultPrevented) open.value = false;
63
+ },
64
+ ...dataAttrs({
65
+ "data-state": presence.visible ? "open" : "closed",
66
+ "data-scroll-lock": true
67
+ })
68
+ }), [children.value]);
69
+ return teleport.value ? createVNode(Teleport, { "to": host.overlayRoot() }, _isSlot(mask) ? mask : { default: () => [mask] }) : mask;
70
+ };
71
+ }, {
72
+ name: "Overlay",
73
+ props: [
74
+ "_open",
75
+ "onUpdate:_open",
76
+ "closeOnClick",
77
+ "lockScroll",
78
+ "teleport",
79
+ "onClick"
80
+ ]
81
+ });
82
+ //#endregion
83
+ export { Overlay, overlayStyles, useLockScroll };
84
+
85
+ //# sourceMappingURL=Overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Overlay.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/overlay/Overlay.tsx"],"sourcesContent":["/**\n * 遮罩:盖住整个页面的半透明层,弹出层、对话框在它上面。打开时锁住页面滚动,点了默认关闭。\n *\n * <Overlay _open={show} />\n * <Overlay _open={loading} closeOnClick={false}><Loading … /></Overlay>\n *\n * 渲染到宿主的浮层根(H5 是 body,小程序是页面根节点下的浮层节点),进出场是淡入淡出。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Teleport, onBeforeUnmount, watch, type VNodeChild } from 'vue';\nimport { useConfig } from '../config/context';\nimport { useHost } from '../utils/host';\nimport { usePresence } from '../utils/presence';\nimport { dataAttrs, mergeAttrs, type PartProps } from '../utils/props';\n\n/** 未声明的属性落到遮罩(div)上 */\nexport interface OverlayProps extends PartProps<'div'> {\n /** 是否显示;双向绑定写 `_open={x}` */\n _open?: boolean;\n /**\n * 点遮罩关闭\n * @default true\n */\n closeOnClick?: boolean;\n /**\n * 打开时锁住页面滚动\n * @default true\n */\n lockScroll?: boolean;\n /**\n * 渲染到宿主的浮层根;弹出层自己已经 Teleport 时传 false\n * @default true\n */\n teleport?: boolean;\n /** 点了遮罩(关闭之前) */\n onClick?: (event: Event) => void;\n /** 遮罩里居中显示的内容 */\n children?: VNodeChild;\n}\n\n/** Overlay 的样式:root */\nexport const overlayStyles = css.create({\n root: {\n position: 'fixed',\n inset: 0,\n zIndex: 2000,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: '_overlay',\n opacity: { default: 0, '[data-state=\"open\"]': 1 },\n transitionProperty: 'opacity',\n transitionDuration: '_lg',\n transitionTimingFunction: '_standard',\n },\n});\n\n/** 在打开期间锁住页面滚动 */\nexport function useLockScroll(locked: () => boolean) {\n const host = useHost();\n let release: (() => void) | undefined;\n const update = (next: boolean) => {\n if (next && !release) release = host.lockScroll();\n else if (!next && release) {\n release();\n release = undefined;\n }\n };\n watch(locked, update, { immediate: true });\n onBeforeUnmount(() => update(false));\n}\n\n/** 遮罩(div,渲染到浮层根) */\nexport const Overlay = _component(\n ({\n _open: open = _bindable(false),\n closeOnClick = true,\n lockScroll = true,\n teleport = true,\n onClick,\n children,\n ...rest\n }: OverlayProps) => {\n const host = useHost();\n const config = useConfig();\n const presence = usePresence(() => open);\n useLockScroll(() => open && lockScroll);\n return () => {\n if (!presence.mounted) return null;\n const mask = (\n <div\n {...mergeAttrs<'div'>({ sx: [config.rootSx, overlayStyles.root] }, rest, {\n onClick: (event: Event) => {\n onClick?.(event);\n if (closeOnClick && !event.defaultPrevented) open = false;\n },\n ...dataAttrs({\n 'data-state': presence.visible ? 'open' : 'closed',\n // 小程序里遮罩 catch 掉 touchmove,挡住下面页面的滚动\n 'data-scroll-lock': true,\n }),\n })}\n >\n {children}\n </div>\n );\n return teleport ? <Teleport to={host.overlayRoot() as never}>{mask}</Teleport> : mask;\n };\n },\n);\n"],"mappings":";;;;;;;;;AAgBA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AA0BA,IAAa,gBAAgB,IAAI,OAAO,EACtC,MAAM;CACJ,UAAU;CACV,OAAO;CACP,QAAQ;CACR,SAAS;CACT,YAAY;CACZ,gBAAgB;CAChB,iBAAiB;CACjB,SAAS;EAAE,SAAS;EAAG,yBAAuB;CAAE;CAChD,oBAAoB;CACpB,oBAAoB;CACpB,0BAA0B;AAC5B,EACF,CAAC;;AAGD,SAAgB,cAAc,QAAuB;CACnD,MAAM,OAAO,QAAQ;CACrB,IAAI;CACJ,MAAM,UAAU,SAAkB;EAChC,IAAI,QAAQ,CAAC,SAAS,UAAU,KAAK,WAAW;OAC3C,IAAI,CAAC,QAAQ,SAAS;GACzB,QAAQ;GACR,UAAU,KAAA;EACZ;CACF;CACA,MAAM,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC;CACzC,sBAAsB,OAAO,KAAK,CAAC;AACrC;;AAGA,IAAa,UAAU,0BACrB,QAAA,SAQoB;CAAA,MAAA,OAAAC,SAAA,QAAA,eAPM,OAAK,KAAA,IAAA;CAAA,MAAA,eAAAC,aAAA,QAAA,gBACd,IAAI;CAAA,MAAA,aAAAA,aAAA,QAAA,cACN,IAAI;CAAA,MAAA,WAAAA,aAAA,QAAA,YACN,IAAI;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAGZ,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAS,UAAU;CACzB,MAAM,WAAW,kBAAY,KAAA,KAAU;CACvC,oBAAoB,KAAA,SAAA,WAAA,KAAkB;CACtC,aAAa;EACX,IAAI,CAAC,SAAS,SAAS,OAAO;EAC9B,MAAM,OAAIC,YAAA,OAEF,WAAkB,EAAE,IAAI,CAAC,OAAO,QAAQ,cAAc,IAAI,EAAE,GAAG,MAAM;GACvE,UAAU,UAAiB;IACzB,QAAA,QAAU,KAAK;IACf,IAAI,aAAA,SAAgB,CAAC,MAAM,kBAAkB,KAAA,QAAO;GACtD;GACA,GAAG,UAAU;IACX,cAAc,SAAS,UAAU,SAAS;IAE1C,oBAAoB;GACtB,CAAC;EACH,CAAC,GAAC,CAAA,SAAA,KAAA,CAAA;EAKN,OAAO,SAAA,QAAAA,YAAA,UAAA,EAAA,MAAyB,KAAK,YAAY,EAAC,GAAA,QAAY,IAAI,IAAJ,OAAI,EAAA,eAAA,CAAJ,IAAI,EAAA,CAAA,IAAe;CACnF;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -0,0 +1,76 @@
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
+ import { type OverlayProps } from './Overlay';
5
+ /** 弹出的位置 */
6
+ export interface PopupPositions {
7
+ /** 屏幕中间,缩放淡入 */
8
+ center: unknown;
9
+ /** 从底部滑入 */
10
+ bottom: unknown;
11
+ /** 从顶部滑入 */
12
+ top: unknown;
13
+ /** 从起始边(左)滑入,占满高度 */
14
+ left: unknown;
15
+ /** 从结束边(右)滑入,占满高度 */
16
+ right: unknown;
17
+ }
18
+ /** 关闭的原因 */
19
+ export type PopupCloseReason = 'overlay' | 'close';
20
+ /** 角色与模态由组件管理 */
21
+ export type PopupManaged = 'role' | 'aria-modal';
22
+ /** 未声明的属性落到面板(div)上 */
23
+ export interface PopupProps extends PartProps<'div', PopupManaged> {
24
+ /** 是否打开;双向绑定写 `_open={x}` */
25
+ _open?: boolean;
26
+ /**
27
+ * 位置
28
+ * @default 'center'
29
+ */
30
+ position?: keyof PopupPositions;
31
+ /** 圆角(底部弹出时只有上面两个角) */
32
+ round?: boolean;
33
+ /** 右上角显示关闭按钮 */
34
+ closeable?: boolean;
35
+ /**
36
+ * 显示遮罩
37
+ * @default true
38
+ */
39
+ overlay?: boolean;
40
+ /**
41
+ * 点遮罩关闭
42
+ * @default true
43
+ */
44
+ closeOnOverlay?: boolean;
45
+ /**
46
+ * 底部弹出时留出安全区(全面屏底部的横条)
47
+ * @default true
48
+ */
49
+ safeArea?: boolean;
50
+ /** 打开或关闭;关闭时带原因(点遮罩、点关闭按钮) */
51
+ onOpenChange?: (open: boolean, details: {
52
+ reason: PopupCloseReason;
53
+ }) => void;
54
+ /** 面板的内容 */
55
+ children?: VNodeChild;
56
+ /** 遮罩的部件属性 */
57
+ propsOverlay?: Partial<OverlayProps>;
58
+ /** 关闭按钮的部件属性 */
59
+ propsClose?: PartProps<'button'>;
60
+ }
61
+ /** Popup 的样式:panel、各位置、round、safeArea、close */
62
+ export declare const popupStyles: Readonly<{
63
+ bottom: css.CompiledStyles;
64
+ center: css.CompiledStyles;
65
+ close: css.CompiledStyles;
66
+ left: css.CompiledStyles;
67
+ panel: css.CompiledStyles;
68
+ right: css.CompiledStyles;
69
+ roundBottom: css.CompiledStyles;
70
+ roundCenter: css.CompiledStyles;
71
+ roundTop: css.CompiledStyles;
72
+ safeArea: css.CompiledStyles;
73
+ top: css.CompiledStyles;
74
+ }>;
75
+ /** 弹出层(遮罩 + 面板 div[role=dialog],渲染到浮层根) */
76
+ export declare const Popup: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<PopupProps>;
@@ -0,0 +1,191 @@
1
+ import { t } from "../theme/tokens.js";
2
+ import { useConfig } from "../config/context.js";
3
+ import { dataAttrs, mergeAttrs, mergePartProps } from "../utils/props.js";
4
+ import { Icon } from "../base/Icon.js";
5
+ import { useHost } from "../utils/host.js";
6
+ import { usePresence } from "../utils/presence.js";
7
+ import { Overlay } from "./Overlay.js";
8
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
9
+ import { _component, bindable, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
+ import { Teleport, createVNode } from "vue";
11
+ import { X } from "@lucide/icons";
12
+ //#region src/overlay/Popup.tsx
13
+ /**
14
+ * 弹出层:从底部(或顶部、两侧)滑入,或在中间弹出的面板,下面有遮罩。动作面板、选择器、对话框都建在它上面。
15
+ *
16
+ * <Popup _open={show} position="bottom" round>…</Popup>
17
+ * <Popup _open={show} closeable onOpenChange={(open, { reason }) => …}>…</Popup>
18
+ *
19
+ * 点遮罩、点右上角的关闭按钮会关闭(onOpenChange 带原因);底部弹出时留出安全区。
20
+ */
21
+ /** 弹出的位置 */
22
+ /** 关闭的原因 */
23
+ /** 角色与模态由组件管理 */
24
+ /** 未声明的属性落到面板(div)上 */
25
+ /** Popup 的样式:panel、各位置、round、safeArea、close */
26
+ var popupStyles = css.create({
27
+ panel: {
28
+ boxSizing: "border-box",
29
+ position: "fixed",
30
+ zIndex: 2e3,
31
+ maxHeight: "100%",
32
+ overflowY: "auto",
33
+ backgroundColor: "_surface",
34
+ color: "_text",
35
+ transitionProperty: "transform, opacity",
36
+ transitionDuration: "_lg",
37
+ transitionTimingFunction: {
38
+ default: "_exit",
39
+ "[data-state=\"open\"]": "_enter"
40
+ }
41
+ },
42
+ center: {
43
+ insetBlockStart: "50%",
44
+ insetInlineStart: "50%",
45
+ width: "max-content",
46
+ maxWidth: `calc(100% - ${t.space.xxl})`,
47
+ transform: {
48
+ default: "translate(-50%, -50%) scale(0.9)",
49
+ "[data-state=\"open\"]": "translate(-50%, -50%) scale(1)"
50
+ },
51
+ opacity: {
52
+ default: 0,
53
+ "[data-state=\"open\"]": 1
54
+ }
55
+ },
56
+ bottom: {
57
+ insetInline: 0,
58
+ insetBlockEnd: 0,
59
+ maxHeight: "80%",
60
+ transform: {
61
+ default: "translateY(100%)",
62
+ "[data-state=\"open\"]": "none"
63
+ }
64
+ },
65
+ top: {
66
+ insetInline: 0,
67
+ insetBlockStart: 0,
68
+ maxHeight: "80%",
69
+ transform: {
70
+ default: "translateY(-100%)",
71
+ "[data-state=\"open\"]": "none"
72
+ }
73
+ },
74
+ left: {
75
+ insetBlock: 0,
76
+ insetInlineStart: 0,
77
+ width: "80%",
78
+ transform: {
79
+ default: "translateX(-100%)",
80
+ "[data-state=\"open\"]": "none"
81
+ }
82
+ },
83
+ right: {
84
+ insetBlock: 0,
85
+ insetInlineEnd: 0,
86
+ width: "80%",
87
+ transform: {
88
+ default: "translateX(100%)",
89
+ "[data-state=\"open\"]": "none"
90
+ }
91
+ },
92
+ roundCenter: { borderRadius: "_xl" },
93
+ roundBottom: {
94
+ borderStartStartRadius: "_xl",
95
+ borderStartEndRadius: "_xl"
96
+ },
97
+ roundTop: {
98
+ borderEndStartRadius: "_xl",
99
+ borderEndEndRadius: "_xl"
100
+ },
101
+ safeArea: { paddingBlockEnd: "env(safe-area-inset-bottom)" },
102
+ close: {
103
+ position: "absolute",
104
+ insetBlockStart: "_md",
105
+ insetInlineEnd: "_md",
106
+ zIndex: 1,
107
+ display: "inline-flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ width: "2em",
111
+ height: "2em",
112
+ padding: 0,
113
+ borderWidth: 0,
114
+ borderRadius: "_full",
115
+ backgroundColor: {
116
+ default: "transparent",
117
+ ":active": "_fill"
118
+ },
119
+ color: "_textMuted",
120
+ fontSize: "_xl",
121
+ cursor: "pointer"
122
+ }
123
+ });
124
+ /** 弹出层(遮罩 + 面板 div[role=dialog],渲染到浮层根) */
125
+ var Popup = /*#__PURE__*/ _component((_props, _ctx) => {
126
+ const open = bindable(_props, "_open", () => false, _ctx.emit);
127
+ const position = readonlyProp(_props, "position", "center");
128
+ const round = readonlyProp(_props, "round", false);
129
+ const closeable = readonlyProp(_props, "closeable", false);
130
+ const overlay = readonlyProp(_props, "overlay", true);
131
+ const closeOnOverlay = readonlyProp(_props, "closeOnOverlay", true);
132
+ const safeArea = readonlyProp(_props, "safeArea", true);
133
+ const onOpenChange = readonlyProp(_props, "onOpenChange");
134
+ const children = childrenProp(_props);
135
+ const propsOverlay = readonlyProp(_props, "propsOverlay");
136
+ const propsClose = readonlyProp(_props, "propsClose");
137
+ const rest = restProps(_props, _ctx, false);
138
+ const host = useHost();
139
+ const config = useConfig();
140
+ const presence = usePresence(() => open.value);
141
+ const close = (reason) => {
142
+ open.value = false;
143
+ onOpenChange.value?.(false, { reason });
144
+ };
145
+ return () => {
146
+ if (!presence.mounted) return null;
147
+ const rounded = round.value && (position.value === "center" ? popupStyles.roundCenter : position.value === "bottom" ? popupStyles.roundBottom : position.value === "top" && popupStyles.roundTop);
148
+ return createVNode(Teleport, { "to": host.overlayRoot() }, { default: () => [overlay.value && createVNode(Overlay, mergePartProps({
149
+ _open: open.value,
150
+ teleport: false,
151
+ closeOnClick: false,
152
+ onClick: () => closeOnOverlay.value && close("overlay")
153
+ }, propsOverlay.value), null), createVNode("div", mergeAttrs({ sx: [
154
+ config.rootSx,
155
+ popupStyles.panel,
156
+ popupStyles[position.value],
157
+ rounded,
158
+ safeArea.value && position.value === "bottom" && popupStyles.safeArea
159
+ ] }, rest, {
160
+ role: "dialog",
161
+ "aria-modal": overlay.value ? "true" : void 0,
162
+ ...dataAttrs({
163
+ "data-state": presence.visible ? "open" : "closed",
164
+ "data-position": position.value
165
+ })
166
+ }), [closeable.value && createVNode("button", mergeAttrs({ sx: popupStyles.close }, propsClose.value, {
167
+ type: "button",
168
+ "aria-label": config.lang.close,
169
+ onClick: () => close("close")
170
+ }), [createVNode(Icon, mergePartProps({ icon: X }, void 0), null)]), children.value])] });
171
+ };
172
+ }, {
173
+ name: "Popup",
174
+ props: [
175
+ "_open",
176
+ "onUpdate:_open",
177
+ "position",
178
+ "round",
179
+ "closeable",
180
+ "overlay",
181
+ "closeOnOverlay",
182
+ "safeArea",
183
+ "onOpenChange",
184
+ "propsOverlay",
185
+ "propsClose"
186
+ ]
187
+ });
188
+ //#endregion
189
+ export { Popup, popupStyles };
190
+
191
+ //# sourceMappingURL=Popup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popup.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/overlay/Popup.tsx"],"sourcesContent":["/**\n * 弹出层:从底部(或顶部、两侧)滑入,或在中间弹出的面板,下面有遮罩。动作面板、选择器、对话框都建在它上面。\n *\n * <Popup _open={show} position=\"bottom\" round>…</Popup>\n * <Popup _open={show} closeable onOpenChange={(open, { reason }) => …}>…</Popup>\n *\n * 点遮罩、点右上角的关闭按钮会关闭(onOpenChange 带原因);底部弹出时留出安全区。\n */\nimport { X } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Teleport, type VNodeChild } from 'vue';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { useConfig } from '../config/context';\nimport { t } from '../theme/tokens';\nimport { useHost } from '../utils/host';\nimport { usePresence } from '../utils/presence';\nimport { dataAttrs, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { Overlay, type OverlayProps } from './Overlay';\n\n/** 弹出的位置 */\nexport interface PopupPositions {\n /** 屏幕中间,缩放淡入 */\n center: unknown;\n /** 从底部滑入 */\n bottom: unknown;\n /** 从顶部滑入 */\n top: unknown;\n /** 从起始边(左)滑入,占满高度 */\n left: unknown;\n /** 从结束边(右)滑入,占满高度 */\n right: unknown;\n}\n\n/** 关闭的原因 */\nexport type PopupCloseReason = 'overlay' | 'close';\n\n/** 角色与模态由组件管理 */\nexport type PopupManaged = 'role' | 'aria-modal';\n\n/** 未声明的属性落到面板(div)上 */\nexport interface PopupProps extends PartProps<'div', PopupManaged> {\n /** 是否打开;双向绑定写 `_open={x}` */\n _open?: boolean;\n /**\n * 位置\n * @default 'center'\n */\n position?: keyof PopupPositions;\n /** 圆角(底部弹出时只有上面两个角) */\n round?: boolean;\n /** 右上角显示关闭按钮 */\n closeable?: boolean;\n /**\n * 显示遮罩\n * @default true\n */\n overlay?: boolean;\n /**\n * 点遮罩关闭\n * @default true\n */\n closeOnOverlay?: boolean;\n /**\n * 底部弹出时留出安全区(全面屏底部的横条)\n * @default true\n */\n safeArea?: boolean;\n /** 打开或关闭;关闭时带原因(点遮罩、点关闭按钮) */\n onOpenChange?: (open: boolean, details: { reason: PopupCloseReason }) => void;\n /** 面板的内容 */\n children?: VNodeChild;\n /** 遮罩的部件属性 */\n propsOverlay?: Partial<OverlayProps>;\n /** 关闭按钮的部件属性 */\n propsClose?: PartProps<'button'>;\n}\n\n/** Popup 的样式:panel、各位置、round、safeArea、close */\nexport const popupStyles = css.create({\n panel: {\n boxSizing: 'border-box',\n position: 'fixed',\n zIndex: 2000,\n maxHeight: '100%',\n overflowY: 'auto',\n backgroundColor: '_surface',\n color: '_text',\n transitionProperty: 'transform, opacity',\n transitionDuration: '_lg',\n transitionTimingFunction: { default: '_exit', '[data-state=\"open\"]': '_enter' },\n },\n center: {\n insetBlockStart: '50%',\n insetInlineStart: '50%',\n width: 'max-content',\n maxWidth: `calc(100% - ${t.space.xxl})`,\n transform: {\n default: 'translate(-50%, -50%) scale(0.9)',\n '[data-state=\"open\"]': 'translate(-50%, -50%) scale(1)',\n },\n opacity: { default: 0, '[data-state=\"open\"]': 1 },\n },\n bottom: {\n insetInline: 0,\n insetBlockEnd: 0,\n maxHeight: '80%',\n transform: { default: 'translateY(100%)', '[data-state=\"open\"]': 'none' },\n },\n top: {\n insetInline: 0,\n insetBlockStart: 0,\n maxHeight: '80%',\n transform: { default: 'translateY(-100%)', '[data-state=\"open\"]': 'none' },\n },\n left: {\n insetBlock: 0,\n insetInlineStart: 0,\n width: '80%',\n transform: { default: 'translateX(-100%)', '[data-state=\"open\"]': 'none' },\n },\n right: {\n insetBlock: 0,\n insetInlineEnd: 0,\n width: '80%',\n transform: { default: 'translateX(100%)', '[data-state=\"open\"]': 'none' },\n },\n roundCenter: { borderRadius: '_xl' },\n roundBottom: { borderStartStartRadius: '_xl', borderStartEndRadius: '_xl' },\n roundTop: { borderEndStartRadius: '_xl', borderEndEndRadius: '_xl' },\n safeArea: { paddingBlockEnd: 'env(safe-area-inset-bottom)' },\n close: {\n position: 'absolute',\n insetBlockStart: '_md',\n insetInlineEnd: '_md',\n zIndex: 1,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2em',\n height: '2em',\n padding: 0,\n borderWidth: 0,\n borderRadius: '_full',\n backgroundColor: { default: 'transparent', ':active': '_fill' },\n color: '_textMuted',\n fontSize: '_xl',\n cursor: 'pointer',\n },\n});\n\n/** 弹出层(遮罩 + 面板 div[role=dialog],渲染到浮层根) */\nexport const Popup = _component(\n ({\n _open: open = _bindable(false),\n position = 'center',\n round = false,\n closeable = false,\n overlay = true,\n closeOnOverlay = true,\n safeArea = true,\n onOpenChange,\n children,\n propsOverlay,\n propsClose,\n ...rest\n }: PopupProps) => {\n const host = useHost();\n const config = useConfig();\n const presence = usePresence(() => open);\n const close = (reason: PopupCloseReason) => {\n open = false;\n onOpenChange?.(false, { reason });\n };\n return () => {\n if (!presence.mounted) return null;\n const rounded =\n round &&\n (position === 'center'\n ? popupStyles.roundCenter\n : position === 'bottom'\n ? popupStyles.roundBottom\n : position === 'top' && popupStyles.roundTop);\n return (\n <Teleport to={host.overlayRoot() as never}>\n {overlay && (\n <Overlay\n {...mergePartProps<OverlayProps>(\n {\n _open: open,\n teleport: false,\n closeOnClick: false,\n onClick: () => closeOnOverlay && close('overlay'),\n },\n propsOverlay,\n )}\n />\n )}\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n config.rootSx,\n popupStyles.panel,\n popupStyles[position],\n rounded,\n safeArea && position === 'bottom' && popupStyles.safeArea,\n ],\n },\n rest,\n {\n role: 'dialog',\n 'aria-modal': overlay ? 'true' : undefined,\n ...dataAttrs({\n 'data-state': presence.visible ? 'open' : 'closed',\n 'data-position': position,\n }),\n },\n )}\n >\n {closeable && (\n <button\n {...mergeAttrs<'button'>({ sx: popupStyles.close }, propsClose, {\n type: 'button',\n 'aria-label': config.lang.close,\n onClick: () => close('close'),\n })}\n >\n <Icon {...mergePartProps<IconProps>({ icon: X }, undefined)} />\n </button>\n )}\n {children}\n </div>\n </Teleport>\n );\n };\n },\n);\n"],"mappings":"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"}