@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,69 @@
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
+ /** 选择的方式 */
5
+ export interface CalendarTypes {
6
+ /** 一天(默认) */
7
+ single: unknown;
8
+ /** 一段:先点开始,再点结束 */
9
+ range: unknown;
10
+ /** 几天:点一下选上,再点一下取消 */
11
+ multiple: unknown;
12
+ }
13
+ /** 日历的值:一天、一段 [开始, 结束]、几天 */
14
+ export type CalendarValue = Date | [Date, Date] | Date[];
15
+ /** 某一天的额外信息 */
16
+ export interface CalendarDayInfo {
17
+ /** 日子下面的小字(价格、节日) */
18
+ bottom?: VNodeChild;
19
+ /** 这一天不能选 */
20
+ disabled?: boolean;
21
+ }
22
+ /** 未声明的属性落到根元素(div)上 */
23
+ export interface CalendarProps extends Omit<PartProps<'div', 'title'>, 'onSelect'> {
24
+ /**
25
+ * 选择的方式
26
+ * @default 'single'
27
+ */
28
+ type?: keyof CalendarTypes;
29
+ /** 选中的日期;双向绑定写 `_value={x}`(确认时写回) */
30
+ _value?: CalendarValue | null;
31
+ /** 最早可选的日子;默认今天 */
32
+ minDate?: Date;
33
+ /** 最晚可选的日子;默认半年后 */
34
+ maxDate?: Date;
35
+ /** 标题 */
36
+ title?: VNodeChild;
37
+ /**
38
+ * 下面显示确认按钮
39
+ * @default true
40
+ */
41
+ showConfirm?: boolean;
42
+ /** 确认的文字;不给时用语言包 */
43
+ confirmText?: VNodeChild;
44
+ /** 每一天的额外信息 */
45
+ dayInfo?: (day: Date) => CalendarDayInfo | undefined;
46
+ /** 点了一天 */
47
+ onSelect?: (day: Date) => void;
48
+ /** 点了确认(或不显示确认按钮时选完了) */
49
+ onConfirm?: (value: CalendarValue) => void;
50
+ }
51
+ /** Calendar 的样式 */
52
+ export declare const calendarStyles: Readonly<{
53
+ body: css.CompiledStyles;
54
+ bottom: css.CompiledStyles;
55
+ day: css.CompiledStyles;
56
+ days: css.CompiledStyles;
57
+ footer: css.CompiledStyles;
58
+ middle: css.CompiledStyles;
59
+ month: css.CompiledStyles;
60
+ monthTitle: css.CompiledStyles;
61
+ rangeEnd: css.CompiledStyles;
62
+ rangeStart: css.CompiledStyles;
63
+ root: css.CompiledStyles;
64
+ selected: css.CompiledStyles;
65
+ title: css.CompiledStyles;
66
+ weekdays: css.CompiledStyles;
67
+ }>;
68
+ /** 日历(div > 标题 + 星期 + 各月 + 确认) */
69
+ export declare const Calendar: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<CalendarProps>;
@@ -0,0 +1,213 @@
1
+ import { useConfig } from "../config/context.js";
2
+ import { dataAttrs, hasContent, mergeAttrs } from "../utils/props.js";
3
+ import { Button } from "../base/Button.js";
4
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
5
+ import { _component, bindable, mergeJsxProps, overridable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { computed, createVNode } from "vue";
7
+ //#region src/picker/Calendar.tsx
8
+ /** 选择的方式 */
9
+ /** 日历的值:一天、一段 [开始, 结束]、几天 */
10
+ /** 某一天的额外信息 */
11
+ /** 未声明的属性落到根元素(div)上 */
12
+ /** Calendar 的样式 */
13
+ var calendarStyles = css.create({
14
+ root: {
15
+ display: "flex",
16
+ flexDirection: "column",
17
+ backgroundColor: "_surface",
18
+ userSelect: "none"
19
+ },
20
+ title: {
21
+ paddingBlock: "0.8em",
22
+ textAlign: "center",
23
+ fontSize: "_lg",
24
+ fontWeight: "_semibold",
25
+ color: "_text"
26
+ },
27
+ weekdays: {
28
+ display: "grid",
29
+ gridTemplateColumns: "repeat(7, 1fr)",
30
+ paddingBlock: "0.4em",
31
+ fontSize: "_xs",
32
+ color: "_textMuted",
33
+ textAlign: "center",
34
+ boxShadow: "_sm"
35
+ },
36
+ body: {
37
+ height: "22em",
38
+ overflowY: "auto"
39
+ },
40
+ month: { paddingBlockEnd: "_sm" },
41
+ monthTitle: {
42
+ paddingBlock: "0.7em",
43
+ textAlign: "center",
44
+ fontSize: "_md",
45
+ fontWeight: "_medium",
46
+ color: "_text"
47
+ },
48
+ days: {
49
+ display: "grid",
50
+ gridTemplateColumns: "repeat(7, 1fr)",
51
+ rowGap: "0.25em"
52
+ },
53
+ day: {
54
+ display: "flex",
55
+ flexDirection: "column",
56
+ alignItems: "center",
57
+ justifyContent: "center",
58
+ height: "3.4em",
59
+ fontSize: "_md",
60
+ color: {
61
+ default: "_text",
62
+ "[data-disabled]": "_textDisabled"
63
+ },
64
+ cursor: {
65
+ default: "pointer",
66
+ "[data-disabled]": "not-allowed"
67
+ }
68
+ },
69
+ middle: {
70
+ backgroundColor: "_accentSoft",
71
+ color: "_accentText"
72
+ },
73
+ selected: {
74
+ borderRadius: "_md",
75
+ backgroundColor: "_accent",
76
+ color: "_accentContrast"
77
+ },
78
+ rangeStart: {
79
+ borderStartEndRadius: 0,
80
+ borderEndEndRadius: 0
81
+ },
82
+ rangeEnd: {
83
+ borderStartStartRadius: 0,
84
+ borderEndStartRadius: 0
85
+ },
86
+ bottom: {
87
+ fontSize: "0.65em",
88
+ lineHeight: "1.2",
89
+ minHeight: "1.2em"
90
+ },
91
+ footer: {
92
+ paddingBlock: "_sm",
93
+ paddingInline: "_lg",
94
+ paddingBlockEnd: "calc(0.5em + env(safe-area-inset-bottom))"
95
+ }
96
+ });
97
+ /** 某天 0 点 */
98
+ var dayOf = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
99
+ var sameDay = (a, b) => !!a && a.getTime() === dayOf(b).getTime();
100
+ /** 值 → 选中的日子列表(区间时是 [开始, 结束?]) */
101
+ function toDays(value) {
102
+ if (!value) return [];
103
+ return (Array.isArray(value) ? value : [value]).map(dayOf);
104
+ }
105
+ /** 日历(div > 标题 + 星期 + 各月 + 确认) */
106
+ var Calendar = /*#__PURE__*/ _component((_props, _ctx) => {
107
+ const type = readonlyProp(_props, "type", "single");
108
+ const value = bindable(_props, "_value", () => null, _ctx.emit);
109
+ const minDate = readonlyProp(_props, "minDate");
110
+ const maxDate = readonlyProp(_props, "maxDate");
111
+ const title = readonlyProp(_props, "title");
112
+ const showConfirm = readonlyProp(_props, "showConfirm", true);
113
+ const confirmText = readonlyProp(_props, "confirmText");
114
+ const dayInfo = readonlyProp(_props, "dayInfo");
115
+ const onSelect = readonlyProp(_props, "onSelect");
116
+ const onConfirm = readonlyProp(_props, "onConfirm");
117
+ const rest = restProps(_props, _ctx, true);
118
+ const config = useConfig();
119
+ const today = dayOf(/* @__PURE__ */ new Date());
120
+ const min = computed(() => dayOf(minDate.value ?? today));
121
+ const max = computed(() => dayOf(maxDate.value ?? new Date(today.getFullYear(), today.getMonth() + 6, today.getDate())));
122
+ let picked = overridable(() => toDays(value.value));
123
+ /** 各月:从 min 的月份到 max 的月份 */
124
+ const months = computed(() => {
125
+ const list = [];
126
+ for (let cursor = new Date(min.value.getFullYear(), min.value.getMonth(), 1); cursor <= max.value; cursor.setMonth(cursor.getMonth() + 1)) list.push({
127
+ year: cursor.getFullYear(),
128
+ month: cursor.getMonth()
129
+ });
130
+ return list;
131
+ });
132
+ const complete = () => type.value === "range" ? picked.value.length === 2 : picked.value.length > 0;
133
+ const result = () => type.value === "single" ? picked.value[0] : type.value === "range" ? [picked.value[0], picked.value[1]] : [...picked.value];
134
+ const commit = () => {
135
+ if (!complete()) return;
136
+ value.value = result();
137
+ onConfirm.value?.(value.value);
138
+ };
139
+ const choose = (day) => {
140
+ onSelect.value?.(day);
141
+ if (type.value === "single") picked.value = [day];
142
+ else if (type.value === "multiple") picked.value = picked.value.some((item) => sameDay(item, day)) ? picked.value.filter((item) => !sameDay(item, day)) : [...picked.value, day].sort((a, b) => a.getTime() - b.getTime());
143
+ else if (picked.value.length !== 1 || day < picked.value[0]) picked.value = [day];
144
+ else picked.value = [picked.value[0], day];
145
+ if (!showConfirm.value && complete()) commit();
146
+ };
147
+ const renderDay = (day) => {
148
+ const info = dayInfo.value?.(day);
149
+ const disabled = day < min.value || day > max.value || !!info?.disabled;
150
+ const [start, end] = picked.value;
151
+ const isStart = type.value === "range" && sameDay(start, day);
152
+ const isEnd = type.value === "range" && sameDay(end, day);
153
+ const selected = type.value === "range" ? isStart || isEnd : picked.value.some((item) => sameDay(item, day));
154
+ const middle = type.value === "range" && !!start && !!end && day > start && day < end;
155
+ const bottom = isStart ? config.lang.start : isEnd ? config.lang.end : info?.bottom;
156
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [
157
+ calendarStyles.day,
158
+ middle && calendarStyles.middle,
159
+ selected && calendarStyles.selected,
160
+ isStart && !!end && calendarStyles.rangeStart,
161
+ isEnd && calendarStyles.rangeEnd
162
+ ] }), {
163
+ "role": "gridcell",
164
+ "aria-selected": selected ? "true" : void 0,
165
+ "aria-disabled": disabled ? "true" : void 0
166
+ }, dataAttrs({ "data-disabled": disabled }), { "onClick": () => !disabled && choose(day) }), [day.getDate(), createVNode("span", mergeAttrs({ sx: calendarStyles.bottom }), [hasContent(bottom) ? bottom : null])]);
167
+ };
168
+ return () => {
169
+ const first = config.lang.firstDayOfWeek;
170
+ const weekdays = [...config.lang.weekdays.slice(first), ...config.lang.weekdays.slice(0, first)];
171
+ return createVNode("div", mergeAttrs({ sx: calendarStyles.root }, rest), [
172
+ hasContent(title.value) && createVNode("div", mergeAttrs({ sx: calendarStyles.title }), [title.value]),
173
+ createVNode("div", mergeJsxProps(mergeAttrs({ sx: calendarStyles.weekdays }), { "aria-hidden": "true" }), [weekdays.map((name) => createVNode("span", null, [name]))]),
174
+ createVNode("div", mergeAttrs({ sx: calendarStyles.body }), [months.value.map(({ year, month }) => {
175
+ const count = new Date(year, month + 1, 0).getDate();
176
+ const offset = (new Date(year, month, 1).getDay() - first + 7) % 7;
177
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: calendarStyles.month }), {
178
+ "role": "grid",
179
+ "aria-label": config.lang.monthTitle(year, month + 1)
180
+ }), [createVNode("div", mergeAttrs({ sx: calendarStyles.monthTitle }), [config.lang.monthTitle(year, month + 1)]), createVNode("div", mergeAttrs({ sx: calendarStyles.days }), [Array.from({ length: offset }, () => createVNode("span", null, null)), Array.from({ length: count }, (_, index) => renderDay(new Date(year, month, index + 1)))])]);
181
+ })]),
182
+ showConfirm.value && createVNode("div", mergeAttrs({ sx: calendarStyles.footer }), [createVNode(Button, {
183
+ "fullWidth": true,
184
+ "radius": "full",
185
+ "disabled": !complete(),
186
+ "onClick": commit,
187
+ "key": "__site0"
188
+ }, {
189
+ default: () => [confirmText.value ?? config.lang.confirm],
190
+ $stable: true
191
+ })])
192
+ ]);
193
+ };
194
+ }, {
195
+ name: "Calendar",
196
+ props: [
197
+ "type",
198
+ "_value",
199
+ "onUpdate:_value",
200
+ "minDate",
201
+ "maxDate",
202
+ "title",
203
+ "showConfirm",
204
+ "confirmText",
205
+ "dayInfo",
206
+ "onSelect",
207
+ "onConfirm"
208
+ ]
209
+ });
210
+ //#endregion
211
+ export { Calendar, calendarStyles };
212
+
213
+ //# sourceMappingURL=Calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Calendar.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vtp_overridable","_createVNode","_mergeProps"],"sources":["../../src/picker/Calendar.tsx"],"sourcesContent":["/**\n * 日历:按月排开的日期格子,选一天、选一段(入住到离店)、或选几天。常放在底部弹出层里,下面一个确认按钮。\n *\n * <Calendar _value={date} onConfirm={(day) => …} />\n * <Calendar type=\"range\" _value={stay} minDate={today} maxDate={inSixMonths} dayInfo={(day) => ({ bottom: '¥299' })} />\n * <Calendar type=\"multiple\" _value={days} />\n *\n * 选的过程在组件里,点了确认才写回 _value(showConfirm 为 false 时选完就写回)。一周从周几开始、星期的写法随语言包。\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 { Button } from '../base/Button';\nimport { useConfig } from '../config/context';\nimport { dataAttrs, hasContent, mergeAttrs, type PartProps } from '../utils/props';\n\n/** 选择的方式 */\nexport interface CalendarTypes {\n /** 一天(默认) */\n single: unknown;\n /** 一段:先点开始,再点结束 */\n range: unknown;\n /** 几天:点一下选上,再点一下取消 */\n multiple: unknown;\n}\n\n/** 日历的值:一天、一段 [开始, 结束]、几天 */\nexport type CalendarValue = Date | [Date, Date] | Date[];\n\n/** 某一天的额外信息 */\nexport interface CalendarDayInfo {\n /** 日子下面的小字(价格、节日) */\n bottom?: VNodeChild;\n /** 这一天不能选 */\n disabled?: boolean;\n}\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface CalendarProps extends Omit<PartProps<'div', 'title'>, 'onSelect'> {\n /**\n * 选择的方式\n * @default 'single'\n */\n type?: keyof CalendarTypes;\n /** 选中的日期;双向绑定写 `_value={x}`(确认时写回) */\n _value?: CalendarValue | null;\n /** 最早可选的日子;默认今天 */\n minDate?: Date;\n /** 最晚可选的日子;默认半年后 */\n maxDate?: Date;\n /** 标题 */\n title?: VNodeChild;\n /**\n * 下面显示确认按钮\n * @default true\n */\n showConfirm?: boolean;\n /** 确认的文字;不给时用语言包 */\n confirmText?: VNodeChild;\n /** 每一天的额外信息 */\n dayInfo?: (day: Date) => CalendarDayInfo | undefined;\n /** 点了一天 */\n onSelect?: (day: Date) => void;\n /** 点了确认(或不显示确认按钮时选完了) */\n onConfirm?: (value: CalendarValue) => void;\n}\n\n/** Calendar 的样式 */\nexport const calendarStyles = css.create({\n root: {\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '_surface',\n userSelect: 'none',\n },\n title: {\n paddingBlock: '0.8em',\n textAlign: 'center',\n fontSize: '_lg',\n fontWeight: '_semibold',\n color: '_text',\n },\n weekdays: {\n display: 'grid',\n gridTemplateColumns: 'repeat(7, 1fr)',\n paddingBlock: '0.4em',\n fontSize: '_xs',\n color: '_textMuted',\n textAlign: 'center',\n boxShadow: '_sm',\n },\n body: { height: '22em', overflowY: 'auto' },\n month: { paddingBlockEnd: '_sm' },\n monthTitle: {\n paddingBlock: '0.7em',\n textAlign: 'center',\n fontSize: '_md',\n fontWeight: '_medium',\n color: '_text',\n },\n days: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', rowGap: '0.25em' },\n day: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '3.4em',\n fontSize: '_md',\n color: { default: '_text', '[data-disabled]': '_textDisabled' },\n cursor: { default: 'pointer', '[data-disabled]': 'not-allowed' },\n },\n // 区间中间的几天:浅色底连成一条\n middle: { backgroundColor: '_accentSoft', color: '_accentText' },\n selected: { borderRadius: '_md', backgroundColor: '_accent', color: '_accentContrast' },\n rangeStart: { borderStartEndRadius: 0, borderEndEndRadius: 0 },\n rangeEnd: { borderStartStartRadius: 0, borderEndStartRadius: 0 },\n bottom: { fontSize: '0.65em', lineHeight: '1.2', minHeight: '1.2em' },\n footer: {\n paddingBlock: '_sm',\n paddingInline: '_lg',\n paddingBlockEnd: 'calc(0.5em + env(safe-area-inset-bottom))',\n },\n});\n\n/** 某天 0 点 */\nconst dayOf = (date: Date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());\nconst sameDay = (a: Date | undefined, b: Date) => !!a && a.getTime() === dayOf(b).getTime();\n\n/** 值 → 选中的日子列表(区间时是 [开始, 结束?]) */\nfunction toDays(value: CalendarValue | null | undefined): Date[] {\n if (!value) return [];\n return (Array.isArray(value) ? value : [value]).map(dayOf);\n}\n\n/** 日历(div > 标题 + 星期 + 各月 + 确认) */\nexport const Calendar = _component(\n ({\n type = 'single',\n _value: value = _bindable<CalendarValue | null>(null),\n minDate,\n maxDate,\n title,\n showConfirm = true,\n confirmText,\n dayInfo,\n onSelect,\n onConfirm,\n ...rest\n }: CalendarProps) => {\n const config = useConfig();\n const today = dayOf(new Date());\n const min = _derived(dayOf(minDate ?? today));\n const max = _derived(\n dayOf(maxDate ?? new Date(today.getFullYear(), today.getMonth() + 6, today.getDate())),\n );\n // 选的过程:确认前不写回 _value(覆盖派生值);外面改了 _value 时重新跟随\n let picked = _derived(toDays(value));\n\n /** 各月:从 min 的月份到 max 的月份 */\n const months = _derived.by(() => {\n const list: { year: number; month: number }[] = [];\n for (\n let cursor = new Date(min.getFullYear(), min.getMonth(), 1);\n cursor <= max;\n cursor.setMonth(cursor.getMonth() + 1)\n )\n list.push({ year: cursor.getFullYear(), month: cursor.getMonth() });\n return list;\n });\n\n const complete = () => (type === 'range' ? picked.length === 2 : picked.length > 0);\n const result = (): CalendarValue =>\n type === 'single' ? picked[0]! : type === 'range' ? [picked[0]!, picked[1]!] : [...picked];\n const commit = () => {\n if (!complete()) return;\n value = result();\n onConfirm?.(value);\n };\n\n const choose = (day: Date) => {\n onSelect?.(day);\n if (type === 'single') picked = [day];\n else if (type === 'multiple')\n picked = picked.some((item) => sameDay(item, day))\n ? picked.filter((item) => !sameDay(item, day))\n : [...picked, day].sort((a, b) => a.getTime() - b.getTime());\n // 区间:没开始或已经选完时重新开始;点在开始之前时当成新的开始\n else if (picked.length !== 1 || day < picked[0]!) picked = [day];\n else picked = [picked[0]!, day];\n if (!showConfirm && complete()) commit();\n };\n\n const renderDay = (day: Date) => {\n const info = dayInfo?.(day);\n const disabled = day < min || day > max || !!info?.disabled;\n const [start, end] = picked;\n const isStart = type === 'range' && sameDay(start, day);\n const isEnd = type === 'range' && sameDay(end, day);\n const selected =\n type === 'range' ? isStart || isEnd : picked.some((item) => sameDay(item, day));\n const middle = type === 'range' && !!start && !!end && day > start && day < end;\n const bottom = isStart ? config.lang.start : isEnd ? config.lang.end : info?.bottom;\n return (\n <div\n {...mergeAttrs<'div'>({\n sx: [\n calendarStyles.day,\n middle && calendarStyles.middle,\n selected && calendarStyles.selected,\n isStart && !!end && calendarStyles.rangeStart,\n isEnd && calendarStyles.rangeEnd,\n ],\n })}\n role=\"gridcell\"\n aria-selected={selected ? 'true' : undefined}\n aria-disabled={disabled ? 'true' : undefined}\n {...dataAttrs({ 'data-disabled': disabled })}\n onClick={() => !disabled && choose(day)}\n >\n {day.getDate()}\n <span {...mergeAttrs<'span'>({ sx: calendarStyles.bottom })}>\n {hasContent(bottom) ? bottom : null}\n </span>\n </div>\n );\n };\n\n return () => {\n const first = config.lang.firstDayOfWeek;\n const weekdays = [\n ...config.lang.weekdays.slice(first),\n ...config.lang.weekdays.slice(0, first),\n ];\n return (\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.root }, rest)}>\n {hasContent(title) && (\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.title })}>{title}</div>\n )}\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.weekdays })} aria-hidden=\"true\">\n {weekdays.map((name) => (\n <span>{name}</span>\n ))}\n </div>\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.body })}>\n {months.map(({ year, month }) => {\n const count = new Date(year, month + 1, 0).getDate();\n // 第一天前面空几格\n const offset = (new Date(year, month, 1).getDay() - first + 7) % 7;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: calendarStyles.month })}\n role=\"grid\"\n aria-label={config.lang.monthTitle(year, month + 1)}\n >\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.monthTitle })}>\n {config.lang.monthTitle(year, month + 1)}\n </div>\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.days })}>\n {Array.from({ length: offset }, () => (\n <span />\n ))}\n {Array.from({ length: count }, (_, index) =>\n renderDay(new Date(year, month, index + 1)),\n )}\n </div>\n </div>\n );\n })}\n </div>\n {showConfirm && (\n <div {...mergeAttrs<'div'>({ sx: calendarStyles.footer })}>\n <Button fullWidth radius=\"full\" disabled={!complete()} onClick={commit}>\n {confirmText ?? config.lang.confirm}\n </Button>\n </div>\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,50 @@
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 { PickerOption } from './PickerColumn';
5
+ /** 选择的结果 */
6
+ export interface CascaderResult {
7
+ /** 最后一级的值 */
8
+ value: string | number;
9
+ /** 一路选的各级选项 */
10
+ selectedOptions: PickerOption[];
11
+ }
12
+ /** 未声明的属性落到根元素(div)上 */
13
+ export interface CascaderProps extends Omit<PartProps<'div', 'title' | 'placeholder'>, 'onChange'> {
14
+ /** 选项树(选项带 children 时有下一级) */
15
+ options: PickerOption[];
16
+ /** 最后一级选中的值;双向绑定写 `_value={x}` */
17
+ _value?: string | number;
18
+ /** 标题 */
19
+ title?: VNodeChild;
20
+ /** 还没选的那一级标签上的文字;不给时用语言包的“请选择” */
21
+ placeholder?: VNodeChild;
22
+ /**
23
+ * 右上角的关闭按钮
24
+ * @default true
25
+ */
26
+ closeable?: boolean;
27
+ /** 选了某一级的一项 */
28
+ onChange?: (result: CascaderResult & {
29
+ tabIndex: number;
30
+ }) => void;
31
+ /** 选到了最后一级 */
32
+ onFinish?: (result: CascaderResult) => void;
33
+ /** 点了关闭 */
34
+ onClose?: () => void;
35
+ }
36
+ /** Cascader 的样式 */
37
+ export declare const cascaderStyles: Readonly<{
38
+ close: css.CompiledStyles;
39
+ header: css.CompiledStyles;
40
+ list: css.CompiledStyles;
41
+ option: css.CompiledStyles;
42
+ root: css.CompiledStyles;
43
+ tab: css.CompiledStyles;
44
+ tabs: css.CompiledStyles;
45
+ title: css.CompiledStyles;
46
+ }>;
47
+ /** 在选项树里找到值为 value 的项,返回一路上的选项 */
48
+ export declare function findPath(options: PickerOption[], value: string | number | undefined): PickerOption[];
49
+ /** 级联选择(div > 标题栏 + 各级标签 + 当前一级的选项) */
50
+ export declare const Cascader: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<CascaderProps>;
@@ -0,0 +1,199 @@
1
+ import { useConfig } from "../config/context.js";
2
+ import { dataAttrs, hasContent, mergeAttrs } from "../utils/props.js";
3
+ import { Icon } from "../base/Icon.js";
4
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
5
+ import { _component, bindable, mergeJsxProps, overridable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode } from "vue";
7
+ import { Check, X } from "@lucide/icons";
8
+ //#region src/picker/Cascader.tsx
9
+ /**
10
+ * 级联选择:一级级往下选(省 → 市 → 区),上面一排标签显示每一级选了什么(点标签回到那一级重选),下面是当前这一级的选项。
11
+ * 选到没有下一级的项时完成。常放在底部弹出层里。
12
+ *
13
+ * <Cascader title="所在地区" options={areaOptions()} _value={code} onFinish={({ selectedOptions }) => …} onClose={…} />
14
+ *
15
+ * _value 是最后一级的值;给了时按它找回整条路径。
16
+ */
17
+ /** 选择的结果 */
18
+ /** 未声明的属性落到根元素(div)上 */
19
+ /** Cascader 的样式 */
20
+ var cascaderStyles = css.create({
21
+ root: {
22
+ backgroundColor: "_surface",
23
+ userSelect: "none"
24
+ },
25
+ header: {
26
+ display: "flex",
27
+ alignItems: "center",
28
+ justifyContent: "space-between",
29
+ height: "3em",
30
+ paddingInline: "_lg"
31
+ },
32
+ title: {
33
+ fontSize: "_lg",
34
+ fontWeight: "_semibold",
35
+ color: "_text"
36
+ },
37
+ close: {
38
+ display: "inline-flex",
39
+ margin: 0,
40
+ padding: 0,
41
+ borderWidth: 0,
42
+ backgroundColor: "transparent",
43
+ color: "_textMuted",
44
+ fontSize: "_xl",
45
+ cursor: "pointer"
46
+ },
47
+ tabs: {
48
+ display: "flex",
49
+ gap: "_lg",
50
+ overflowX: "auto",
51
+ paddingInline: "_lg",
52
+ borderBlockEndWidth: "_hairline",
53
+ borderBlockEndStyle: "solid",
54
+ borderBlockEndColor: "_border",
55
+ scrollbarWidth: "none"
56
+ },
57
+ tab: {
58
+ position: "relative",
59
+ flex: "none",
60
+ maxWidth: "8em",
61
+ height: "2.6em",
62
+ margin: 0,
63
+ padding: 0,
64
+ borderWidth: 0,
65
+ backgroundColor: "transparent",
66
+ overflow: "hidden",
67
+ whiteSpace: "nowrap",
68
+ textOverflow: "ellipsis",
69
+ color: {
70
+ default: "_text",
71
+ "[data-empty]": "_textMuted"
72
+ },
73
+ fontFamily: "inherit",
74
+ fontSize: "_md",
75
+ fontWeight: {
76
+ default: "_normal",
77
+ "[aria-selected=\"true\"]": "_semibold"
78
+ },
79
+ cursor: "pointer",
80
+ backgroundImage: {
81
+ default: "none",
82
+ "[aria-selected=\"true\"]": "linear-gradient(currentColor, currentColor)"
83
+ },
84
+ backgroundSize: "1.6em 0.2em",
85
+ backgroundPosition: "center bottom",
86
+ backgroundRepeat: "no-repeat"
87
+ },
88
+ list: {
89
+ height: "22em",
90
+ overflowY: "auto",
91
+ paddingBlock: "_sm"
92
+ },
93
+ option: {
94
+ display: "flex",
95
+ alignItems: "center",
96
+ justifyContent: "space-between",
97
+ paddingBlock: "0.65em",
98
+ paddingInline: "_lg",
99
+ fontSize: "_md",
100
+ color: {
101
+ default: "_text",
102
+ "[aria-selected=\"true\"]": "_accentText",
103
+ "[data-disabled]": "_textDisabled"
104
+ },
105
+ backgroundColor: {
106
+ default: "transparent",
107
+ ":active:not([data-disabled])": "_fillActive"
108
+ },
109
+ cursor: {
110
+ default: "pointer",
111
+ "[data-disabled]": "not-allowed"
112
+ }
113
+ }
114
+ });
115
+ /** 在选项树里找到值为 value 的项,返回一路上的选项 */
116
+ function findPath(options, value) {
117
+ if (value === void 0) return [];
118
+ for (const option of options) {
119
+ if (option.value === value) return [option];
120
+ const rest = findPath(option.children ?? [], value);
121
+ if (rest.length) return [option, ...rest];
122
+ }
123
+ return [];
124
+ }
125
+ /** 级联选择(div > 标题栏 + 各级标签 + 当前一级的选项) */
126
+ var Cascader = /*#__PURE__*/ _component((_props, _ctx) => {
127
+ const _cache = [];
128
+ const options = readonlyProp(_props, "options");
129
+ const value = bindable(_props, "_value", () => void 0, _ctx.emit);
130
+ const title = readonlyProp(_props, "title");
131
+ const placeholder = readonlyProp(_props, "placeholder");
132
+ const closeable = readonlyProp(_props, "closeable", true);
133
+ const onChange = readonlyProp(_props, "onChange");
134
+ const onFinish = readonlyProp(_props, "onFinish");
135
+ const onClose = readonlyProp(_props, "onClose");
136
+ const rest = restProps(_props, _ctx, true);
137
+ const config = useConfig();
138
+ let path = overridable(() => findPath(options.value, value.value));
139
+ let tab = overridable(() => Math.max(0, path.value.length - 1));
140
+ /** 第 level 级的选项 */
141
+ const levelOptions = (level) => level === 0 ? options.value : path.value[level - 1]?.children ?? [];
142
+ const choose = (level, option) => {
143
+ if (option.disabled) return;
144
+ path.value = [...path.value.slice(0, level), option];
145
+ const result = {
146
+ value: option.value,
147
+ selectedOptions: path.value
148
+ };
149
+ onChange.value?.({
150
+ ...result,
151
+ tabIndex: level
152
+ });
153
+ if (option.children?.length) tab.value = level + 1;
154
+ else {
155
+ value.value = option.value;
156
+ onFinish.value?.(result);
157
+ }
158
+ };
159
+ return () => {
160
+ const levels = path.value.length + (path.value[path.value.length - 1]?.children?.length || !path.value.length ? 1 : 0);
161
+ return createVNode("div", mergeAttrs({ sx: cascaderStyles.root }, rest), [
162
+ createVNode("div", mergeAttrs({ sx: cascaderStyles.header }), [createVNode("span", mergeAttrs({ sx: cascaderStyles.title }), [hasContent(title.value) ? title.value : null]), closeable.value && createVNode("button", mergeJsxProps(mergeAttrs({ sx: cascaderStyles.close }), {
163
+ "type": "button",
164
+ "aria-label": config.lang.close,
165
+ "onClick": _cache[0] || (_cache[0] = () => onClose.value?.())
166
+ }), [createVNode(Icon, { "icon": X }, null)])]),
167
+ createVNode("div", mergeJsxProps(mergeAttrs({ sx: cascaderStyles.tabs }), { "role": "tablist" }), [Array.from({ length: levels }, (_, level) => createVNode("button", mergeJsxProps(mergeAttrs({ sx: cascaderStyles.tab }), {
168
+ "type": "button",
169
+ "role": "tab",
170
+ "aria-selected": level === tab.value ? "true" : "false"
171
+ }, dataAttrs({ "data-empty": !path.value[level] }), { "onClick": () => tab.value = level }), [path.value[level]?.text ?? placeholder.value ?? config.lang.select]))]),
172
+ createVNode("div", mergeJsxProps(mergeAttrs({ sx: cascaderStyles.list }), { "role": "listbox" }), [levelOptions(tab.value).map((option) => {
173
+ const selected = path.value[tab.value]?.value === option.value;
174
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: cascaderStyles.option }), {
175
+ "role": "option",
176
+ "aria-selected": selected ? "true" : "false",
177
+ "aria-disabled": option.disabled ? "true" : void 0
178
+ }, dataAttrs({ "data-disabled": option.disabled }), { "onClick": () => choose(tab.value, option) }), [createVNode("span", null, [option.text]), selected && createVNode(Icon, { "icon": Check }, null)]);
179
+ })])
180
+ ]);
181
+ };
182
+ }, {
183
+ name: "Cascader",
184
+ props: [
185
+ "options",
186
+ "_value",
187
+ "onUpdate:_value",
188
+ "title",
189
+ "placeholder",
190
+ "closeable",
191
+ "onChange",
192
+ "onFinish",
193
+ "onClose"
194
+ ]
195
+ });
196
+ //#endregion
197
+ export { Cascader, cascaderStyles, findPath };
198
+
199
+ //# sourceMappingURL=Cascader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cascader.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vtp_overridable","_createVNode","_mergeProps"],"sources":["../../src/picker/Cascader.tsx"],"sourcesContent":["/**\n * 级联选择:一级级往下选(省 → 市 → 区),上面一排标签显示每一级选了什么(点标签回到那一级重选),下面是当前这一级的选项。\n * 选到没有下一级的项时完成。常放在底部弹出层里。\n *\n * <Cascader title=\"所在地区\" options={areaOptions()} _value={code} onFinish={({ selectedOptions }) => …} onClose={…} />\n *\n * _value 是最后一级的值;给了时按它找回整条路径。\n */\nimport { Check, X } from '@lucide/icons';\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 } from '../base/Icon';\nimport { useConfig } from '../config/context';\nimport { dataAttrs, hasContent, mergeAttrs, type PartProps } from '../utils/props';\nimport type { PickerOption } from './PickerColumn';\n\n/** 选择的结果 */\nexport interface CascaderResult {\n /** 最后一级的值 */\n value: string | number;\n /** 一路选的各级选项 */\n selectedOptions: PickerOption[];\n}\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface CascaderProps extends Omit<PartProps<'div', 'title' | 'placeholder'>, 'onChange'> {\n /** 选项树(选项带 children 时有下一级) */\n options: PickerOption[];\n /** 最后一级选中的值;双向绑定写 `_value={x}` */\n _value?: string | number;\n /** 标题 */\n title?: VNodeChild;\n /** 还没选的那一级标签上的文字;不给时用语言包的“请选择” */\n placeholder?: VNodeChild;\n /**\n * 右上角的关闭按钮\n * @default true\n */\n closeable?: boolean;\n /** 选了某一级的一项 */\n onChange?: (result: CascaderResult & { tabIndex: number }) => void;\n /** 选到了最后一级 */\n onFinish?: (result: CascaderResult) => void;\n /** 点了关闭 */\n onClose?: () => void;\n}\n\n/** Cascader 的样式 */\nexport const cascaderStyles = css.create({\n root: { backgroundColor: '_surface', userSelect: 'none' },\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n height: '3em',\n paddingInline: '_lg',\n },\n title: { fontSize: '_lg', fontWeight: '_semibold', color: '_text' },\n close: {\n display: 'inline-flex',\n margin: 0,\n padding: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n color: '_textMuted',\n fontSize: '_xl',\n cursor: 'pointer',\n },\n tabs: {\n display: 'flex',\n gap: '_lg',\n overflowX: 'auto',\n paddingInline: '_lg',\n borderBlockEndWidth: '_hairline',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_border',\n scrollbarWidth: 'none',\n },\n tab: {\n position: 'relative',\n flex: 'none',\n maxWidth: '8em',\n height: '2.6em',\n margin: 0,\n padding: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n color: { default: '_text', '[data-empty]': '_textMuted' },\n fontFamily: 'inherit',\n fontSize: '_md',\n fontWeight: { default: '_normal', '[aria-selected=\"true\"]': '_semibold' },\n cursor: 'pointer',\n // 当前一级的下划线(背景渐变画在底部,不用伪元素)\n backgroundImage: {\n default: 'none',\n '[aria-selected=\"true\"]': 'linear-gradient(currentColor, currentColor)',\n },\n backgroundSize: '1.6em 0.2em',\n backgroundPosition: 'center bottom',\n backgroundRepeat: 'no-repeat',\n },\n list: { height: '22em', overflowY: 'auto', paddingBlock: '_sm' },\n option: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingBlock: '0.65em',\n paddingInline: '_lg',\n fontSize: '_md',\n color: {\n default: '_text',\n '[aria-selected=\"true\"]': '_accentText',\n '[data-disabled]': '_textDisabled',\n },\n backgroundColor: { default: 'transparent', ':active:not([data-disabled])': '_fillActive' },\n cursor: { default: 'pointer', '[data-disabled]': 'not-allowed' },\n },\n});\n\n/** 在选项树里找到值为 value 的项,返回一路上的选项 */\nexport function findPath(\n options: PickerOption[],\n value: string | number | undefined,\n): PickerOption[] {\n if (value === undefined) return [];\n for (const option of options) {\n if (option.value === value) return [option];\n const rest = findPath(option.children ?? [], value);\n if (rest.length) return [option, ...rest];\n }\n return [];\n}\n\n/** 级联选择(div > 标题栏 + 各级标签 + 当前一级的选项) */\nexport const Cascader = _component(\n ({\n options,\n _value: value = _bindable<string | number | undefined>(undefined),\n title,\n placeholder,\n closeable = true,\n onChange,\n onFinish,\n onClose,\n ...rest\n }: CascaderProps) => {\n const config = useConfig();\n // 一路选的项:按 _value 找回,选的过程中覆盖;外面改了 _value 时重新跟随\n let path = _derived(findPath(options, value));\n // 当前的一级:默认是最后选的那一级,点标签、选了有下一级的项时覆盖\n let tab = _derived(Math.max(0, path.length - 1));\n /** 第 level 级的选项 */\n const levelOptions = (level: number) =>\n level === 0 ? options : (path[level - 1]?.children ?? []);\n const choose = (level: number, option: PickerOption) => {\n if (option.disabled) return;\n path = [...path.slice(0, level), option];\n const result = { value: option.value, selectedOptions: path };\n onChange?.({ ...result, tabIndex: level });\n if (option.children?.length) tab = level + 1;\n else {\n value = option.value;\n onFinish?.(result);\n }\n };\n\n return () => {\n // 标签:选过的各级,加上还没选的下一级\n const levels =\n path.length + (path[path.length - 1]?.children?.length || !path.length ? 1 : 0);\n return (\n <div {...mergeAttrs<'div'>({ sx: cascaderStyles.root }, rest)}>\n <div {...mergeAttrs<'div'>({ sx: cascaderStyles.header })}>\n <span {...mergeAttrs<'span'>({ sx: cascaderStyles.title })}>\n {hasContent(title) ? title : null}\n </span>\n {closeable && (\n <button\n {...mergeAttrs<'button'>({ sx: cascaderStyles.close })}\n type=\"button\"\n aria-label={config.lang.close}\n onClick={() => onClose?.()}\n >\n <Icon icon={X} />\n </button>\n )}\n </div>\n <div {...mergeAttrs<'div'>({ sx: cascaderStyles.tabs })} role=\"tablist\">\n {Array.from({ length: levels }, (_, level) => (\n <button\n {...mergeAttrs<'button'>({ sx: cascaderStyles.tab })}\n type=\"button\"\n role=\"tab\"\n aria-selected={level === tab ? 'true' : 'false'}\n {...dataAttrs({ 'data-empty': !path[level] })}\n onClick={() => (tab = level)}\n >\n {path[level]?.text ?? placeholder ?? config.lang.select}\n </button>\n ))}\n </div>\n <div {...mergeAttrs<'div'>({ sx: cascaderStyles.list })} role=\"listbox\">\n {levelOptions(tab).map((option) => {\n const selected = path[tab]?.value === option.value;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: cascaderStyles.option })}\n role=\"option\"\n aria-selected={selected ? 'true' : 'false'}\n aria-disabled={option.disabled ? 'true' : undefined}\n {...dataAttrs({ 'data-disabled': option.disabled })}\n onClick={() => choose(tab, option)}\n >\n <span>{option.text}</span>\n {selected && <Icon icon={Check} />}\n </div>\n );\n })}\n </div>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { VNodeChild } from 'vue';
2
+ import type { PartProps } from '../utils/props';
3
+ /** 日期的列 */
4
+ export type DateColumn = 'year' | 'month' | 'day';
5
+ /** 共有的属性 */
6
+ interface PickerShellProps extends Omit<PartProps<'div', 'title'>, 'onChange'> {
7
+ /** 标题 */
8
+ title?: VNodeChild;
9
+ /** 点了取消 */
10
+ onCancel?: () => void;
11
+ /** 可见的行数 */
12
+ visibleItemCount?: number;
13
+ }
14
+ /** 未声明的属性落到选择器的根元素上 */
15
+ export interface DatePickerProps extends PickerShellProps {
16
+ /** 选中的日期;双向绑定写 `_value={x}`。不给时是今天(限在范围内) */
17
+ _value?: Date;
18
+ /** 最早的日期;默认十年前的 1 月 1 日 */
19
+ minDate?: Date;
20
+ /** 最晚的日期;默认十年后的 12 月 31 日 */
21
+ maxDate?: Date;
22
+ /**
23
+ * 显示哪几列
24
+ * @default ['year', 'month', 'day']
25
+ */
26
+ columns?: DateColumn[];
27
+ /** 点了确认 */
28
+ onConfirm?: (date: Date) => void;
29
+ }
30
+ /** 日期选择器(Picker) */
31
+ export declare const DatePicker: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<DatePickerProps>;
32
+ /** 未声明的属性落到选择器的根元素上 */
33
+ export interface TimePickerProps extends PickerShellProps {
34
+ /** 选中的时间 "HH:mm";双向绑定写 `_value={x}`。不给时是 00:00 */
35
+ _value?: string;
36
+ /**
37
+ * 最小、最大的小时
38
+ * @default 0、23
39
+ */
40
+ minHour?: number;
41
+ maxHour?: number;
42
+ /**
43
+ * 分钟的步长
44
+ * @default 1
45
+ */
46
+ minuteStep?: number;
47
+ /** 点了确认 */
48
+ onConfirm?: (time: string) => void;
49
+ }
50
+ /** 时间选择器(Picker:时、分两列) */
51
+ export declare const TimePicker: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<TimePickerProps>;
52
+ export {};