@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.
- package/LICENSE +21 -0
- package/README.md +29 -2
- package/dist/area/data.d.ts +10 -0
- package/dist/area/data.js +3899 -0
- package/dist/area/data.js.map +1 -0
- package/dist/area/index.d.ts +22 -0
- package/dist/area/index.js +41 -0
- package/dist/area/index.js.map +1 -0
- package/dist/base/Button.d.ts +170 -0
- package/dist/base/Button.js +537 -0
- package/dist/base/Button.js.map +1 -0
- package/dist/base/Icon.d.ts +38 -0
- package/dist/base/Icon.js +65 -0
- package/dist/base/Icon.js.map +1 -0
- package/dist/capability/PrivacyPrompt.d.ts +1 -0
- package/dist/capability/PrivacyPrompt.js +73 -0
- package/dist/capability/PrivacyPrompt.js.map +1 -0
- package/dist/capability/types.d.ts +92 -0
- package/dist/capability/usePermission.d.ts +23 -0
- package/dist/capability/usePermission.js +52 -0
- package/dist/capability/usePermission.js.map +1 -0
- package/dist/capability/useStorage.d.ts +8 -0
- package/dist/capability/useStorage.js +19 -0
- package/dist/capability/useStorage.js.map +1 -0
- package/dist/capability/web.d.ts +18 -0
- package/dist/capability/web.js +109 -0
- package/dist/capability/web.js.map +1 -0
- package/dist/capacitor/index.d.ts +9 -0
- package/dist/capacitor/index.js +143 -0
- package/dist/capacitor/index.js.map +1 -0
- package/dist/config/ConfigProvider.d.ts +37 -0
- package/dist/config/ConfigProvider.js +64 -0
- package/dist/config/ConfigProvider.js.map +1 -0
- package/dist/config/context.d.ts +16 -0
- package/dist/config/context.js +20 -0
- package/dist/config/context.js.map +1 -0
- package/dist/config/lang.d.ts +85 -0
- package/dist/config/lang.js +138 -0
- package/dist/config/lang.js.map +1 -0
- package/dist/display/Badge.d.ts +39 -0
- package/dist/display/Badge.js +108 -0
- package/dist/display/Badge.js.map +1 -0
- package/dist/display/Cell.d.ts +92 -0
- package/dist/display/Cell.js +204 -0
- package/dist/display/Cell.js.map +1 -0
- package/dist/display/Collapse.d.ts +47 -0
- package/dist/display/Collapse.js +173 -0
- package/dist/display/Collapse.js.map +1 -0
- package/dist/display/Empty.d.ts +42 -0
- package/dist/display/Empty.js +79 -0
- package/dist/display/Empty.js.map +1 -0
- package/dist/display/Grid.d.ts +49 -0
- package/dist/display/Grid.js +136 -0
- package/dist/display/Grid.js.map +1 -0
- package/dist/display/Image.d.ts +70 -0
- package/dist/display/Image.js +138 -0
- package/dist/display/Image.js.map +1 -0
- package/dist/display/IndexBar.d.ts +34 -0
- package/dist/display/IndexBar.js +158 -0
- package/dist/display/IndexBar.js.map +1 -0
- package/dist/display/List.d.ts +34 -0
- package/dist/display/List.js +105 -0
- package/dist/display/List.js.map +1 -0
- package/dist/display/NoticeBar.d.ts +57 -0
- package/dist/display/NoticeBar.js +172 -0
- package/dist/display/NoticeBar.js.map +1 -0
- package/dist/display/Steps.d.ts +59 -0
- package/dist/display/Steps.js +158 -0
- package/dist/display/Steps.js.map +1 -0
- package/dist/display/SwipeCell.d.ts +37 -0
- package/dist/display/SwipeCell.js +147 -0
- package/dist/display/SwipeCell.js.map +1 -0
- package/dist/display/Swiper.d.ts +47 -0
- package/dist/display/Swiper.js +173 -0
- package/dist/display/Swiper.js.map +1 -0
- package/dist/display/Tag.d.ts +99 -0
- package/dist/display/Tag.js +320 -0
- package/dist/display/Tag.js.map +1 -0
- package/dist/feedback/Dialog.d.ts +79 -0
- package/dist/feedback/Dialog.js +186 -0
- package/dist/feedback/Dialog.js.map +1 -0
- package/dist/feedback/FeedbackOutlet.d.ts +2 -0
- package/dist/feedback/FeedbackOutlet.js +31 -0
- package/dist/feedback/FeedbackOutlet.js.map +1 -0
- package/dist/feedback/Loading.d.ts +26 -0
- package/dist/feedback/Loading.js +68 -0
- package/dist/feedback/Loading.js.map +1 -0
- package/dist/feedback/Notify.d.ts +48 -0
- package/dist/feedback/Notify.js +116 -0
- package/dist/feedback/Notify.js.map +1 -0
- package/dist/feedback/PullRefresh.d.ts +58 -0
- package/dist/feedback/PullRefresh.js +178 -0
- package/dist/feedback/PullRefresh.js.map +1 -0
- package/dist/feedback/Skeleton.d.ts +56 -0
- package/dist/feedback/Skeleton.js +99 -0
- package/dist/feedback/Skeleton.js.map +1 -0
- package/dist/feedback/Toast.d.ts +89 -0
- package/dist/feedback/Toast.js +186 -0
- package/dist/feedback/Toast.js.map +1 -0
- package/dist/form/Checkbox.d.ts +52 -0
- package/dist/form/Checkbox.js +107 -0
- package/dist/form/Checkbox.js.map +1 -0
- package/dist/form/Field.d.ts +91 -0
- package/dist/form/Field.js +296 -0
- package/dist/form/Field.js.map +1 -0
- package/dist/form/Form.d.ts +50 -0
- package/dist/form/Form.js +96 -0
- package/dist/form/Form.js.map +1 -0
- package/dist/form/FormItem.d.ts +57 -0
- package/dist/form/FormItem.js +142 -0
- package/dist/form/FormItem.js.map +1 -0
- package/dist/form/Radio.d.ts +41 -0
- package/dist/form/Radio.js +85 -0
- package/dist/form/Radio.js.map +1 -0
- package/dist/form/Rate.d.ts +45 -0
- package/dist/form/Rate.js +162 -0
- package/dist/form/Rate.js.map +1 -0
- package/dist/form/Search.d.ts +50 -0
- package/dist/form/Search.js +152 -0
- package/dist/form/Search.js.map +1 -0
- package/dist/form/Slider.d.ts +43 -0
- package/dist/form/Slider.js +213 -0
- package/dist/form/Slider.js.map +1 -0
- package/dist/form/Stepper.d.ts +61 -0
- package/dist/form/Stepper.js +222 -0
- package/dist/form/Stepper.js.map +1 -0
- package/dist/form/Switch.d.ts +33 -0
- package/dist/form/Switch.js +116 -0
- package/dist/form/Switch.js.map +1 -0
- package/dist/form/Uploader.d.ts +67 -0
- package/dist/form/Uploader.js +207 -0
- package/dist/form/Uploader.js.map +1 -0
- package/dist/form/choice.d.ts +42 -0
- package/dist/form/choice.js +109 -0
- package/dist/form/choice.js.map +1 -0
- package/dist/form/context.d.ts +83 -0
- package/dist/form/context.js +89 -0
- package/dist/form/context.js.map +1 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +59 -0
- package/dist/layout/Divider.d.ts +34 -0
- package/dist/layout/Divider.js +55 -0
- package/dist/layout/Divider.js.map +1 -0
- package/dist/layout/Space.d.ts +66 -0
- package/dist/layout/Space.js +65 -0
- package/dist/layout/Space.js.map +1 -0
- package/dist/navigation/BackTop.d.ts +29 -0
- package/dist/navigation/BackTop.js +89 -0
- package/dist/navigation/BackTop.js.map +1 -0
- package/dist/navigation/NavBar.d.ts +46 -0
- package/dist/navigation/NavBar.js +141 -0
- package/dist/navigation/NavBar.js.map +1 -0
- package/dist/navigation/Sticky.d.ts +19 -0
- package/dist/navigation/Sticky.js +28 -0
- package/dist/navigation/Sticky.js.map +1 -0
- package/dist/navigation/TabBar.d.ts +54 -0
- package/dist/navigation/TabBar.js +138 -0
- package/dist/navigation/TabBar.js.map +1 -0
- package/dist/navigation/Tabs.d.ts +45 -0
- package/dist/navigation/Tabs.js +206 -0
- package/dist/navigation/Tabs.js.map +1 -0
- package/dist/overlay/ActionSheet.d.ts +80 -0
- package/dist/overlay/ActionSheet.js +164 -0
- package/dist/overlay/ActionSheet.js.map +1 -0
- package/dist/overlay/Overlay.d.ts +35 -0
- package/dist/overlay/Overlay.js +85 -0
- package/dist/overlay/Overlay.js.map +1 -0
- package/dist/overlay/Popup.d.ts +76 -0
- package/dist/overlay/Popup.js +191 -0
- package/dist/overlay/Popup.js.map +1 -0
- package/dist/picker/Calendar.d.ts +69 -0
- package/dist/picker/Calendar.js +213 -0
- package/dist/picker/Calendar.js.map +1 -0
- package/dist/picker/Cascader.d.ts +50 -0
- package/dist/picker/Cascader.js +199 -0
- package/dist/picker/Cascader.js.map +1 -0
- package/dist/picker/DatePicker.d.ts +52 -0
- package/dist/picker/DatePicker.js +135 -0
- package/dist/picker/DatePicker.js.map +1 -0
- package/dist/picker/DropdownMenu.d.ts +39 -0
- package/dist/picker/DropdownMenu.js +242 -0
- package/dist/picker/DropdownMenu.js.map +1 -0
- package/dist/picker/Picker.d.ts +67 -0
- package/dist/picker/Picker.js +185 -0
- package/dist/picker/Picker.js.map +1 -0
- package/dist/picker/PickerColumn.d.ts +36 -0
- package/dist/picker/PickerColumn.js +175 -0
- package/dist/picker/PickerColumn.js.map +1 -0
- package/dist/theme/dark.d.ts +121 -0
- package/dist/theme/dark.js +77 -0
- package/dist/theme/dark.js.map +1 -0
- package/dist/theme/divider.d.ts +6 -0
- package/dist/theme/divider.js +18 -0
- package/dist/theme/divider.js.map +1 -0
- package/dist/theme/token-names.d.ts +1389 -0
- package/dist/theme/tokens.d.ts +549 -0
- package/dist/theme/tokens.js +312 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/utils/host.d.ts +97 -0
- package/dist/utils/host.js +98 -0
- package/dist/utils/host.js.map +1 -0
- package/dist/utils/presence.d.ts +11 -0
- package/dist/utils/presence.js +34 -0
- package/dist/utils/presence.js.map +1 -0
- package/dist/utils/props.d.ts +38 -0
- package/dist/utils/props.js +115 -0
- package/dist/utils/props.js.map +1 -0
- package/dist/utils/scales.d.ts +48 -0
- package/package.json +106 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IntrinsicProps, JSX } from '@zerodep-dev/vue-tsx-pro-tsx/jsx-runtime';
|
|
2
|
+
import { type SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
3
|
+
import type { VNodeChild } from 'vue';
|
|
4
|
+
import '../theme/tokens';
|
|
5
|
+
/**
|
|
6
|
+
* 原生元素部件的属性:该元素的属性加上 sx,去掉组件管理的属性与 children(内容走组件自己的 prop)。
|
|
7
|
+
* 形如 `propsInput?: PartProps<'input', 'value' | 'aria-invalid'>`
|
|
8
|
+
*/
|
|
9
|
+
export type PartProps<Tag extends keyof JSX.IntrinsicElements, Managed extends string = never> = Omit<IntrinsicProps<Tag>, Managed | 'children'> & {
|
|
10
|
+
sx?: SxStyles;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* data-* 写进对象字面量(部件属性、合并的各层)时包一层:元素的属性类型不收 data-* 键。
|
|
14
|
+
* 值为 false 的去掉:Vue 会把它写成 data-x="false",样式里的 [data-x] 照样成立
|
|
15
|
+
*/
|
|
16
|
+
export declare function dataAttrs(attrs: Record<`data-${string}`, string | number | boolean | undefined>): Record<`data-${string}`, string | number | true>;
|
|
17
|
+
type Props = Record<string, unknown>;
|
|
18
|
+
/** 一层属性:Target 是标签名时为该元素的属性加 sx,是组件的 props 类型时就是它 */
|
|
19
|
+
type PropsLayer<Target> = Partial<[
|
|
20
|
+
Target
|
|
21
|
+
] extends [keyof JSX.IntrinsicElements] ? PartProps<Target> : Target>;
|
|
22
|
+
/**
|
|
23
|
+
* 合并部件的三层属性:`mergeProps<IconProps>({ sx: … }, propsIcon)`;原生元素用 mergeAttrs。
|
|
24
|
+
* 只有默认层时原样返回;只有两层以上都给了同名事件时才包一层回调(渲染路径上每个部件都要走这里)
|
|
25
|
+
*/
|
|
26
|
+
export declare function mergeProps<Target = Props>(defaults: PropsLayer<Target>, user?: PropsLayer<Target>, managed?: PropsLayer<Target>): PropsLayer<Target>;
|
|
27
|
+
/**
|
|
28
|
+
* 子组件部件的合并:默认层写齐子组件的必填 props,结果就是完整的 props 类型,不必断言:
|
|
29
|
+
* <Icon {...mergePartProps<IconProps>({ icon: X, sx: styles.icon }, propsIcon)} />
|
|
30
|
+
*/
|
|
31
|
+
export declare function mergePartProps<P extends object>(defaults: P, user?: Partial<P>, managed?: Partial<P>): P;
|
|
32
|
+
/** 原生元素部件的合并:合并后把 sx 换成 class 与 style,结果直接展开到元素上 */
|
|
33
|
+
export declare function mergeAttrs<Tag extends keyof JSX.IntrinsicElements>(defaults: PropsLayer<Tag>, user?: PropsLayer<Tag>, managed?: PropsLayer<Tag>): Omit<PropsLayer<Tag>, 'sx' | 'children'>;
|
|
34
|
+
/** 原生元素:把 sx 换成样式引擎生成的 class 与 style,与已有的 class、style 合并;去掉 children */
|
|
35
|
+
export declare function elementProps<P extends object>(props: P): Omit<P, 'sx' | 'children'>;
|
|
36
|
+
/** 内容有没有东西:null、undefined、空字符串与布尔都算没有(`footer={cond && …}` 不成立时是 false) */
|
|
37
|
+
export declare function hasContent(node: VNodeChild): boolean;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import "../theme/tokens.js";
|
|
2
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
3
|
+
import { mergeRefs } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
4
|
+
//#region src/utils/props.ts
|
|
5
|
+
/**
|
|
6
|
+
* 部件属性的类型与合并(MOBILE.md §2):组件给部件的属性分三层——可被覆盖的默认层、使用方传入的、组件状态决定的受管层。
|
|
7
|
+
* - sx:默认在前、使用方其次、受管最后,后者覆盖前者
|
|
8
|
+
* - class、style:依次排成数组交给 Vue
|
|
9
|
+
* - 事件 onXxx:使用方先执行,调用了 event.preventDefault() 就跳过组件自己的处理
|
|
10
|
+
* - ref:各方都拿到元素
|
|
11
|
+
* - 其他属性:受管 > 使用方 > 默认
|
|
12
|
+
* 规则与桌面组件库相同,实现独立:小程序里没有 Event 全局,取消与否看事件对象上的 defaultPrevented。
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* data-* 写进对象字面量(部件属性、合并的各层)时包一层:元素的属性类型不收 data-* 键。
|
|
16
|
+
* 值为 false 的去掉:Vue 会把它写成 data-x="false",样式里的 [data-x] 照样成立
|
|
17
|
+
*/
|
|
18
|
+
function dataAttrs(attrs) {
|
|
19
|
+
const result = {};
|
|
20
|
+
for (const [name, value] of Object.entries(attrs)) if (value !== false && value !== void 0) result[name] = value;
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 合并部件的三层属性:`mergeProps<IconProps>({ sx: … }, propsIcon)`;原生元素用 mergeAttrs。
|
|
25
|
+
* 只有默认层时原样返回;只有两层以上都给了同名事件时才包一层回调(渲染路径上每个部件都要走这里)
|
|
26
|
+
*/
|
|
27
|
+
function mergeProps(defaults, user, managed) {
|
|
28
|
+
const base = defaults;
|
|
29
|
+
const own = hasKeys(user) ? user : void 0;
|
|
30
|
+
const fixed = hasKeys(managed) ? managed : void 0;
|
|
31
|
+
if (!own && !fixed) return defaults;
|
|
32
|
+
const merged = {
|
|
33
|
+
...base,
|
|
34
|
+
...own,
|
|
35
|
+
...fixed
|
|
36
|
+
};
|
|
37
|
+
for (const key of LISTED_KEYS) {
|
|
38
|
+
const values = present(base[key], own?.[key], fixed?.[key]);
|
|
39
|
+
if (values) merged[key] = values;
|
|
40
|
+
}
|
|
41
|
+
const refs = present(base.ref, own?.ref, fixed?.ref);
|
|
42
|
+
if (refs && refs.length > 1) merged.ref = mergeRefs(refs);
|
|
43
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(own ?? {}), ...Object.keys(fixed ?? {})]);
|
|
44
|
+
for (const key of keys) {
|
|
45
|
+
if (!isHandlerKey(key)) continue;
|
|
46
|
+
merged[key] = mergeHandlers(own?.[key], [base[key], fixed?.[key]]) ?? own?.[key] ?? fixed?.[key] ?? base[key];
|
|
47
|
+
}
|
|
48
|
+
return merged;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 子组件部件的合并:默认层写齐子组件的必填 props,结果就是完整的 props 类型,不必断言:
|
|
52
|
+
* <Icon {...mergePartProps<IconProps>({ icon: X, sx: styles.icon }, propsIcon)} />
|
|
53
|
+
*/
|
|
54
|
+
function mergePartProps(defaults, user, managed) {
|
|
55
|
+
return mergeProps(defaults, user, managed);
|
|
56
|
+
}
|
|
57
|
+
/** 原生元素部件的合并:合并后把 sx 换成 class 与 style,结果直接展开到元素上 */
|
|
58
|
+
function mergeAttrs(defaults, user, managed) {
|
|
59
|
+
return elementProps(mergeProps(defaults, user, managed));
|
|
60
|
+
}
|
|
61
|
+
/** 原生元素:把 sx 换成样式引擎生成的 class 与 style,与已有的 class、style 合并;去掉 children */
|
|
62
|
+
function elementProps(props) {
|
|
63
|
+
const { sx, children: _children, ...rest } = props;
|
|
64
|
+
if (sx == null) return rest;
|
|
65
|
+
const compiled = compileSx(sx);
|
|
66
|
+
const element = rest;
|
|
67
|
+
if (compiled.ref) element.ref = element.ref != null ? mergeRefs([element.ref, compiled.ref]) : compiled.ref;
|
|
68
|
+
element.class = present(rest.class, compiled.class) ?? [];
|
|
69
|
+
element.style = present(compiled.style, rest.style) ?? [];
|
|
70
|
+
return rest;
|
|
71
|
+
}
|
|
72
|
+
/** 单个样式对象是不变的常量:按对象缓存 css.attrs 的结果 */
|
|
73
|
+
var compiledCache = /* @__PURE__ */ new WeakMap();
|
|
74
|
+
function compileSx(sx) {
|
|
75
|
+
if (Array.isArray(sx) || typeof sx !== "object" || sx === null) return css.attrs(sx);
|
|
76
|
+
let compiled = compiledCache.get(sx);
|
|
77
|
+
if (!compiled) compiledCache.set(sx, compiled = css.attrs(sx));
|
|
78
|
+
return compiled;
|
|
79
|
+
}
|
|
80
|
+
/** onClick、onUpdate:_value:on 后面跟大写字母 */
|
|
81
|
+
var isHandlerKey = (key) => /^on[A-Z]/.test(key);
|
|
82
|
+
function hasKeys(layer) {
|
|
83
|
+
if (!layer) return false;
|
|
84
|
+
for (const _ in layer) return true;
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
/** 使用方的回调先执行,调用了 preventDefault 就跳过组件的;只有一方提供回调时返回 undefined */
|
|
88
|
+
function mergeHandlers(user, internal) {
|
|
89
|
+
const own = internal.filter((handler) => typeof handler === "function");
|
|
90
|
+
if (own.length + (user ? 1 : 0) < 2) return void 0;
|
|
91
|
+
return (...args) => {
|
|
92
|
+
user?.(...args);
|
|
93
|
+
if (args[0]?.defaultPrevented) return;
|
|
94
|
+
for (const handler of own) handler(...args);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** 按层排列、要合并成数组的属性 */
|
|
98
|
+
var LISTED_KEYS = [
|
|
99
|
+
"sx",
|
|
100
|
+
"class",
|
|
101
|
+
"style"
|
|
102
|
+
];
|
|
103
|
+
/** 几个值里不为空的那些,按原顺序成数组;都为空时 undefined */
|
|
104
|
+
function present(...values) {
|
|
105
|
+
const list = values.filter((value) => value != null);
|
|
106
|
+
return list.length ? list : void 0;
|
|
107
|
+
}
|
|
108
|
+
/** 内容有没有东西:null、undefined、空字符串与布尔都算没有(`footer={cond && …}` 不成立时是 false) */
|
|
109
|
+
function hasContent(node) {
|
|
110
|
+
return node != null && typeof node !== "boolean" && node !== "";
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { dataAttrs, elementProps, hasContent, mergeAttrs, mergePartProps, mergeProps };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props.js","names":[],"sources":["../../src/utils/props.ts"],"sourcesContent":["/**\n * 部件属性的类型与合并(MOBILE.md §2):组件给部件的属性分三层——可被覆盖的默认层、使用方传入的、组件状态决定的受管层。\n * - sx:默认在前、使用方其次、受管最后,后者覆盖前者\n * - class、style:依次排成数组交给 Vue\n * - 事件 onXxx:使用方先执行,调用了 event.preventDefault() 就跳过组件自己的处理\n * - ref:各方都拿到元素\n * - 其他属性:受管 > 使用方 > 默认\n * 规则与桌面组件库相同,实现独立:小程序里没有 Event 全局,取消与否看事件对象上的 defaultPrevented。\n */\nimport { mergeRefs, type RefSetter } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport type { IntrinsicProps, JSX } from '@zerodep-dev/vue-tsx-pro-tsx/jsx-runtime';\nimport { css, type SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\n// 登记主题 tokens(样式里的 '_md' 靠它):每个组件都经过这里合并属性,渲染之前一定登记过\nimport '../theme/tokens';\n\n/**\n * 原生元素部件的属性:该元素的属性加上 sx,去掉组件管理的属性与 children(内容走组件自己的 prop)。\n * 形如 `propsInput?: PartProps<'input', 'value' | 'aria-invalid'>`\n */\nexport type PartProps<\n Tag extends keyof JSX.IntrinsicElements,\n Managed extends string = never,\n> = Omit<IntrinsicProps<Tag>, Managed | 'children'> & { sx?: SxStyles };\n\n/**\n * data-* 写进对象字面量(部件属性、合并的各层)时包一层:元素的属性类型不收 data-* 键。\n * 值为 false 的去掉:Vue 会把它写成 data-x=\"false\",样式里的 [data-x] 照样成立\n */\nexport function dataAttrs(\n attrs: Record<`data-${string}`, string | number | boolean | undefined>,\n): Record<`data-${string}`, string | number | true> {\n const result: Record<`data-${string}`, string | number | true> = {};\n for (const [name, value] of Object.entries(attrs) as [`data-${string}`, unknown][])\n if (value !== false && value !== undefined) result[name] = value as string | number | true;\n return result;\n}\n\ntype Props = Record<string, unknown>;\ntype Handler = (...args: unknown[]) => unknown;\n\n/** 一层属性:Target 是标签名时为该元素的属性加 sx,是组件的 props 类型时就是它 */\ntype PropsLayer<Target> = Partial<\n [Target] extends [keyof JSX.IntrinsicElements] ? PartProps<Target> : Target\n>;\n\n/**\n * 合并部件的三层属性:`mergeProps<IconProps>({ sx: … }, propsIcon)`;原生元素用 mergeAttrs。\n * 只有默认层时原样返回;只有两层以上都给了同名事件时才包一层回调(渲染路径上每个部件都要走这里)\n */\nexport function mergeProps<Target = Props>(\n defaults: PropsLayer<Target>,\n user?: PropsLayer<Target>,\n managed?: PropsLayer<Target>,\n): PropsLayer<Target> {\n const base = defaults as Props;\n const own = hasKeys(user) ? (user as Props) : undefined;\n const fixed = hasKeys(managed) ? (managed as Props) : undefined;\n if (!own && !fixed) return defaults;\n const merged: Props = { ...base, ...own, ...fixed };\n\n for (const key of LISTED_KEYS) {\n const values = present(base[key], own?.[key], fixed?.[key]);\n if (values) merged[key] = values;\n }\n const refs = present(base.ref, own?.ref, fixed?.ref) as RefSetter[] | undefined;\n if (refs && refs.length > 1) merged.ref = mergeRefs(refs);\n\n // 同名事件:使用方的先执行;使用方传 undefined(onClick={cond ? fn : undefined})不盖掉组件自己的\n const keys = new Set([...Object.keys(own ?? {}), ...Object.keys(fixed ?? {})]);\n for (const key of keys) {\n if (!isHandlerKey(key)) continue;\n const handler = mergeHandlers(own?.[key] as Handler | undefined, [base[key], fixed?.[key]]);\n merged[key] = handler ?? own?.[key] ?? fixed?.[key] ?? base[key];\n }\n return merged as PropsLayer<Target>;\n}\n\n/**\n * 子组件部件的合并:默认层写齐子组件的必填 props,结果就是完整的 props 类型,不必断言:\n * <Icon {...mergePartProps<IconProps>({ icon: X, sx: styles.icon }, propsIcon)} />\n */\nexport function mergePartProps<P extends object>(\n defaults: P,\n user?: Partial<P>,\n managed?: Partial<P>,\n): P {\n return mergeProps(\n defaults as Props,\n user as Props | undefined,\n managed as Props | undefined,\n ) as P;\n}\n\n/** 原生元素部件的合并:合并后把 sx 换成 class 与 style,结果直接展开到元素上 */\nexport function mergeAttrs<Tag extends keyof JSX.IntrinsicElements>(\n defaults: PropsLayer<Tag>,\n user?: PropsLayer<Tag>,\n managed?: PropsLayer<Tag>,\n): Omit<PropsLayer<Tag>, 'sx' | 'children'> {\n return elementProps(mergeProps<Tag>(defaults, user, managed));\n}\n\n/** 原生元素:把 sx 换成样式引擎生成的 class 与 style,与已有的 class、style 合并;去掉 children */\nexport function elementProps<P extends object>(props: P): Omit<P, 'sx' | 'children'> {\n // 解构出的 rest 是新对象,之后直接往上写\n const { sx, children: _children, ...rest } = props as P & Props;\n if (sx == null) return rest as Omit<P, 'sx' | 'children'>;\n const compiled = compileSx(sx as SxStyles);\n const element = rest as Props;\n // 响应式绑定的 ref(元素挂上后改变量)与使用方的 ref 都要拿到元素\n if (compiled.ref)\n element.ref =\n element.ref != null ? mergeRefs([element.ref as RefSetter, compiled.ref]) : compiled.ref;\n element.class = present(rest.class, compiled.class) ?? [];\n element.style = present(compiled.style, rest.style) ?? [];\n return rest as Omit<P, 'sx' | 'children'>;\n}\n\n/** 单个样式对象是不变的常量:按对象缓存 css.attrs 的结果 */\nconst compiledCache = new WeakMap<object, ReturnType<typeof css.attrs>>();\nfunction compileSx(sx: SxStyles) {\n if (Array.isArray(sx) || typeof sx !== 'object' || sx === null) return css.attrs(sx);\n let compiled = compiledCache.get(sx);\n if (!compiled) compiledCache.set(sx, (compiled = css.attrs(sx)));\n return compiled;\n}\n\n/** onClick、onUpdate:_value:on 后面跟大写字母 */\nconst isHandlerKey = (key: string) => /^on[A-Z]/.test(key);\n\nfunction hasKeys(layer: object | undefined): boolean {\n if (!layer) return false;\n for (const _ in layer) return true;\n return false;\n}\n\n/** 使用方的回调先执行,调用了 preventDefault 就跳过组件的;只有一方提供回调时返回 undefined */\nfunction mergeHandlers(user: Handler | undefined, internal: unknown[]): Handler | undefined {\n const own = internal.filter((handler): handler is Handler => typeof handler === 'function');\n if (own.length + (user ? 1 : 0) < 2) return undefined;\n return (...args) => {\n user?.(...args);\n if ((args[0] as { defaultPrevented?: boolean } | undefined)?.defaultPrevented) return;\n for (const handler of own) handler(...args);\n };\n}\n\n/** 按层排列、要合并成数组的属性 */\nconst LISTED_KEYS = ['sx', 'class', 'style'] as const;\n\n/** 几个值里不为空的那些,按原顺序成数组;都为空时 undefined */\nfunction present(...values: unknown[]): unknown[] | undefined {\n const list = values.filter((value) => value != null);\n return list.length ? list : undefined;\n}\n\n/** 内容有没有东西:null、undefined、空字符串与布尔都算没有(`footer={cond && …}` 不成立时是 false) */\nexport function hasContent(node: VNodeChild): boolean {\n return node != null && typeof node !== 'boolean' && node !== '';\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 组件共用的档位:色调、尺寸、圆角。取值写成带注释的接口,`keyof` 出来的联合在补全与悬停里能看到每个取值的意思。
|
|
3
|
+
*/
|
|
4
|
+
/** 色调 */
|
|
5
|
+
export interface MobileTones {
|
|
6
|
+
/** 品牌色:主要操作、选中 */
|
|
7
|
+
accent: unknown;
|
|
8
|
+
/** 中性:次要操作、普通标签 */
|
|
9
|
+
neutral: unknown;
|
|
10
|
+
/** 危险:删除、错误 */
|
|
11
|
+
danger: unknown;
|
|
12
|
+
/** 成功 */
|
|
13
|
+
success: unknown;
|
|
14
|
+
/** 警告 */
|
|
15
|
+
warning: unknown;
|
|
16
|
+
/** 信息 */
|
|
17
|
+
info: unknown;
|
|
18
|
+
}
|
|
19
|
+
/** 色调 */
|
|
20
|
+
export type MobileTone = keyof MobileTones;
|
|
21
|
+
/** 控件的尺寸档位 */
|
|
22
|
+
export interface MobileSizes {
|
|
23
|
+
/** 极小:行内的小按钮、标签(24px 高) */
|
|
24
|
+
xs: unknown;
|
|
25
|
+
/** 小:卡片里的按钮(32px 高) */
|
|
26
|
+
sm: unknown;
|
|
27
|
+
/** 中:页面里的常规控件(44px 高,触控目标的推荐尺寸) */
|
|
28
|
+
md: unknown;
|
|
29
|
+
/** 大:页面底部的主操作(50px 高) */
|
|
30
|
+
lg: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** 控件的尺寸档位 */
|
|
33
|
+
export type MobileSize = keyof MobileSizes;
|
|
34
|
+
/** 圆角 */
|
|
35
|
+
export interface MobileRadii {
|
|
36
|
+
/** 直角 */
|
|
37
|
+
none: unknown;
|
|
38
|
+
/** 小圆角 */
|
|
39
|
+
sm: unknown;
|
|
40
|
+
/** 常规圆角 */
|
|
41
|
+
md: unknown;
|
|
42
|
+
/** 大圆角 */
|
|
43
|
+
lg: unknown;
|
|
44
|
+
/** 全圆:胶囊、圆形 */
|
|
45
|
+
full: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** 圆角 */
|
|
48
|
+
export type MobileRadius = keyof MobileRadii;
|
package/package.json
CHANGED
|
@@ -1,6 +1,109 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zerodep-dev/vue-tsx-pro-mobile",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "vue-tsx-pro 移动端组件库:H5 为主,同一套组件经 @zerodep-dev/vue-tsx-pro-mini 跑在微信、支付宝小程序",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/kenconnet666/vue-tsx-pro.git",
|
|
13
|
+
"directory": "packages/mobile"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"vue",
|
|
17
|
+
"vue3",
|
|
18
|
+
"mobile",
|
|
19
|
+
"components",
|
|
20
|
+
"miniprogram",
|
|
21
|
+
"tsx"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": [
|
|
24
|
+
"./src/theme/tokens.ts",
|
|
25
|
+
"./dist/theme/tokens.js"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"@vue-tsx-pro/source": "./src/index.ts",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./area": {
|
|
34
|
+
"@vue-tsx-pro/source": "./src/area/index.ts",
|
|
35
|
+
"types": "./dist/area/index.d.ts",
|
|
36
|
+
"default": "./dist/area/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./capacitor": {
|
|
39
|
+
"@vue-tsx-pro/source": "./src/capacitor/index.ts",
|
|
40
|
+
"types": "./dist/capacitor/index.d.ts",
|
|
41
|
+
"default": "./dist/capacitor/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./package.json": "./package.json"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@zerodep-dev/vue-tsx-pro-tsx": "^0.4.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@capacitor/app": "^8.0.0",
|
|
50
|
+
"@capacitor/camera": "^8.0.0",
|
|
51
|
+
"@capacitor/clipboard": "^8.0.0",
|
|
52
|
+
"@capacitor/core": "^8.0.0",
|
|
53
|
+
"@capacitor/geolocation": "^8.0.0",
|
|
54
|
+
"@capacitor/haptics": "^8.0.0",
|
|
55
|
+
"@capacitor/keyboard": "^8.0.0",
|
|
56
|
+
"@capacitor/preferences": "^8.0.0",
|
|
57
|
+
"@lucide/icons": "^1.59.0",
|
|
58
|
+
"vue": "^3.5.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"@capacitor/app": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@capacitor/camera": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"@capacitor/clipboard": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@capacitor/core": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@capacitor/geolocation": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@capacitor/haptics": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@capacitor/keyboard": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@capacitor/preferences": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@capacitor/app": "8.1.2",
|
|
88
|
+
"@capacitor/camera": "8.2.6",
|
|
89
|
+
"@capacitor/clipboard": "8.0.1",
|
|
90
|
+
"@capacitor/core": "8.5.3",
|
|
91
|
+
"@capacitor/geolocation": "8.2.4",
|
|
92
|
+
"@capacitor/haptics": "8.0.2",
|
|
93
|
+
"@capacitor/keyboard": "8.0.6",
|
|
94
|
+
"@capacitor/preferences": "8.0.1",
|
|
95
|
+
"@lucide/icons": "1.59.0",
|
|
96
|
+
"@types/node": "24.19.2",
|
|
97
|
+
"@zerodep-dev/vue-tsx-pro-mini": "^0.4.0",
|
|
98
|
+
"happy-dom": "21.0.3",
|
|
99
|
+
"typescript": "7.1.0-beta",
|
|
100
|
+
"vite": "8.3.4",
|
|
101
|
+
"vitest": "5.0.5",
|
|
102
|
+
"vue": "3.5.44"
|
|
103
|
+
},
|
|
104
|
+
"scripts": {
|
|
105
|
+
"build": "vite build --configLoader native && tsc -p tsconfig.build.json",
|
|
106
|
+
"typecheck": "tsc -p . --incremental --tsBuildInfoFile node_modules/.cache/typecheck.tsbuildinfo",
|
|
107
|
+
"test": "vitest run --configLoader native"
|
|
108
|
+
}
|
|
6
109
|
}
|