@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,143 @@
1
+ import { webPermissions } from "../capability/web.js";
2
+ import { webHost } from "../utils/host.js";
3
+ import { App } from "@capacitor/app";
4
+ import { Capacitor, SystemBars, SystemBarsStyle } from "@capacitor/core";
5
+ import { Camera } from "@capacitor/camera";
6
+ import { Clipboard } from "@capacitor/clipboard";
7
+ import { Geolocation } from "@capacitor/geolocation";
8
+ import { Haptics, ImpactStyle } from "@capacitor/haptics";
9
+ import { Keyboard, KeyboardStyle } from "@capacitor/keyboard";
10
+ import { Preferences } from "@capacitor/preferences";
11
+ //#region src/capacitor/index.ts
12
+ /**
13
+ * 原生应用(Capacitor 的 iOS / Android 外壳)里的宿主能力:页面跑在系统 WebView 里,DOM、测量、滚动照常用浏览器的,
14
+ * 设备权限、存储、震动、剪贴板、选图换成官方插件(原生的授权弹窗、不会被系统清掉的存储)。
15
+ * 子路径 @zerodep-dev/vue-tsx-pro-mobile/capacitor,插件是可选的 peer 依赖,做原生应用时才装。
16
+ *
17
+ * // main.ts:在原生外壳里才加载(H5 的包里不带插件)
18
+ * if (window.Capacitor?.isNativePlatform()) {
19
+ * const { createCapacitorHost } = await import('@zerodep-dev/vue-tsx-pro-mobile/capacitor');
20
+ * app.provide(HOST_KEY, await createCapacitorHost());
21
+ * }
22
+ *
23
+ * 插件接口按 Capacitor 8 的官方文档(2026-10):Geolocation、Camera 的 checkPermissions / requestPermissions 返回
24
+ * granted、denied、prompt、prompt-with-rationale(相机的还有 limited);Preferences 是异步的键值存储,启动时整个读进内存,之后同步读、写穿透。
25
+ */
26
+ var stateOf = (state) => state === "granted" || state === "limited" ? "granted" : state === "denied" ? "denied" : "prompt";
27
+ /** 页面主题 → 状态栏的样式:Dark 是深色底上的浅色文字,Default 跟着系统的深浅色 */
28
+ var BAR_STYLES = {
29
+ light: SystemBarsStyle.Light,
30
+ dark: SystemBarsStyle.Dark,
31
+ system: SystemBarsStyle.Default
32
+ };
33
+ /** 页面主题 → iOS 键盘的深浅色(安卓的键盘由输入法决定,插件不支持) */
34
+ var KEYBOARD_STYLES = {
35
+ light: KeyboardStyle.Light,
36
+ dark: KeyboardStyle.Dark,
37
+ system: KeyboardStyle.Default
38
+ };
39
+ /** 设备权限 → 插件与它的权限名;麦克风没有官方插件,走 WebView 的 getUserMedia(外壳会转成系统授权) */
40
+ async function status(name) {
41
+ switch (name) {
42
+ case "location": return stateOf((await Geolocation.checkPermissions()).location);
43
+ case "fuzzyLocation": return stateOf((await Geolocation.checkPermissions()).coarseLocation);
44
+ case "camera": return stateOf((await Camera.checkPermissions()).camera);
45
+ case "album": return stateOf((await Camera.checkPermissions()).photos);
46
+ case "microphone": return webPermissions.status(name);
47
+ case "bluetooth": return "unsupported";
48
+ }
49
+ }
50
+ async function request(name) {
51
+ switch (name) {
52
+ case "location": return stateOf((await Geolocation.requestPermissions({ permissions: ["location"] })).location);
53
+ case "fuzzyLocation": return stateOf((await Geolocation.requestPermissions({ permissions: ["coarseLocation"] })).coarseLocation);
54
+ case "camera": return stateOf((await Camera.requestPermissions({ permissions: ["camera"] })).camera);
55
+ case "album": return stateOf((await Camera.requestPermissions({ permissions: ["photos"] })).photos);
56
+ case "microphone": return webPermissions.request(name);
57
+ case "bluetooth": return "unsupported";
58
+ }
59
+ }
60
+ /** Preferences 整个读进内存:组件按同步接口读;写的时候同时写回原生存储 */
61
+ async function preferencesStorage() {
62
+ const { keys } = await Preferences.keys();
63
+ const values = /* @__PURE__ */ new Map();
64
+ await Promise.all(keys.map(async (key) => {
65
+ const { value } = await Preferences.get({ key });
66
+ if (value !== null) values.set(key, value);
67
+ }));
68
+ return {
69
+ get(key) {
70
+ const text = values.get(key);
71
+ if (text === void 0) return void 0;
72
+ try {
73
+ return JSON.parse(text);
74
+ } catch {
75
+ return;
76
+ }
77
+ },
78
+ set(key, value) {
79
+ const text = JSON.stringify(value);
80
+ values.set(key, text);
81
+ Preferences.set({
82
+ key,
83
+ value: text
84
+ });
85
+ },
86
+ remove(key) {
87
+ values.delete(key);
88
+ Preferences.remove({ key });
89
+ },
90
+ keys: () => [...values.keys()]
91
+ };
92
+ }
93
+ var backButtonHooked = false;
94
+ /**
95
+ * 原生应用的宿主能力:在浏览器的实现上换掉设备权限、存储、震动、剪贴板、选图;
96
+ * 顺带接上安卓的返回键(页面能后退就后退,到头了退出应用),状态栏的文字颜色、iOS 键盘的深浅色跟着页面主题。只在原生外壳里调用。
97
+ *
98
+ * 键盘弹起时的布局由外壳负责:安卓上 Capacitor 8 的 SystemBars 把键盘高度垫在 WebView 下面,
99
+ * iOS 上 Keyboard 插件的 resize: native 把 WebView 缩到键盘上面——两端页面都变矮,底部固定的元素与正在输入的框露在键盘上方
100
+ */
101
+ async function createCapacitorHost() {
102
+ if (!backButtonHooked) {
103
+ backButtonHooked = true;
104
+ App.addListener("backButton", ({ canGoBack }) => canGoBack ? history.back() : void App.exitApp());
105
+ }
106
+ return {
107
+ ...webHost,
108
+ platform: "app",
109
+ permissions: {
110
+ status,
111
+ async request(name) {
112
+ const current = await status(name);
113
+ return current === "prompt" ? request(name) : current;
114
+ },
115
+ openSettings: status
116
+ },
117
+ storage: await preferencesStorage(),
118
+ vibrate() {
119
+ Haptics.impact({ style: ImpactStyle.Light });
120
+ },
121
+ themeChanged(theme) {
122
+ SystemBars.setStyle({ style: BAR_STYLES[theme] });
123
+ if (Capacitor.getPlatform() === "ios") Keyboard.setStyle({ style: KEYBOARD_STYLES[theme] });
124
+ },
125
+ copy: (text) => Clipboard.write({ string: text }),
126
+ async chooseImages({ count }) {
127
+ const { photos } = await Camera.pickImages({ limit: count });
128
+ return Promise.all(photos.map(async (photo, index) => {
129
+ const blob = await fetch(photo.webPath).then((response) => response.blob());
130
+ const file = new File([blob], `photo-${index}.${photo.format}`, { type: blob.type });
131
+ return {
132
+ url: photo.webPath,
133
+ size: blob.size,
134
+ file
135
+ };
136
+ }));
137
+ }
138
+ };
139
+ }
140
+ //#endregion
141
+ export { createCapacitorHost };
142
+
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/capacitor/index.ts"],"sourcesContent":["/**\n * 原生应用(Capacitor 的 iOS / Android 外壳)里的宿主能力:页面跑在系统 WebView 里,DOM、测量、滚动照常用浏览器的,\n * 设备权限、存储、震动、剪贴板、选图换成官方插件(原生的授权弹窗、不会被系统清掉的存储)。\n * 子路径 @zerodep-dev/vue-tsx-pro-mobile/capacitor,插件是可选的 peer 依赖,做原生应用时才装。\n *\n * // main.ts:在原生外壳里才加载(H5 的包里不带插件)\n * if (window.Capacitor?.isNativePlatform()) {\n * const { createCapacitorHost } = await import('@zerodep-dev/vue-tsx-pro-mobile/capacitor');\n * app.provide(HOST_KEY, await createCapacitorHost());\n * }\n *\n * 插件接口按 Capacitor 8 的官方文档(2026-10):Geolocation、Camera 的 checkPermissions / requestPermissions 返回\n * granted、denied、prompt、prompt-with-rationale(相机的还有 limited);Preferences 是异步的键值存储,启动时整个读进内存,之后同步读、写穿透。\n */\nimport { App } from '@capacitor/app';\nimport { Capacitor, SystemBars, SystemBarsStyle } from '@capacitor/core';\nimport { Camera } from '@capacitor/camera';\nimport { Clipboard } from '@capacitor/clipboard';\nimport { Geolocation } from '@capacitor/geolocation';\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\nimport { Keyboard, KeyboardStyle } from '@capacitor/keyboard';\nimport { Preferences } from '@capacitor/preferences';\nimport type { DevicePermission, DevicePermissionState, HostStorage } from '../capability/types';\nimport { webPermissions } from '../capability/web';\nimport { webHost, type Host } from '../utils/host';\n\n/**\n * 插件的权限状态;prompt-with-rationale 是安卓上拒绝过一次、还能再问(要先说明用途),\n * limited 是 iOS 只允许访问部分照片(选图照常能用,算同意)\n */\ntype PluginState = 'granted' | 'denied' | 'prompt' | 'prompt-with-rationale' | 'limited';\n\nconst stateOf = (state: PluginState | undefined): DevicePermissionState =>\n state === 'granted' || state === 'limited' ? 'granted' : state === 'denied' ? 'denied' : 'prompt';\n\n/** 页面主题 → 状态栏的样式:Dark 是深色底上的浅色文字,Default 跟着系统的深浅色 */\nconst BAR_STYLES = {\n light: SystemBarsStyle.Light,\n dark: SystemBarsStyle.Dark,\n system: SystemBarsStyle.Default,\n} as const;\n\n/** 页面主题 → iOS 键盘的深浅色(安卓的键盘由输入法决定,插件不支持) */\nconst KEYBOARD_STYLES = {\n light: KeyboardStyle.Light,\n dark: KeyboardStyle.Dark,\n system: KeyboardStyle.Default,\n} as const;\n\n/** 设备权限 → 插件与它的权限名;麦克风没有官方插件,走 WebView 的 getUserMedia(外壳会转成系统授权) */\nasync function status(name: DevicePermission): Promise<DevicePermissionState> {\n switch (name) {\n case 'location':\n return stateOf((await Geolocation.checkPermissions()).location);\n case 'fuzzyLocation':\n return stateOf((await Geolocation.checkPermissions()).coarseLocation);\n case 'camera':\n return stateOf((await Camera.checkPermissions()).camera);\n case 'album':\n return stateOf((await Camera.checkPermissions()).photos);\n case 'microphone':\n return webPermissions.status(name);\n case 'bluetooth':\n // 要社区插件(@capacitor-community/bluetooth-le),默认不带\n return 'unsupported';\n }\n}\n\nasync function request(name: DevicePermission): Promise<DevicePermissionState> {\n switch (name) {\n case 'location':\n return stateOf(\n (await Geolocation.requestPermissions({ permissions: ['location'] })).location,\n );\n case 'fuzzyLocation':\n return stateOf(\n (await Geolocation.requestPermissions({ permissions: ['coarseLocation'] })).coarseLocation,\n );\n case 'camera':\n return stateOf((await Camera.requestPermissions({ permissions: ['camera'] })).camera);\n case 'album':\n return stateOf((await Camera.requestPermissions({ permissions: ['photos'] })).photos);\n case 'microphone':\n return webPermissions.request(name);\n case 'bluetooth':\n return 'unsupported';\n }\n}\n\n/** Preferences 整个读进内存:组件按同步接口读;写的时候同时写回原生存储 */\nasync function preferencesStorage(): Promise<HostStorage> {\n const { keys } = await Preferences.keys();\n const values = new Map<string, string>();\n await Promise.all(\n keys.map(async (key) => {\n const { value } = await Preferences.get({ key });\n if (value !== null) values.set(key, value);\n }),\n );\n return {\n get<T>(key: string) {\n const text = values.get(key);\n if (text === undefined) return undefined;\n try {\n return JSON.parse(text) as T;\n } catch {\n return undefined;\n }\n },\n set(key, value) {\n const text = JSON.stringify(value);\n values.set(key, text);\n void Preferences.set({ key, value: text });\n },\n remove(key) {\n values.delete(key);\n void Preferences.remove({ key });\n },\n keys: () => [...values.keys()],\n };\n}\n\nlet backButtonHooked = false;\n\n/**\n * 原生应用的宿主能力:在浏览器的实现上换掉设备权限、存储、震动、剪贴板、选图;\n * 顺带接上安卓的返回键(页面能后退就后退,到头了退出应用),状态栏的文字颜色、iOS 键盘的深浅色跟着页面主题。只在原生外壳里调用。\n *\n * 键盘弹起时的布局由外壳负责:安卓上 Capacitor 8 的 SystemBars 把键盘高度垫在 WebView 下面,\n * iOS 上 Keyboard 插件的 resize: native 把 WebView 缩到键盘上面——两端页面都变矮,底部固定的元素与正在输入的框露在键盘上方\n */\nexport async function createCapacitorHost(): Promise<Host> {\n if (!backButtonHooked) {\n backButtonHooked = true;\n void App.addListener('backButton', ({ canGoBack }) =>\n canGoBack ? history.back() : void App.exitApp(),\n );\n }\n return {\n ...webHost,\n platform: 'app',\n permissions: {\n status,\n async request(name) {\n const current = await status(name);\n return current === 'prompt' ? request(name) : current;\n },\n // 官方插件没有打开系统设置页的接口:返回当前状态,引导由 usePermission 说明\n openSettings: status,\n },\n storage: await preferencesStorage(),\n vibrate() {\n void Haptics.impact({ style: ImpactStyle.Light });\n },\n themeChanged(theme) {\n void SystemBars.setStyle({ style: BAR_STYLES[theme] });\n if (Capacitor.getPlatform() === 'ios')\n void Keyboard.setStyle({ style: KEYBOARD_STYLES[theme] });\n },\n copy: (text) => Clipboard.write({ string: text }),\n async chooseImages({ count }) {\n const { photos } = await Camera.pickImages({ limit: count });\n // webPath 能直接作为 img 的地址;上传要 File,从它取回内容\n return Promise.all(\n photos.map(async (photo, index) => {\n const blob = await fetch(photo.webPath).then((response) => response.blob());\n const file = new File([blob], `photo-${index}.${photo.format}`, { type: blob.type });\n return { url: photo.webPath, size: blob.size, file };\n }),\n );\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import { type VNodeChild } from 'vue';
3
+ import { type Host } from '../utils/host';
4
+ import { type PartProps } from '../utils/props';
5
+ import { type MobileLang } from './lang';
6
+ /** 主题 */
7
+ export interface MobileThemes {
8
+ /** 亮色 */
9
+ light: unknown;
10
+ /** 暗色 */
11
+ dark: unknown;
12
+ /** 跟随系统的暗色偏好 */
13
+ system: unknown;
14
+ }
15
+ /** 未声明的属性落到根元素(div)上;lang 是语言包,不是元素的 lang 属性 */
16
+ export interface ConfigProviderProps extends PartProps<'div', 'lang'> {
17
+ /**
18
+ * 主题
19
+ * @default 'light'
20
+ */
21
+ theme?: keyof MobileThemes;
22
+ /**
23
+ * 语言包
24
+ * @default zhCN
25
+ */
26
+ lang?: MobileLang;
27
+ /** 补上或换掉的宿主能力(只在创建时读):H5 给出 login 这类应用自己的实现,测试里换成假的 */
28
+ host?: Partial<Host>;
29
+ /** 内容 */
30
+ children?: VNodeChild;
31
+ }
32
+ /** ConfigProvider 的样式:root */
33
+ export declare const configProviderStyles: Readonly<{
34
+ root: css.CompiledStyles;
35
+ }>;
36
+ /** 全局配置:主题与语言;根元素是一个 div,后面是命令式反馈的出口 */
37
+ export declare const ConfigProvider: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<ConfigProviderProps>;
@@ -0,0 +1,64 @@
1
+ import { darkTheme, systemTheme } from "../theme/dark.js";
2
+ import { zhCN } from "./lang.js";
3
+ import { ConfigContext } from "./context.js";
4
+ import { dataAttrs, mergeAttrs } from "../utils/props.js";
5
+ import { HOST_KEY, useHost } from "../utils/host.js";
6
+ import { FeedbackOutlet } from "../feedback/FeedbackOutlet.js";
7
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
+ import { _component, childrenProp, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
9
+ import { createVNode, provide, watch } from "vue";
10
+ //#region src/config/ConfigProvider.tsx
11
+ /** 主题 */
12
+ /** 未声明的属性落到根元素(div)上;lang 是语言包,不是元素的 lang 属性 */
13
+ /** ConfigProvider 的样式:root */
14
+ var configProviderStyles = css.create({ root: {
15
+ fontFamily: "_sans",
16
+ fontSize: "_md",
17
+ lineHeight: "_normal",
18
+ color: "_text",
19
+ WebkitTapHighlightColor: "transparent",
20
+ textSizeAdjust: "100%"
21
+ } });
22
+ var THEMES = {
23
+ light: null,
24
+ dark: darkTheme,
25
+ system: systemTheme
26
+ };
27
+ /** 全局配置:主题与语言;根元素是一个 div,后面是命令式反馈的出口 */
28
+ var ConfigProvider = /*#__PURE__*/ _component((_props, _ctx) => {
29
+ const theme = readonlyProp(_props, "theme", "light");
30
+ const lang = readonlyProp(_props, "lang", () => zhCN);
31
+ const host = readonlyProp(_props, "host");
32
+ const children = childrenProp(_props);
33
+ const rest = restProps(_props, _ctx, false);
34
+ const override = untrack(() => host.value);
35
+ if (override) provide(HOST_KEY, {
36
+ ...useHost(),
37
+ ...override
38
+ });
39
+ const outermost = ConfigContext.inject(null) === null;
40
+ if (outermost) {
41
+ const current = useHost();
42
+ watch(() => theme.value, (next) => current.themeChanged?.(next), { immediate: true });
43
+ }
44
+ ConfigContext.provide({
45
+ get lang() {
46
+ return lang.value;
47
+ },
48
+ get rootSx() {
49
+ return [configProviderStyles.root, THEMES[theme.value]];
50
+ }
51
+ });
52
+ return () => [createVNode("div", mergeAttrs({ sx: [configProviderStyles.root, THEMES[theme.value]] }, rest, dataAttrs({ "data-theme": theme.value })), [children.value]), outermost && createVNode(FeedbackOutlet, null, null)];
53
+ }, {
54
+ name: "ConfigProvider",
55
+ props: [
56
+ "theme",
57
+ "lang",
58
+ "host"
59
+ ]
60
+ });
61
+ //#endregion
62
+ export { ConfigProvider, configProviderStyles };
63
+
64
+ //# sourceMappingURL=ConfigProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigProvider.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vtp_untrack","_createVNode"],"sources":["../../src/config/ConfigProvider.tsx"],"sourcesContent":["/**\n * 全局配置:主题(亮色、暗色、跟随系统)与语言。包在每个页面(或应用)外面,里面的组件读它:\n *\n * <ConfigProvider theme=\"system\" lang={enUS}>\n * <Page />\n * </ConfigProvider>\n *\n * 主题是根元素上只改变量的类,换主题不重新渲染组件;根元素也给出页面的字体、字号、文字颜色。\n * 命令式的反馈(showToast、showDialog、showNotify)渲染在最外层的 ConfigProvider 里:用它们的页面要包一层。\n * 不包时组件用简体中文、亮色主题。\n *\n * host 补上或换掉宿主能力(utils/host.ts):H5 没有平台登录,由应用给出 login 等实现:\n *\n * <ConfigProvider host={{ login: () => myOAuth() }}>\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { provide, watch, type VNodeChild } from 'vue';\nimport { FeedbackOutlet } from '../feedback/FeedbackOutlet';\nimport { darkTheme, systemTheme } from '../theme/dark';\nimport { HOST_KEY, useHost, type Host } from '../utils/host';\nimport { dataAttrs, mergeAttrs, type PartProps } from '../utils/props';\nimport { ConfigContext } from './context';\nimport { zhCN, type MobileLang } from './lang';\n\n/** 主题 */\nexport interface MobileThemes {\n /** 亮色 */\n light: unknown;\n /** 暗色 */\n dark: unknown;\n /** 跟随系统的暗色偏好 */\n system: unknown;\n}\n\n/** 未声明的属性落到根元素(div)上;lang 是语言包,不是元素的 lang 属性 */\nexport interface ConfigProviderProps extends PartProps<'div', 'lang'> {\n /**\n * 主题\n * @default 'light'\n */\n theme?: keyof MobileThemes;\n /**\n * 语言包\n * @default zhCN\n */\n lang?: MobileLang;\n /** 补上或换掉的宿主能力(只在创建时读):H5 给出 login 这类应用自己的实现,测试里换成假的 */\n host?: Partial<Host>;\n /** 内容 */\n children?: VNodeChild;\n}\n\n/** ConfigProvider 的样式:root */\nexport const configProviderStyles = css.create({\n root: {\n fontFamily: '_sans',\n fontSize: '_md',\n lineHeight: '_normal',\n color: '_text',\n WebkitTapHighlightColor: 'transparent',\n textSizeAdjust: '100%',\n },\n});\n\nconst THEMES = { light: null, dark: darkTheme, system: systemTheme } as const;\n\n/** 全局配置:主题与语言;根元素是一个 div,后面是命令式反馈的出口 */\nexport const ConfigProvider = _component(\n ({ theme = 'light', lang = zhCN, host, children, ...rest }: ConfigProviderProps) => {\n // 只在创建时读:换宿主能力要重建页面\n const override = _untrack(host);\n if (override) provide(HOST_KEY, { ...useHost(), ...override });\n // 嵌套时只有最外层渲染出口,否则同一条提示会出现两次\n const outermost = ConfigContext.inject(null) === null;\n // 最外层的主题告诉宿主(原生应用的状态栏跟着换)\n if (outermost) {\n const current = useHost();\n watch(\n () => theme,\n (next) => current.themeChanged?.(next),\n { immediate: true },\n );\n }\n ConfigContext.provide({\n get lang() {\n return lang;\n },\n get rootSx() {\n return [configProviderStyles.root, THEMES[theme]];\n },\n });\n return () => [\n <div\n {...mergeAttrs<'div'>(\n { sx: [configProviderStyles.root, THEMES[theme]] },\n rest,\n dataAttrs({ 'data-theme': theme }),\n )}\n >\n {children}\n </div>,\n outermost && <FeedbackOutlet />,\n ];\n },\n);\n"],"mappings":";;;;;;;;;;;;;AAsDA,IAAa,uBAAuB,IAAI,OAAO,EAC7C,MAAM;CACJ,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,OAAO;CACP,yBAAyB;CACzB,gBAAgB;AAClB,EACF,CAAC;AAED,IAAM,SAAS;CAAE,OAAO;CAAM,MAAM;CAAW,QAAQ;AAAY;;AAGnE,IAAa,iBAAiB,0BAC5B,QAAA,SAAoF;CAAA,MAAA,QAAAA,aAAA,QAAA,SAAzE,OAAO;CAAA,MAAA,OAAAA,aAAA,QAAA,cAAS,IAAI;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAqB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEtD,MAAM,WAAQC,cAAA,KAAA,KAAA;CACd,IAAI,UAAU,QAAQ,UAAU;EAAE,GAAG,QAAQ;EAAG,GAAG;CAAS,CAAC;CAE7D,MAAM,YAAY,cAAc,OAAO,IAAI,MAAM;CAEjD,IAAI,WAAW;EACb,MAAM,UAAU,QAAQ;EACxB,YACE,MAAA,QACC,SAAS,QAAQ,eAAe,IAAI,GACrC,EAAE,WAAW,KAAK,CACpB;CACF;CACA,cAAc,QAAQ;EACpB,IAAI,OAAO;GACT,OAAA,KAAA;EACF;EACA,IAAI,SAAS;GACX,OAAO,CAAC,qBAAqB,MAAM,OAAM,MAAA,MAAO;EAClD;CACF,CAAC;CACD,aAAa,CAAAC,YAAA,OAEL,WACF,EAAE,IAAI,CAAC,qBAAqB,MAAM,OAAM,MAAA,MAAO,EAAE,GACjD,MACA,UAAU,EAAE,cAAY,MAAA,MAAQ,CAAC,CACnC,GAAC,CAAA,SAAA,KAAA,CAAA,GAIH,aAASA,YAAA,gBAAA,MAAA,IAAA,CAAsB;AAEnC,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -0,0 +1,16 @@
1
+ import type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
+ import { type MobileLang } from './lang';
3
+ /** 组件读到的配置 */
4
+ export interface MobileConfig {
5
+ /** 语言包 */
6
+ readonly lang: MobileLang;
7
+ /**
8
+ * 浮层根元素要重新挂上的样式:主题类与字体、文字颜色。弹出层 Teleport 到 body(或小程序的浮层根)后
9
+ * 就不在 ConfigProvider 的根元素里了,靠它保持同一个主题
10
+ */
11
+ readonly rootSx: SxStyles;
12
+ }
13
+ /** 配置的上下文 */
14
+ export declare const ConfigContext: import("@zerodep-dev/vue-tsx-pro-tsx").Context<MobileConfig>;
15
+ /** 当前的配置;不在 ConfigProvider 里时是默认配置(简体中文、亮色) */
16
+ export declare const useConfig: () => MobileConfig;
@@ -0,0 +1,20 @@
1
+ import { zhCN } from "./lang.js";
2
+ import { createContext } from "@zerodep-dev/vue-tsx-pro-tsx";
3
+ //#region src/config/context.ts
4
+ /**
5
+ * 配置的上下文:ConfigProvider 提供,组件里 `useConfig()` 读。单独一个模块(不带组件),
6
+ * ConfigProvider 渲染的命令式反馈出口(轻提示、对话框)也要读它,放在一起会互相导入。
7
+ */
8
+ /** 配置的上下文 */
9
+ var ConfigContext = createContext("ConfigProvider");
10
+ /** 不在 ConfigProvider 里时的默认配置 */
11
+ var defaultConfig = {
12
+ lang: zhCN,
13
+ rootSx: null
14
+ };
15
+ /** 当前的配置;不在 ConfigProvider 里时是默认配置(简体中文、亮色) */
16
+ var useConfig = () => ConfigContext.inject(defaultConfig);
17
+ //#endregion
18
+ export { ConfigContext, useConfig };
19
+
20
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/config/context.ts"],"sourcesContent":["/**\n * 配置的上下文:ConfigProvider 提供,组件里 `useConfig()` 读。单独一个模块(不带组件),\n * ConfigProvider 渲染的命令式反馈出口(轻提示、对话框)也要读它,放在一起会互相导入。\n */\nimport { createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { zhCN, type MobileLang } from './lang';\n\n/** 组件读到的配置 */\nexport interface MobileConfig {\n /** 语言包 */\n readonly lang: MobileLang;\n /**\n * 浮层根元素要重新挂上的样式:主题类与字体、文字颜色。弹出层 Teleport 到 body(或小程序的浮层根)后\n * 就不在 ConfigProvider 的根元素里了,靠它保持同一个主题\n */\n readonly rootSx: SxStyles;\n}\n\n/** 配置的上下文 */\nexport const ConfigContext = createContext<MobileConfig>('ConfigProvider');\n\n/** 不在 ConfigProvider 里时的默认配置 */\nconst defaultConfig: MobileConfig = { lang: zhCN, rootSx: null };\n\n/** 当前的配置;不在 ConfigProvider 里时是默认配置(简体中文、亮色) */\nexport const useConfig = (): MobileConfig => ConfigContext.inject(defaultConfig);\n"],"mappings":";;;;;;;;AAoBA,IAAa,gBAAgB,cAA4B,gBAAgB;;AAGzE,IAAM,gBAA8B;CAAE,MAAM;CAAM,QAAQ;AAAK;;AAG/D,IAAa,kBAAgC,cAAc,OAAO,aAAa"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 语言包:组件里出现的文案(确认、取消、加载中、下拉刷新的各阶段……)。地区(locale)用于数字与日期的格式化。
3
+ * 用 ConfigProvider 的 `lang` 换整套,或在默认的基础上改几条:`{ ...zhCN, confirm: '好的' }`
4
+ */
5
+ import type { DevicePermission } from '../capability/types';
6
+ export interface MobileLang {
7
+ /** 地区(BCP 47),数字、日期格式化用 */
8
+ locale: string;
9
+ /** 确认按钮 */
10
+ confirm: string;
11
+ /** 取消按钮 */
12
+ cancel: string;
13
+ /** 关闭按钮的读屏名称 */
14
+ close: string;
15
+ /** 清除按钮的读屏名称 */
16
+ clear: string;
17
+ /** 加载中 */
18
+ loading: string;
19
+ /** 没有数据 */
20
+ empty: string;
21
+ /** 下拉刷新:继续往下拉 */
22
+ pulling: string;
23
+ /** 下拉刷新:松手就刷新 */
24
+ loosing: string;
25
+ /** 下拉刷新:正在刷新 */
26
+ refreshing: string;
27
+ /** 列表:加载失败,点击重试 */
28
+ loadFailed: string;
29
+ /** 列表:没有更多了 */
30
+ noMore: string;
31
+ /** 表单:必填项没填时的消息 */
32
+ fieldRequired: (label: string) => string;
33
+ /** 日期、时间选择器各列的单位(2026 年、10 月);英文留空 */
34
+ dateUnits: {
35
+ year: string;
36
+ month: string;
37
+ day: string;
38
+ hour: string;
39
+ minute: string;
40
+ };
41
+ /** 日历:一周的第一天是周几(0 周日、1 周一)与星期的简称(从周日起) */
42
+ firstDayOfWeek: number;
43
+ weekdays: [string, string, string, string, string, string, string];
44
+ /** 日历:年月的标题 */
45
+ monthTitle: (year: number, month: number) => string;
46
+ /** 回到顶部按钮的读屏名称 */
47
+ backTop: string;
48
+ /** 导航栏只有返回箭头时的读屏名称 */
49
+ back: string;
50
+ /** 搜索框:占位文字、按钮 */
51
+ search: string;
52
+ /** 输入框:已输入字数 / 上限 */
53
+ wordLimit: (count: number, max: number) => string;
54
+ /** 步进器:增加、减少的读屏名称 */
55
+ increase: string;
56
+ decrease: string;
57
+ /** 上传:添加图片、删除 */
58
+ upload: string;
59
+ remove: string;
60
+ /** 选择器、日历:请选择 */
61
+ select: string;
62
+ /** 日历:开始、结束 */
63
+ start: string;
64
+ end: string;
65
+ /** 设备权限的名字(被拒后的引导里用) */
66
+ permissions: Record<DevicePermission, string>;
67
+ /** 权限被拒后引导去设置页:标题、说明、去设置的按钮 */
68
+ permissionDenied: {
69
+ title: string;
70
+ message: (name: string) => string;
71
+ openSettings: string;
72
+ };
73
+ /** 隐私协议弹窗:标题、说明、协议链接、拒绝与同意 */
74
+ privacy: {
75
+ title: string;
76
+ message: string;
77
+ contract: string;
78
+ disagree: string;
79
+ agree: string;
80
+ };
81
+ }
82
+ /** 简体中文 */
83
+ export declare const zhCN: MobileLang;
84
+ /** 英文 */
85
+ export declare const enUS: MobileLang;
@@ -0,0 +1,138 @@
1
+ //#region src/config/lang.ts
2
+ /** 简体中文 */
3
+ var zhCN = {
4
+ locale: "zh-CN",
5
+ confirm: "确认",
6
+ cancel: "取消",
7
+ close: "关闭",
8
+ clear: "清除",
9
+ loading: "加载中…",
10
+ empty: "暂无数据",
11
+ pulling: "下拉即可刷新…",
12
+ loosing: "释放即可刷新…",
13
+ refreshing: "加载中…",
14
+ loadFailed: "加载失败,点击重试",
15
+ fieldRequired: (label) => label ? `请填写${label}` : "请填写",
16
+ search: "搜索",
17
+ backTop: "回到顶部",
18
+ back: "返回",
19
+ dateUnits: {
20
+ year: "年",
21
+ month: "月",
22
+ day: "日",
23
+ hour: "时",
24
+ minute: "分"
25
+ },
26
+ firstDayOfWeek: 1,
27
+ weekdays: [
28
+ "日",
29
+ "一",
30
+ "二",
31
+ "三",
32
+ "四",
33
+ "五",
34
+ "六"
35
+ ],
36
+ monthTitle: (year, month) => `${year} 年 ${month} 月`,
37
+ noMore: "没有更多了",
38
+ wordLimit: (count, max) => `${count}/${max}`,
39
+ increase: "增加",
40
+ decrease: "减少",
41
+ upload: "上传图片",
42
+ remove: "删除",
43
+ select: "请选择",
44
+ start: "开始",
45
+ end: "结束",
46
+ permissions: {
47
+ location: "位置",
48
+ fuzzyLocation: "位置",
49
+ camera: "相机",
50
+ microphone: "麦克风",
51
+ album: "相册",
52
+ bluetooth: "蓝牙"
53
+ },
54
+ permissionDenied: {
55
+ title: "需要权限",
56
+ message: (name) => `你之前拒绝了${name}权限,要用这项功能请在设置里打开`,
57
+ openSettings: "去设置"
58
+ },
59
+ privacy: {
60
+ title: "隐私保护提示",
61
+ message: "使用这项功能前,请阅读并同意隐私保护指引",
62
+ contract: "《隐私保护指引》",
63
+ disagree: "拒绝",
64
+ agree: "同意"
65
+ }
66
+ };
67
+ /** 英文 */
68
+ var enUS = {
69
+ locale: "en-US",
70
+ confirm: "Confirm",
71
+ cancel: "Cancel",
72
+ close: "Close",
73
+ clear: "Clear",
74
+ loading: "Loading…",
75
+ empty: "No data",
76
+ pulling: "Pull to refresh…",
77
+ loosing: "Release to refresh…",
78
+ refreshing: "Loading…",
79
+ loadFailed: "Failed to load, tap to retry",
80
+ fieldRequired: (label) => label ? `${label} is required` : "Required",
81
+ search: "Search",
82
+ backTop: "Back to top",
83
+ back: "Back",
84
+ dateUnits: {
85
+ year: "",
86
+ month: "",
87
+ day: "",
88
+ hour: "",
89
+ minute: ""
90
+ },
91
+ firstDayOfWeek: 0,
92
+ weekdays: [
93
+ "Sun",
94
+ "Mon",
95
+ "Tue",
96
+ "Wed",
97
+ "Thu",
98
+ "Fri",
99
+ "Sat"
100
+ ],
101
+ monthTitle: (year, month) => new Date(year, month - 1, 1).toLocaleDateString("en-US", {
102
+ year: "numeric",
103
+ month: "long"
104
+ }),
105
+ noMore: "No more",
106
+ wordLimit: (count, max) => `${count}/${max}`,
107
+ increase: "Increase",
108
+ decrease: "Decrease",
109
+ upload: "Upload",
110
+ remove: "Remove",
111
+ select: "Select",
112
+ start: "Start",
113
+ end: "End",
114
+ permissions: {
115
+ location: "location",
116
+ fuzzyLocation: "location",
117
+ camera: "camera",
118
+ microphone: "microphone",
119
+ album: "photo album",
120
+ bluetooth: "Bluetooth"
121
+ },
122
+ permissionDenied: {
123
+ title: "Permission needed",
124
+ message: (name) => `You denied ${name} access earlier. Turn it on in Settings to use this feature.`,
125
+ openSettings: "Open Settings"
126
+ },
127
+ privacy: {
128
+ title: "Privacy notice",
129
+ message: "Please read and agree to the privacy policy before using this feature.",
130
+ contract: "Privacy Policy",
131
+ disagree: "Decline",
132
+ agree: "Agree"
133
+ }
134
+ };
135
+ //#endregion
136
+ export { enUS, zhCN };
137
+
138
+ //# sourceMappingURL=lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.js","names":[],"sources":["../../src/config/lang.ts"],"sourcesContent":["/**\n * 语言包:组件里出现的文案(确认、取消、加载中、下拉刷新的各阶段……)。地区(locale)用于数字与日期的格式化。\n * 用 ConfigProvider 的 `lang` 换整套,或在默认的基础上改几条:`{ ...zhCN, confirm: '好的' }`\n */\nimport type { DevicePermission } from '../capability/types';\n\nexport interface MobileLang {\n /** 地区(BCP 47),数字、日期格式化用 */\n locale: string;\n /** 确认按钮 */\n confirm: string;\n /** 取消按钮 */\n cancel: string;\n /** 关闭按钮的读屏名称 */\n close: string;\n /** 清除按钮的读屏名称 */\n clear: string;\n /** 加载中 */\n loading: string;\n /** 没有数据 */\n empty: string;\n /** 下拉刷新:继续往下拉 */\n pulling: string;\n /** 下拉刷新:松手就刷新 */\n loosing: string;\n /** 下拉刷新:正在刷新 */\n refreshing: string;\n /** 列表:加载失败,点击重试 */\n loadFailed: string;\n /** 列表:没有更多了 */\n noMore: string;\n /** 表单:必填项没填时的消息 */\n fieldRequired: (label: string) => string;\n /** 日期、时间选择器各列的单位(2026 年、10 月);英文留空 */\n dateUnits: { year: string; month: string; day: string; hour: string; minute: string };\n /** 日历:一周的第一天是周几(0 周日、1 周一)与星期的简称(从周日起) */\n firstDayOfWeek: number;\n weekdays: [string, string, string, string, string, string, string];\n /** 日历:年月的标题 */\n monthTitle: (year: number, month: number) => string;\n /** 回到顶部按钮的读屏名称 */\n backTop: string;\n /** 导航栏只有返回箭头时的读屏名称 */\n back: string;\n /** 搜索框:占位文字、按钮 */\n search: string;\n /** 输入框:已输入字数 / 上限 */\n wordLimit: (count: number, max: number) => string;\n /** 步进器:增加、减少的读屏名称 */\n increase: string;\n decrease: string;\n /** 上传:添加图片、删除 */\n upload: string;\n remove: string;\n /** 选择器、日历:请选择 */\n select: string;\n /** 日历:开始、结束 */\n start: string;\n end: string;\n /** 设备权限的名字(被拒后的引导里用) */\n permissions: Record<DevicePermission, string>;\n /** 权限被拒后引导去设置页:标题、说明、去设置的按钮 */\n permissionDenied: { title: string; message: (name: string) => string; openSettings: string };\n /** 隐私协议弹窗:标题、说明、协议链接、拒绝与同意 */\n privacy: { title: string; message: string; contract: string; disagree: string; agree: string };\n}\n\n/** 简体中文 */\nexport const zhCN: MobileLang = {\n locale: 'zh-CN',\n confirm: '确认',\n cancel: '取消',\n close: '关闭',\n clear: '清除',\n loading: '加载中…',\n empty: '暂无数据',\n pulling: '下拉即可刷新…',\n loosing: '释放即可刷新…',\n refreshing: '加载中…',\n loadFailed: '加载失败,点击重试',\n fieldRequired: (label) => (label ? `请填写${label}` : '请填写'),\n search: '搜索',\n backTop: '回到顶部',\n back: '返回',\n dateUnits: { year: '年', month: '月', day: '日', hour: '时', minute: '分' },\n firstDayOfWeek: 1,\n weekdays: ['日', '一', '二', '三', '四', '五', '六'],\n monthTitle: (year, month) => `${year} 年 ${month} 月`,\n noMore: '没有更多了',\n wordLimit: (count, max) => `${count}/${max}`,\n increase: '增加',\n decrease: '减少',\n upload: '上传图片',\n remove: '删除',\n select: '请选择',\n start: '开始',\n end: '结束',\n permissions: {\n location: '位置',\n fuzzyLocation: '位置',\n camera: '相机',\n microphone: '麦克风',\n album: '相册',\n bluetooth: '蓝牙',\n },\n permissionDenied: {\n title: '需要权限',\n message: (name) => `你之前拒绝了${name}权限,要用这项功能请在设置里打开`,\n openSettings: '去设置',\n },\n privacy: {\n title: '隐私保护提示',\n message: '使用这项功能前,请阅读并同意隐私保护指引',\n contract: '《隐私保护指引》',\n disagree: '拒绝',\n agree: '同意',\n },\n};\n\n/** 英文 */\nexport const enUS: MobileLang = {\n locale: 'en-US',\n confirm: 'Confirm',\n cancel: 'Cancel',\n close: 'Close',\n clear: 'Clear',\n loading: 'Loading…',\n empty: 'No data',\n pulling: 'Pull to refresh…',\n loosing: 'Release to refresh…',\n refreshing: 'Loading…',\n loadFailed: 'Failed to load, tap to retry',\n fieldRequired: (label) => (label ? `${label} is required` : 'Required'),\n search: 'Search',\n backTop: 'Back to top',\n back: 'Back',\n dateUnits: { year: '', month: '', day: '', hour: '', minute: '' },\n firstDayOfWeek: 0,\n weekdays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n monthTitle: (year, month) =>\n new Date(year, month - 1, 1).toLocaleDateString('en-US', { year: 'numeric', month: 'long' }),\n noMore: 'No more',\n wordLimit: (count, max) => `${count}/${max}`,\n increase: 'Increase',\n decrease: 'Decrease',\n upload: 'Upload',\n remove: 'Remove',\n select: 'Select',\n start: 'Start',\n end: 'End',\n permissions: {\n location: 'location',\n fuzzyLocation: 'location',\n camera: 'camera',\n microphone: 'microphone',\n album: 'photo album',\n bluetooth: 'Bluetooth',\n },\n permissionDenied: {\n title: 'Permission needed',\n message: (name) =>\n `You denied ${name} access earlier. Turn it on in Settings to use this feature.`,\n openSettings: 'Open Settings',\n },\n privacy: {\n title: 'Privacy notice',\n message: 'Please read and agree to the privacy policy before using this feature.',\n contract: 'Privacy Policy',\n disagree: 'Decline',\n agree: 'Agree',\n },\n};\n"],"mappings":";;AAoEA,IAAa,OAAmB;CAC9B,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,OAAO;CACP,OAAO;CACP,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,YAAY;CACZ,YAAY;CACZ,gBAAgB,UAAW,QAAQ,MAAM,UAAU;CACnD,QAAQ;CACR,SAAS;CACT,MAAM;CACN,WAAW;EAAE,MAAM;EAAK,OAAO;EAAK,KAAK;EAAK,MAAM;EAAK,QAAQ;CAAI;CACrE,gBAAgB;CAChB,UAAU;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CAC5C,aAAa,MAAM,UAAU,GAAG,KAAK,KAAK,MAAM;CAChD,QAAQ;CACR,YAAY,OAAO,QAAQ,GAAG,MAAM,GAAG;CACvC,UAAU;CACV,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,KAAK;CACL,aAAa;EACX,UAAU;EACV,eAAe;EACf,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,WAAW;CACb;CACA,kBAAkB;EAChB,OAAO;EACP,UAAU,SAAS,SAAS,KAAK;EACjC,cAAc;CAChB;CACA,SAAS;EACP,OAAO;EACP,SAAS;EACT,UAAU;EACV,UAAU;EACV,OAAO;CACT;AACF;;AAGA,IAAa,OAAmB;CAC9B,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,OAAO;CACP,OAAO;CACP,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,YAAY;CACZ,YAAY;CACZ,gBAAgB,UAAW,QAAQ,GAAG,MAAM,gBAAgB;CAC5D,QAAQ;CACR,SAAS;CACT,MAAM;CACN,WAAW;EAAE,MAAM;EAAI,OAAO;EAAI,KAAK;EAAI,MAAM;EAAI,QAAQ;CAAG;CAChE,gBAAgB;CAChB,UAAU;EAAC;EAAO;EAAO;EAAO;EAAO;EAAO;EAAO;CAAK;CAC1D,aAAa,MAAM,UACjB,IAAI,KAAK,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,mBAAmB,SAAS;EAAE,MAAM;EAAW,OAAO;CAAO,CAAC;CAC7F,QAAQ;CACR,YAAY,OAAO,QAAQ,GAAG,MAAM,GAAG;CACvC,UAAU;CACV,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,KAAK;CACL,aAAa;EACX,UAAU;EACV,eAAe;EACf,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,WAAW;CACb;CACA,kBAAkB;EAChB,OAAO;EACP,UAAU,SACR,cAAc,KAAK;EACrB,cAAc;CAChB;CACA,SAAS;EACP,OAAO;EACP,SAAS;EACT,UAAU;EACV,UAAU;EACV,OAAO;CACT;AACF"}
@@ -0,0 +1,39 @@
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
+ /** 未声明的属性落到外层(span)上 */
5
+ export interface BadgeProps extends PartProps<'span'> {
6
+ /** 数字或文字 */
7
+ content?: number | string;
8
+ /** 数字超过它时显示 `max+` */
9
+ max?: number;
10
+ /** 只显示一个小红点 */
11
+ dot?: boolean;
12
+ /** 内容是 0 时也显示 */
13
+ showZero?: boolean;
14
+ /**
15
+ * 色调
16
+ * @default 'danger'
17
+ */
18
+ tone?: 'danger' | 'accent' | 'success' | 'warning' | 'neutral';
19
+ /** 相对右上角的偏移(px):[向右, 向下] */
20
+ offset?: readonly [number, number];
21
+ /** 被标记的内容;没有时徽标单独显示(行内) */
22
+ children?: VNodeChild;
23
+ /** 徽标本身的部件属性 */
24
+ propsBadge?: PartProps<'span'>;
25
+ }
26
+ /** Badge 的样式:root、badge、corner、dot、各色调 */
27
+ export declare const badgeStyles: Readonly<{
28
+ accent: css.CompiledStyles;
29
+ badge: css.CompiledStyles;
30
+ corner: css.CompiledStyles;
31
+ danger: css.CompiledStyles;
32
+ dot: css.CompiledStyles;
33
+ neutral: css.CompiledStyles;
34
+ root: css.CompiledStyles;
35
+ success: css.CompiledStyles;
36
+ warning: css.CompiledStyles;
37
+ }>;
38
+ /** 徽标(span > 内容 + 徽标) */
39
+ export declare const Badge: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<BadgeProps>;