@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 @@
|
|
|
1
|
+
{"version":3,"file":"Collapse.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/display/Collapse.tsx"],"sourcesContent":["/**\n * 折叠面板:一组可展开、收起的段落(常见问题、订单详情的分组);手风琴模式下同时只展开一个。\n *\n * <Collapse _value={open}>\n * <CollapseItem name=\"ship\" title=\"多久发货?\">付款后 48 小时内发货。</CollapseItem>\n * <CollapseItem name=\"refund\" title=\"怎么退款?\">…</CollapseItem>\n * </Collapse>\n * <Collapse _value={current} accordion>…</Collapse>\n *\n * 展开收起的高度动画用网格行(0fr ↔ 1fr),不用量内容的高度,小程序里也一样。\n */\nimport { ChevronDown } from '@lucide/icons';\nimport { _component, createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Icon } from '../base/Icon';\nimport { dividerImage, dividerLayout } from '../theme/divider';\nimport { dataAttrs, hasContent, mergeAttrs, type PartProps } from '../utils/props';\n\n/** 面板提供给各项的 */\ninterface CollapseState {\n isOpen(name: string): boolean;\n toggle(name: string): void;\n}\n\nconst CollapseContext = createContext<CollapseState>('Collapse');\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface CollapseProps extends Omit<PartProps<'div'>, 'onChange'> {\n /** 展开的项;双向绑定写 `_value={x}`。手风琴模式下是一个名字(或 null),否则是名字的数组 */\n _value?: string[] | string | null;\n /** 手风琴:同时只展开一个 */\n accordion?: boolean;\n /** 展开的项变了 */\n onChange?: (value: string[] | string | null) => void;\n /** 各个 CollapseItem */\n children?: VNodeChild;\n}\n\n/** Collapse 的样式:root、header、title、arrow、panel、content */\nexport const collapseStyles = css.create({\n root: { backgroundColor: '_surface' },\n item: {\n // 项之间的细线(同 Cell),最后一项不画\n backgroundImage: {\n default: dividerImage,\n ':last-child': 'none',\n },\n ...dividerLayout,\n },\n header: {\n boxSizing: 'border-box',\n display: 'flex',\n alignItems: 'center',\n gap: '_md',\n width: '100%',\n minHeight: '_control',\n margin: 0,\n paddingBlock: '0.7em',\n paddingInline: '_lg',\n borderWidth: 0,\n backgroundColor: { default: 'transparent', ':active:not([disabled])': '_fillActive' },\n color: { default: '_text', '[disabled]': '_textDisabled' },\n fontFamily: 'inherit',\n fontSize: '_md',\n lineHeight: '1.5',\n textAlign: 'start',\n cursor: { default: 'pointer', '[disabled]': 'not-allowed' },\n },\n title: { flex: '1 1 auto', minWidth: 0, overflowWrap: 'anywhere' },\n value: { flex: 'none', color: '_textMuted' },\n arrow: {\n flex: 'none',\n color: '_textPlaceholder',\n transform: { default: 'none', '[data-open]': 'rotate(180deg)' },\n transitionProperty: 'transform',\n transitionDuration: '_md',\n },\n panel: {\n display: 'grid',\n gridTemplateRows: { default: '0fr', '[data-open]': '1fr' },\n transitionProperty: 'grid-template-rows',\n transitionDuration: '_md',\n transitionTimingFunction: '_standard',\n },\n clip: { overflow: 'hidden', minHeight: 0 },\n content: {\n paddingBlock: '0.25em 1em',\n paddingInline: '_lg',\n fontSize: '_sm',\n lineHeight: '1.6',\n color: '_textMuted',\n },\n});\n\n/** 折叠面板(div > 各项) */\nexport const Collapse = _component(\n ({\n _value: value = _bindable<string[] | string | null>([]),\n accordion = false,\n onChange,\n children,\n ...rest\n }: CollapseProps) => {\n CollapseContext.provide({\n isOpen: (name) => (Array.isArray(value) ? value.includes(name) : value === name),\n toggle(name) {\n if (accordion) value = value === name ? null : name;\n else {\n const list = Array.isArray(value) ? value : [];\n value = list.includes(name) ? list.filter((item) => item !== name) : [...list, name];\n }\n onChange?.(value);\n },\n });\n return () => <div {...mergeAttrs<'div'>({ sx: collapseStyles.root }, rest)}>{children}</div>;\n },\n);\n\n/** 未声明的属性落到这一项的根元素(div)上 */\nexport interface CollapseItemProps extends PartProps<'div', 'title'> {\n /** 名字:展开的状态按它记 */\n name: string;\n /** 标题 */\n title: VNodeChild;\n /** 标题右边的值 */\n value?: VNodeChild;\n /** 不能展开 */\n disabled?: boolean;\n /** 展开的内容 */\n children?: VNodeChild;\n /** 标题栏(button)的部件属性 */\n propsHeader?: PartProps<'button'>;\n /** 内容的部件属性 */\n propsContent?: PartProps<'div'>;\n}\n\n/** 折叠面板的一项(div > 标题栏 button[aria-expanded] + 内容) */\nexport const CollapseItem = _component(\n ({\n name,\n title,\n value,\n disabled = false,\n children,\n propsHeader,\n propsContent,\n ...rest\n }: CollapseItemProps) => {\n const collapse = CollapseContext.inject();\n return () => {\n const open = collapse.isOpen(name);\n const state = dataAttrs({ 'data-open': open });\n return (\n <div {...mergeAttrs<'div'>({ sx: collapseStyles.item }, rest, state)}>\n <button\n {...mergeAttrs<'button'>({ sx: collapseStyles.header }, propsHeader, {\n type: 'button',\n disabled,\n 'aria-expanded': open ? 'true' : 'false',\n onClick: () => collapse.toggle(name),\n })}\n >\n <span {...mergeAttrs<'span'>({ sx: collapseStyles.title })}>{title}</span>\n {hasContent(value) && (\n <span {...mergeAttrs<'span'>({ sx: collapseStyles.value })}>{value}</span>\n )}\n <Icon icon={ChevronDown} sx={collapseStyles.arrow} {...state} />\n </button>\n <div {...mergeAttrs<'div'>({ sx: collapseStyles.panel }, state)}>\n <div {...mergeAttrs<'div'>({ sx: collapseStyles.clip })}>\n <div {...mergeAttrs<'div'>({ sx: collapseStyles.content }, propsContent)}>\n {children}\n </div>\n </div>\n </div>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
|
+
import type { VNodeChild } from 'vue';
|
|
3
|
+
import { type IconData, type IconProps } from '../base/Icon';
|
|
4
|
+
import { type PartProps } from '../utils/props';
|
|
5
|
+
/** 预设的图标 */
|
|
6
|
+
export interface EmptyPresets {
|
|
7
|
+
/** 没有数据(默认) */
|
|
8
|
+
default: unknown;
|
|
9
|
+
/** 没有搜索结果 */
|
|
10
|
+
search: unknown;
|
|
11
|
+
/** 网络不通 */
|
|
12
|
+
network: unknown;
|
|
13
|
+
/** 出错了 */
|
|
14
|
+
error: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** 未声明的属性落到根元素(div)上 */
|
|
17
|
+
export interface EmptyProps extends PartProps<'div'> {
|
|
18
|
+
/**
|
|
19
|
+
* 预设的图标
|
|
20
|
+
* @default 'default'
|
|
21
|
+
*/
|
|
22
|
+
preset?: keyof EmptyPresets;
|
|
23
|
+
/** 自己的图标(代替预设的) */
|
|
24
|
+
icon?: IconData;
|
|
25
|
+
/** 说明;不给时用语言包的“暂无数据” */
|
|
26
|
+
description?: VNodeChild;
|
|
27
|
+
/** 下面的操作(按钮) */
|
|
28
|
+
children?: VNodeChild;
|
|
29
|
+
/** 图标的部件属性 */
|
|
30
|
+
propsIcon?: Partial<IconProps>;
|
|
31
|
+
/** 说明的部件属性 */
|
|
32
|
+
propsDescription?: PartProps<'div'>;
|
|
33
|
+
}
|
|
34
|
+
/** Empty 的样式:root、icon、description、actions */
|
|
35
|
+
export declare const emptyStyles: Readonly<{
|
|
36
|
+
actions: css.CompiledStyles;
|
|
37
|
+
description: css.CompiledStyles;
|
|
38
|
+
icon: css.CompiledStyles;
|
|
39
|
+
root: css.CompiledStyles;
|
|
40
|
+
}>;
|
|
41
|
+
/** 空状态(div > 图标 + 说明 + 操作) */
|
|
42
|
+
export declare const Empty: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<EmptyProps>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useConfig } from "../config/context.js";
|
|
2
|
+
import { hasContent, mergeAttrs, mergePartProps } 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, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
6
|
+
import { createVNode } from "vue";
|
|
7
|
+
import { CircleAlert, Inbox, SearchX, WifiOff } from "@lucide/icons";
|
|
8
|
+
//#region src/display/Empty.tsx
|
|
9
|
+
/**
|
|
10
|
+
* 空状态:列表没有数据、搜索没有结果、网络出错时,在内容区中间放一个大图标、一句说明,下面可放操作按钮。
|
|
11
|
+
*
|
|
12
|
+
* <Empty /> 暂无数据
|
|
13
|
+
* <Empty preset="search" description="没有找到相关商品" />
|
|
14
|
+
* <Empty preset="network"><Button size="sm" onClick={retry}>重新加载</Button></Empty>
|
|
15
|
+
*/
|
|
16
|
+
/** 预设的图标 */
|
|
17
|
+
/** 未声明的属性落到根元素(div)上 */
|
|
18
|
+
/** Empty 的样式:root、icon、description、actions */
|
|
19
|
+
var emptyStyles = css.create({
|
|
20
|
+
root: {
|
|
21
|
+
display: "flex",
|
|
22
|
+
flexDirection: "column",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
justifyContent: "center",
|
|
25
|
+
gap: "_md",
|
|
26
|
+
paddingBlock: "2.5em",
|
|
27
|
+
paddingInline: "_xl",
|
|
28
|
+
textAlign: "center"
|
|
29
|
+
},
|
|
30
|
+
icon: {
|
|
31
|
+
fontSize: "4em",
|
|
32
|
+
color: "_border"
|
|
33
|
+
},
|
|
34
|
+
description: {
|
|
35
|
+
fontSize: "_sm",
|
|
36
|
+
lineHeight: "1.5",
|
|
37
|
+
color: "_textMuted"
|
|
38
|
+
},
|
|
39
|
+
actions: { marginBlockStart: "_sm" }
|
|
40
|
+
});
|
|
41
|
+
var PRESETS = {
|
|
42
|
+
default: Inbox,
|
|
43
|
+
search: SearchX,
|
|
44
|
+
network: WifiOff,
|
|
45
|
+
error: CircleAlert
|
|
46
|
+
};
|
|
47
|
+
/** 空状态(div > 图标 + 说明 + 操作) */
|
|
48
|
+
var Empty = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
49
|
+
const preset = readonlyProp(_props, "preset", "default");
|
|
50
|
+
const icon = readonlyProp(_props, "icon");
|
|
51
|
+
const description = readonlyProp(_props, "description");
|
|
52
|
+
const children = childrenProp(_props);
|
|
53
|
+
const propsIcon = readonlyProp(_props, "propsIcon");
|
|
54
|
+
const propsDescription = readonlyProp(_props, "propsDescription");
|
|
55
|
+
const rest = restProps(_props, _ctx, false);
|
|
56
|
+
const config = useConfig();
|
|
57
|
+
return () => createVNode("div", mergeAttrs({ sx: emptyStyles.root }, rest), [
|
|
58
|
+
createVNode(Icon, mergePartProps({
|
|
59
|
+
icon: icon.value ?? PRESETS[preset.value],
|
|
60
|
+
strokeWidth: 1.25,
|
|
61
|
+
sx: emptyStyles.icon
|
|
62
|
+
}, propsIcon.value), null),
|
|
63
|
+
createVNode("div", mergeAttrs({ sx: emptyStyles.description }, propsDescription.value), [description.value ?? config.lang.empty]),
|
|
64
|
+
hasContent(children.value) && createVNode("div", mergeAttrs({ sx: emptyStyles.actions }), [children.value])
|
|
65
|
+
]);
|
|
66
|
+
}, {
|
|
67
|
+
name: "Empty",
|
|
68
|
+
props: [
|
|
69
|
+
"preset",
|
|
70
|
+
"icon",
|
|
71
|
+
"description",
|
|
72
|
+
"propsIcon",
|
|
73
|
+
"propsDescription"
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
//#endregion
|
|
77
|
+
export { Empty, emptyStyles };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=Empty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Empty.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/display/Empty.tsx"],"sourcesContent":["/**\n * 空状态:列表没有数据、搜索没有结果、网络出错时,在内容区中间放一个大图标、一句说明,下面可放操作按钮。\n *\n * <Empty /> 暂无数据\n * <Empty preset=\"search\" description=\"没有找到相关商品\" />\n * <Empty preset=\"network\"><Button size=\"sm\" onClick={retry}>重新加载</Button></Empty>\n */\nimport { CircleAlert, Inbox, SearchX, WifiOff } 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, type IconData, type IconProps } from '../base/Icon';\nimport { useConfig } from '../config/context';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\n\n/** 预设的图标 */\nexport interface EmptyPresets {\n /** 没有数据(默认) */\n default: unknown;\n /** 没有搜索结果 */\n search: unknown;\n /** 网络不通 */\n network: unknown;\n /** 出错了 */\n error: unknown;\n}\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface EmptyProps extends PartProps<'div'> {\n /**\n * 预设的图标\n * @default 'default'\n */\n preset?: keyof EmptyPresets;\n /** 自己的图标(代替预设的) */\n icon?: IconData;\n /** 说明;不给时用语言包的“暂无数据” */\n description?: VNodeChild;\n /** 下面的操作(按钮) */\n children?: VNodeChild;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 说明的部件属性 */\n propsDescription?: PartProps<'div'>;\n}\n\n/** Empty 的样式:root、icon、description、actions */\nexport const emptyStyles = css.create({\n root: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_md',\n paddingBlock: '2.5em',\n paddingInline: '_xl',\n textAlign: 'center',\n },\n icon: { fontSize: '4em', color: '_border' },\n description: { fontSize: '_sm', lineHeight: '1.5', color: '_textMuted' },\n actions: { marginBlockStart: '_sm' },\n});\n\nconst PRESETS = { default: Inbox, search: SearchX, network: WifiOff, error: CircleAlert } as const;\n\n/** 空状态(div > 图标 + 说明 + 操作) */\nexport const Empty = _component(\n ({\n preset = 'default',\n icon,\n description,\n children,\n propsIcon,\n propsDescription,\n ...rest\n }: EmptyProps) => {\n const config = useConfig();\n return () => (\n <div {...mergeAttrs<'div'>({ sx: emptyStyles.root }, rest)}>\n <Icon\n {...mergePartProps<IconProps>(\n { icon: icon ?? PRESETS[preset], strokeWidth: 1.25, sx: emptyStyles.icon },\n propsIcon,\n )}\n />\n <div {...mergeAttrs<'div'>({ sx: emptyStyles.description }, propsDescription)}>\n {description ?? config.lang.empty}\n </div>\n {hasContent(children) && (\n <div {...mergeAttrs<'div'>({ sx: emptyStyles.actions })}>{children}</div>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+CA,IAAa,cAAc,IAAI,OAAO;CACpC,MAAM;EACJ,SAAS;EACT,eAAe;EACf,YAAY;EACZ,gBAAgB;EAChB,KAAK;EACL,cAAc;EACd,eAAe;EACf,WAAW;CACb;CACA,MAAM;EAAE,UAAU;EAAO,OAAO;CAAU;CAC1C,aAAa;EAAE,UAAU;EAAO,YAAY;EAAO,OAAO;CAAa;CACvE,SAAS,EAAE,kBAAkB,MAAM;AACrC,CAAC;AAED,IAAM,UAAU;CAAE,SAAS;CAAO,QAAQ;CAAS,SAAS;CAAS,OAAO;AAAY;;AAGxF,IAAa,QAAQ,0BACnB,QAAA,SAQkB;CAAA,MAAA,SAAAA,aAAA,QAAA,UAPP,SAAS;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAA,YAAAD,aAAA,QAAA,WAAA;CAAA,MAAA,mBAAAA,aAAA,QAAA,kBAAA;CAAA,MAMf,OAAIE,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,SAAS,UAAU;CACzB,aAAOC,YAAA,OACI,WAAkB,EAAE,IAAI,YAAY,KAAK,GAAG,IAAI,GAAC;EAAAA,YAAA,MAElD,eACF;GAAE,MAAM,KAAA,SAAQ,QAAO,OAAA;GAAU,aAAa;GAAM,IAAI,YAAY;EAAK,GAAC,UAAA,KAE5E,GAAC,IAAA;EAAAA,YAAA,OAEM,WAAkB,EAAE,IAAI,YAAY,YAAY,GAAC,iBAAA,KAAkB,GAAC,CAC1E,YAAA,SAAe,OAAO,KAAK,KAAK,CAAA;EAElC,WAAU,SAAA,KAAS,KAACA,YAAA,OACV,WAAkB,EAAE,IAAI,YAAY,QAAQ,CAAC,GAAC,CAAA,SAAA,KAAA,CAAA;CACxD,CAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
|
+
import type { VNodeChild } from 'vue';
|
|
3
|
+
import { type IconData, type IconProps } from '../base/Icon';
|
|
4
|
+
import { type PartProps } from '../utils/props';
|
|
5
|
+
/** 未声明的属性落到根元素(div)上 */
|
|
6
|
+
export interface GridProps extends PartProps<'div'> {
|
|
7
|
+
/**
|
|
8
|
+
* 一排几个
|
|
9
|
+
* @default 4
|
|
10
|
+
*/
|
|
11
|
+
columns?: number;
|
|
12
|
+
/** 每格是正方形 */
|
|
13
|
+
square?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 格子之间画细线
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
border?: boolean;
|
|
19
|
+
/** 各个 GridItem */
|
|
20
|
+
children?: VNodeChild;
|
|
21
|
+
}
|
|
22
|
+
/** Grid、GridItem 的样式:root、bordered、item、itemBorder、square、clickable、icon、text */
|
|
23
|
+
export declare const gridStyles: Readonly<{
|
|
24
|
+
bordered: css.CompiledStyles;
|
|
25
|
+
clickable: css.CompiledStyles;
|
|
26
|
+
icon: css.CompiledStyles;
|
|
27
|
+
item: css.CompiledStyles;
|
|
28
|
+
itemBorder: css.CompiledStyles;
|
|
29
|
+
root: css.CompiledStyles;
|
|
30
|
+
square: css.CompiledStyles;
|
|
31
|
+
text: css.CompiledStyles;
|
|
32
|
+
}>;
|
|
33
|
+
/** 宫格(div > 各格) */
|
|
34
|
+
export declare const Grid: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<GridProps>;
|
|
35
|
+
/** 未声明的属性落到格子(div)上 */
|
|
36
|
+
export interface GridItemProps extends PartProps<'div', 'role'> {
|
|
37
|
+
/** 图标 */
|
|
38
|
+
icon?: IconData;
|
|
39
|
+
/** 文字 */
|
|
40
|
+
text?: VNodeChild;
|
|
41
|
+
/** 图标右上角的徽标:数字、文字,true 是小红点 */
|
|
42
|
+
badge?: number | string | boolean;
|
|
43
|
+
/** 自定义内容(代替图标与文字) */
|
|
44
|
+
children?: VNodeChild;
|
|
45
|
+
/** 图标的部件属性 */
|
|
46
|
+
propsIcon?: Partial<IconProps>;
|
|
47
|
+
}
|
|
48
|
+
/** 宫格的一格(div[role=listitem]):有 onClick 时可点击 */
|
|
49
|
+
export declare const GridItem: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<GridItemProps>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { dataAttrs, hasContent, mergeAttrs, mergePartProps } from "../utils/props.js";
|
|
2
|
+
import { Icon } from "../base/Icon.js";
|
|
3
|
+
import { Badge } from "./Badge.js";
|
|
4
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
5
|
+
import { _component, childrenProp, createContext, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
6
|
+
import { createVNode, isVNode } from "vue";
|
|
7
|
+
//#region src/display/Grid.tsx
|
|
8
|
+
/** 宫格提供给各格的 */
|
|
9
|
+
function _isSlot(s) {
|
|
10
|
+
return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
|
|
11
|
+
}
|
|
12
|
+
var GridContext = createContext("Grid");
|
|
13
|
+
/** 未声明的属性落到根元素(div)上 */
|
|
14
|
+
/** Grid、GridItem 的样式:root、bordered、item、itemBorder、square、clickable、icon、text */
|
|
15
|
+
var gridStyles = css.create({
|
|
16
|
+
root: {
|
|
17
|
+
display: "flex",
|
|
18
|
+
flexWrap: "wrap",
|
|
19
|
+
backgroundColor: "_surface"
|
|
20
|
+
},
|
|
21
|
+
bordered: {
|
|
22
|
+
borderBlockStartWidth: "_hairline",
|
|
23
|
+
borderBlockStartStyle: "solid",
|
|
24
|
+
borderBlockStartColor: "_border"
|
|
25
|
+
},
|
|
26
|
+
item: {
|
|
27
|
+
boxSizing: "border-box",
|
|
28
|
+
display: "flex",
|
|
29
|
+
flexDirection: "column",
|
|
30
|
+
alignItems: "center",
|
|
31
|
+
justifyContent: "center",
|
|
32
|
+
gap: "0.45em",
|
|
33
|
+
paddingBlock: "1em",
|
|
34
|
+
paddingInline: "0.5em",
|
|
35
|
+
fontSize: "_xs",
|
|
36
|
+
color: "_text",
|
|
37
|
+
textAlign: "center"
|
|
38
|
+
},
|
|
39
|
+
itemBorder: {
|
|
40
|
+
borderInlineEndWidth: "_hairline",
|
|
41
|
+
borderInlineEndStyle: "solid",
|
|
42
|
+
borderInlineEndColor: "_border",
|
|
43
|
+
borderBlockEndWidth: "_hairline",
|
|
44
|
+
borderBlockEndStyle: "solid",
|
|
45
|
+
borderBlockEndColor: "_border"
|
|
46
|
+
},
|
|
47
|
+
square: { aspectRatio: "1" },
|
|
48
|
+
clickable: {
|
|
49
|
+
cursor: "pointer",
|
|
50
|
+
userSelect: "none",
|
|
51
|
+
backgroundColor: {
|
|
52
|
+
default: "_surface",
|
|
53
|
+
":active": "_fillActive"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
icon: {
|
|
57
|
+
fontSize: "1.75em",
|
|
58
|
+
color: "_text"
|
|
59
|
+
},
|
|
60
|
+
text: { overflowWrap: "anywhere" }
|
|
61
|
+
});
|
|
62
|
+
/** 宫格(div > 各格) */
|
|
63
|
+
var Grid = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
64
|
+
const columns = readonlyProp(_props, "columns", 4);
|
|
65
|
+
const square = readonlyProp(_props, "square", false);
|
|
66
|
+
const border = readonlyProp(_props, "border", true);
|
|
67
|
+
const children = childrenProp(_props);
|
|
68
|
+
const rest = restProps(_props, _ctx, false);
|
|
69
|
+
GridContext.provide({
|
|
70
|
+
get columns() {
|
|
71
|
+
return columns.value;
|
|
72
|
+
},
|
|
73
|
+
get square() {
|
|
74
|
+
return square.value;
|
|
75
|
+
},
|
|
76
|
+
get border() {
|
|
77
|
+
return border.value;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return () => createVNode("div", mergeAttrs({ sx: [gridStyles.root, border.value && gridStyles.bordered] }, rest, { role: "list" }), [children.value]);
|
|
81
|
+
}, {
|
|
82
|
+
name: "Grid",
|
|
83
|
+
props: [
|
|
84
|
+
"columns",
|
|
85
|
+
"square",
|
|
86
|
+
"border"
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
/** 未声明的属性落到格子(div)上 */
|
|
90
|
+
/** 宫格的一格(div[role=listitem]):有 onClick 时可点击 */
|
|
91
|
+
var GridItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
|
|
92
|
+
const icon = readonlyProp(_props2, "icon");
|
|
93
|
+
const text = readonlyProp(_props2, "text");
|
|
94
|
+
const badge = readonlyProp(_props2, "badge");
|
|
95
|
+
const children = childrenProp(_props2);
|
|
96
|
+
const propsIcon = readonlyProp(_props2, "propsIcon");
|
|
97
|
+
const rest = restProps(_props2, _ctx2, false);
|
|
98
|
+
const grid = GridContext.inject();
|
|
99
|
+
return () => {
|
|
100
|
+
const clickable = rest.onClick !== void 0;
|
|
101
|
+
const glyph = icon.value && createVNode(Icon, mergePartProps({
|
|
102
|
+
icon: icon.value,
|
|
103
|
+
sx: gridStyles.icon
|
|
104
|
+
}, propsIcon.value), null);
|
|
105
|
+
return createVNode("div", mergeAttrs({
|
|
106
|
+
sx: [
|
|
107
|
+
gridStyles.item,
|
|
108
|
+
css.select(() => grid.border && gridStyles.itemBorder, true),
|
|
109
|
+
css.select(() => grid.square && gridStyles.square, true),
|
|
110
|
+
clickable && gridStyles.clickable
|
|
111
|
+
],
|
|
112
|
+
style: {
|
|
113
|
+
flexBasis: `${100 / grid.columns}%`,
|
|
114
|
+
maxWidth: `${100 / grid.columns}%`
|
|
115
|
+
}
|
|
116
|
+
}, rest, {
|
|
117
|
+
role: "listitem",
|
|
118
|
+
...dataAttrs({ "data-clickable": clickable })
|
|
119
|
+
}), [hasContent(children.value) ? children.value : [glyph && (badge.value === void 0 || badge.value === false ? glyph : createVNode(Badge, {
|
|
120
|
+
"content": badge.value === true ? void 0 : badge.value,
|
|
121
|
+
"dot": badge.value === true
|
|
122
|
+
}, _isSlot(glyph) ? glyph : { default: () => [glyph] })), hasContent(text.value) && createVNode("span", mergeAttrs({ sx: gridStyles.text }), [text.value])]]);
|
|
123
|
+
};
|
|
124
|
+
}, {
|
|
125
|
+
name: "GridItem",
|
|
126
|
+
props: [
|
|
127
|
+
"icon",
|
|
128
|
+
"text",
|
|
129
|
+
"badge",
|
|
130
|
+
"propsIcon"
|
|
131
|
+
]
|
|
132
|
+
});
|
|
133
|
+
//#endregion
|
|
134
|
+
export { Grid, GridItem, gridStyles };
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=Grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Grid.js","names":["_isVNode","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode"],"sources":["../../src/display/Grid.tsx"],"sourcesContent":["/**\n * 宫格:一排几个的入口(首页的功能区、个人中心的订单状态),每格一个图标加文字,可带徽标。\n *\n * <Grid columns={4}>\n * <GridItem icon={Wallet} text=\"待付款\" badge={2} onClick={…} />\n * <GridItem icon={Truck} text=\"待收货\" />\n * </Grid>\n * <Grid columns={3} square border={false}>…</Grid>\n */\nimport { _component, createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Icon, type IconData, type IconProps } from '../base/Icon';\nimport { dataAttrs, hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { Badge } from './Badge';\n\n/** 宫格提供给各格的 */\ninterface GridState {\n readonly columns: number;\n readonly square: boolean;\n readonly border: boolean;\n}\n\nconst GridContext = createContext<GridState>('Grid');\n\n/** 未声明的属性落到根元素(div)上 */\nexport interface GridProps extends PartProps<'div'> {\n /**\n * 一排几个\n * @default 4\n */\n columns?: number;\n /** 每格是正方形 */\n square?: boolean;\n /**\n * 格子之间画细线\n * @default true\n */\n border?: boolean;\n /** 各个 GridItem */\n children?: VNodeChild;\n}\n\n/** Grid、GridItem 的样式:root、bordered、item、itemBorder、square、clickable、icon、text */\nexport const gridStyles = css.create({\n root: { display: 'flex', flexWrap: 'wrap', backgroundColor: '_surface' },\n bordered: {\n borderBlockStartWidth: '_hairline',\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_border',\n },\n item: {\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '0.45em',\n paddingBlock: '1em',\n paddingInline: '0.5em',\n fontSize: '_xs',\n color: '_text',\n textAlign: 'center',\n },\n itemBorder: {\n borderInlineEndWidth: '_hairline',\n borderInlineEndStyle: 'solid',\n borderInlineEndColor: '_border',\n borderBlockEndWidth: '_hairline',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_border',\n },\n square: { aspectRatio: '1' },\n clickable: {\n cursor: 'pointer',\n userSelect: 'none',\n backgroundColor: { default: '_surface', ':active': '_fillActive' },\n },\n icon: { fontSize: '1.75em', color: '_text' },\n text: { overflowWrap: 'anywhere' },\n});\n\n/** 宫格(div > 各格) */\nexport const Grid = _component(\n ({ columns = 4, square = false, border = true, children, ...rest }: GridProps) => {\n GridContext.provide({\n get columns() {\n return columns;\n },\n get square() {\n return square;\n },\n get border() {\n return border;\n },\n });\n return () => (\n <div\n {...mergeAttrs<'div'>({ sx: [gridStyles.root, border && gridStyles.bordered] }, rest, {\n role: 'list',\n })}\n >\n {children}\n </div>\n );\n },\n);\n\n/** 未声明的属性落到格子(div)上 */\nexport interface GridItemProps extends PartProps<'div', 'role'> {\n /** 图标 */\n icon?: IconData;\n /** 文字 */\n text?: VNodeChild;\n /** 图标右上角的徽标:数字、文字,true 是小红点 */\n badge?: number | string | boolean;\n /** 自定义内容(代替图标与文字) */\n children?: VNodeChild;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n}\n\n/** 宫格的一格(div[role=listitem]):有 onClick 时可点击 */\nexport const GridItem = _component(\n ({ icon, text, badge, children, propsIcon, ...rest }: GridItemProps) => {\n const grid = GridContext.inject();\n return () => {\n const clickable = rest.onClick !== undefined;\n const glyph = icon && (\n <Icon {...mergePartProps<IconProps>({ icon, sx: gridStyles.icon }, propsIcon)} />\n );\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n gridStyles.item,\n grid.border && gridStyles.itemBorder,\n grid.square && gridStyles.square,\n clickable && gridStyles.clickable,\n ],\n style: { flexBasis: `${100 / grid.columns}%`, maxWidth: `${100 / grid.columns}%` },\n },\n rest,\n { role: 'listitem', ...dataAttrs({ 'data-clickable': clickable }) },\n )}\n >\n {hasContent(children)\n ? children\n : [\n glyph &&\n (badge === undefined || badge === false ? (\n glyph\n ) : (\n <Badge content={badge === true ? undefined : badge} dot={badge === true}>\n {glyph}\n </Badge>\n )),\n hasContent(text) && (\n <span {...mergeAttrs<'span'>({ sx: gridStyles.text })}>{text}</span>\n ),\n ]}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
|
+
import { type IconProps } from '../base/Icon';
|
|
3
|
+
import { type LoadingProps } from '../feedback/Loading';
|
|
4
|
+
import { type PartProps } from '../utils/props';
|
|
5
|
+
/** 填充方式(同 CSS 的 object-fit) */
|
|
6
|
+
export interface ImageFits {
|
|
7
|
+
/** 保持比例填满,多出的裁掉 */
|
|
8
|
+
cover: unknown;
|
|
9
|
+
/** 保持比例完整显示,可能留白 */
|
|
10
|
+
contain: unknown;
|
|
11
|
+
/** 拉伸填满 */
|
|
12
|
+
fill: unknown;
|
|
13
|
+
/** 原始大小 */
|
|
14
|
+
none: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** 由组件管理的 img 属性 */
|
|
17
|
+
export type ImageManaged = 'src' | 'loading' | 'onLoad' | 'onError';
|
|
18
|
+
/** 未声明的属性落到 img 上 */
|
|
19
|
+
export interface ImageProps extends PartProps<'img', ImageManaged> {
|
|
20
|
+
/** 图片地址 */
|
|
21
|
+
src?: string;
|
|
22
|
+
/** 宽度(px,或 CSS 长度) */
|
|
23
|
+
width?: number | string;
|
|
24
|
+
/** 高度(px,或 CSS 长度) */
|
|
25
|
+
height?: number | string;
|
|
26
|
+
/**
|
|
27
|
+
* 填充方式
|
|
28
|
+
* @default 'fill'
|
|
29
|
+
*/
|
|
30
|
+
fit?: keyof ImageFits;
|
|
31
|
+
/** 圆角档位 */
|
|
32
|
+
radius?: 'sm' | 'md' | 'lg';
|
|
33
|
+
/** 圆形 */
|
|
34
|
+
round?: boolean;
|
|
35
|
+
/** 进入视口才加载 */
|
|
36
|
+
lazy?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* 加载中显示旋转指示
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
showLoading?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 加载失败显示占位图标
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
showError?: boolean;
|
|
47
|
+
/** 加载完成 */
|
|
48
|
+
onLoad?: (event: Event) => void;
|
|
49
|
+
/** 加载失败 */
|
|
50
|
+
onError?: (event: Event) => void;
|
|
51
|
+
/** 外层(裁切与占位)的部件属性 */
|
|
52
|
+
propsRoot?: PartProps<'div'>;
|
|
53
|
+
/** 加载指示的部件属性 */
|
|
54
|
+
propsLoading?: Partial<LoadingProps>;
|
|
55
|
+
/** 失败图标的部件属性 */
|
|
56
|
+
propsError?: Partial<IconProps>;
|
|
57
|
+
}
|
|
58
|
+
/** Image 的样式:root、round、各圆角、img、hidden、placeholder */
|
|
59
|
+
export declare const imageStyles: Readonly<{
|
|
60
|
+
hidden: css.CompiledStyles;
|
|
61
|
+
img: css.CompiledStyles;
|
|
62
|
+
lg: css.CompiledStyles;
|
|
63
|
+
md: css.CompiledStyles;
|
|
64
|
+
placeholder: css.CompiledStyles;
|
|
65
|
+
root: css.CompiledStyles;
|
|
66
|
+
round: css.CompiledStyles;
|
|
67
|
+
sm: css.CompiledStyles;
|
|
68
|
+
}>;
|
|
69
|
+
/** 图片(div > img + 占位) */
|
|
70
|
+
export declare const Image: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<ImageProps>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { dataAttrs, mergeAttrs, mergePartProps } from "../utils/props.js";
|
|
2
|
+
import { Icon } from "../base/Icon.js";
|
|
3
|
+
import { Loading } from "../feedback/Loading.js";
|
|
4
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
5
|
+
import { _component, overridable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
6
|
+
import { createVNode } from "vue";
|
|
7
|
+
import { ImageOff } from "@lucide/icons";
|
|
8
|
+
//#region src/display/Image.tsx
|
|
9
|
+
/**
|
|
10
|
+
* 图片:按 fit 填充、加载中与加载失败有占位、可圆角或圆形、可懒加载。
|
|
11
|
+
*
|
|
12
|
+
* <Image src={url} width={96} height={96} fit="cover" radius="md" />
|
|
13
|
+
* <Image src={avatar} width={40} height={40} round />
|
|
14
|
+
*
|
|
15
|
+
* 小程序里由运行时渲染成 image 组件,fit 换成对应的 mode。
|
|
16
|
+
*/
|
|
17
|
+
/** 填充方式(同 CSS 的 object-fit) */
|
|
18
|
+
/** 小程序 image 组件的 mode(运行时读 img 上的 mode 属性) */
|
|
19
|
+
var MINI_MODES = {
|
|
20
|
+
cover: "aspectFill",
|
|
21
|
+
contain: "aspectFit",
|
|
22
|
+
fill: "scaleToFill",
|
|
23
|
+
none: "center"
|
|
24
|
+
};
|
|
25
|
+
/** 加载状态 */
|
|
26
|
+
/** 由组件管理的 img 属性 */
|
|
27
|
+
/** 未声明的属性落到 img 上 */
|
|
28
|
+
/**
|
|
29
|
+
* 给小程序 image 组件的属性(mode、lazy-load):浏览器忽略不认识的属性;
|
|
30
|
+
* 不在 img 的属性类型里,单独组一个对象再展开
|
|
31
|
+
*/
|
|
32
|
+
var miniImageAttrs = (fit, lazy) => ({
|
|
33
|
+
mode: MINI_MODES[fit],
|
|
34
|
+
"lazy-load": lazy || void 0
|
|
35
|
+
});
|
|
36
|
+
var length = (value) => typeof value === "number" ? `${value}px` : value;
|
|
37
|
+
/** Image 的样式:root、round、各圆角、img、hidden、placeholder */
|
|
38
|
+
var imageStyles = css.create({
|
|
39
|
+
root: {
|
|
40
|
+
position: "relative",
|
|
41
|
+
display: "inline-block",
|
|
42
|
+
overflow: "hidden",
|
|
43
|
+
verticalAlign: "middle",
|
|
44
|
+
backgroundColor: {
|
|
45
|
+
default: "transparent",
|
|
46
|
+
"[data-status=\"loading\"]": "_fill",
|
|
47
|
+
"[data-status=\"error\"]": "_fill"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
round: { borderRadius: "_full" },
|
|
51
|
+
sm: { borderRadius: "_sm" },
|
|
52
|
+
md: { borderRadius: "_md" },
|
|
53
|
+
lg: { borderRadius: "_lg" },
|
|
54
|
+
img: {
|
|
55
|
+
display: "block",
|
|
56
|
+
width: "100%",
|
|
57
|
+
height: "100%"
|
|
58
|
+
},
|
|
59
|
+
hidden: { opacity: 0 },
|
|
60
|
+
placeholder: {
|
|
61
|
+
position: "absolute",
|
|
62
|
+
inset: 0,
|
|
63
|
+
display: "flex",
|
|
64
|
+
alignItems: "center",
|
|
65
|
+
justifyContent: "center",
|
|
66
|
+
fontSize: "_xxl",
|
|
67
|
+
color: "_textPlaceholder"
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
/** 图片(div > img + 占位) */
|
|
71
|
+
var Image = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
72
|
+
const src = readonlyProp(_props, "src");
|
|
73
|
+
const width = readonlyProp(_props, "width");
|
|
74
|
+
const height = readonlyProp(_props, "height");
|
|
75
|
+
const fit = readonlyProp(_props, "fit", "fill");
|
|
76
|
+
const radius = readonlyProp(_props, "radius");
|
|
77
|
+
const round = readonlyProp(_props, "round", false);
|
|
78
|
+
const lazy = readonlyProp(_props, "lazy", false);
|
|
79
|
+
const showLoading = readonlyProp(_props, "showLoading", true);
|
|
80
|
+
const showError = readonlyProp(_props, "showError", true);
|
|
81
|
+
const onLoad = readonlyProp(_props, "onLoad");
|
|
82
|
+
const onError = readonlyProp(_props, "onError");
|
|
83
|
+
const propsRoot = readonlyProp(_props, "propsRoot");
|
|
84
|
+
const propsLoading = readonlyProp(_props, "propsLoading");
|
|
85
|
+
const propsError = readonlyProp(_props, "propsError");
|
|
86
|
+
const rest = restProps(_props, _ctx, true);
|
|
87
|
+
let status = overridable(() => src.value ? "loading" : "error");
|
|
88
|
+
return () => createVNode("div", mergeAttrs({ sx: [
|
|
89
|
+
imageStyles.root,
|
|
90
|
+
round.value && imageStyles.round,
|
|
91
|
+
radius.value && imageStyles[radius.value]
|
|
92
|
+
] }, propsRoot.value, {
|
|
93
|
+
style: {
|
|
94
|
+
width: length(width.value),
|
|
95
|
+
height: length(height.value)
|
|
96
|
+
},
|
|
97
|
+
...dataAttrs({ "data-status": status.value })
|
|
98
|
+
}), [
|
|
99
|
+
src.value && createVNode("img", mergeAttrs({ sx: [imageStyles.img, status.value !== "loaded" && imageStyles.hidden] }, rest, {
|
|
100
|
+
src: src.value,
|
|
101
|
+
loading: lazy.value ? "lazy" : void 0,
|
|
102
|
+
style: { objectFit: fit.value },
|
|
103
|
+
...miniImageAttrs(fit.value, lazy.value),
|
|
104
|
+
onLoad: (event) => {
|
|
105
|
+
status.value = "loaded";
|
|
106
|
+
onLoad.value?.(event);
|
|
107
|
+
},
|
|
108
|
+
onError: (event) => {
|
|
109
|
+
status.value = "error";
|
|
110
|
+
onError.value?.(event);
|
|
111
|
+
}
|
|
112
|
+
}), null),
|
|
113
|
+
status.value === "loading" && showLoading.value && createVNode("div", mergeAttrs({ sx: imageStyles.placeholder }), [createVNode(Loading, mergePartProps({}, propsLoading.value), null)]),
|
|
114
|
+
status.value === "error" && showError.value && createVNode("div", mergeAttrs({ sx: imageStyles.placeholder }), [createVNode(Icon, mergePartProps({ icon: ImageOff }, propsError.value), null)])
|
|
115
|
+
]);
|
|
116
|
+
}, {
|
|
117
|
+
name: "Image",
|
|
118
|
+
props: [
|
|
119
|
+
"src",
|
|
120
|
+
"width",
|
|
121
|
+
"height",
|
|
122
|
+
"fit",
|
|
123
|
+
"radius",
|
|
124
|
+
"round",
|
|
125
|
+
"lazy",
|
|
126
|
+
"showLoading",
|
|
127
|
+
"showError",
|
|
128
|
+
"onLoad",
|
|
129
|
+
"onError",
|
|
130
|
+
"propsRoot",
|
|
131
|
+
"propsLoading",
|
|
132
|
+
"propsError"
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
//#endregion
|
|
136
|
+
export { Image, imageStyles };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=Image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.js","names":["_vtp_readonlyProp","_vtp_restProps","_vtp_overridable","_createVNode"],"sources":["../../src/display/Image.tsx"],"sourcesContent":["/**\n * 图片:按 fit 填充、加载中与加载失败有占位、可圆角或圆形、可懒加载。\n *\n * <Image src={url} width={96} height={96} fit=\"cover\" radius=\"md\" />\n * <Image src={avatar} width={40} height={40} round />\n *\n * 小程序里由运行时渲染成 image 组件,fit 换成对应的 mode。\n */\nimport { ImageOff } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { Loading, type LoadingProps } from '../feedback/Loading';\nimport { dataAttrs, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\n\n/** 填充方式(同 CSS 的 object-fit) */\nexport interface ImageFits {\n /** 保持比例填满,多出的裁掉 */\n cover: unknown;\n /** 保持比例完整显示,可能留白 */\n contain: unknown;\n /** 拉伸填满 */\n fill: unknown;\n /** 原始大小 */\n none: unknown;\n}\n\n/** 小程序 image 组件的 mode(运行时读 img 上的 mode 属性) */\nconst MINI_MODES = {\n cover: 'aspectFill',\n contain: 'aspectFit',\n fill: 'scaleToFill',\n none: 'center',\n} as const satisfies Record<keyof ImageFits, string>;\n\n/** 加载状态 */\ntype ImageStatus = 'loading' | 'loaded' | 'error';\n\n/** 由组件管理的 img 属性 */\nexport type ImageManaged = 'src' | 'loading' | 'onLoad' | 'onError';\n\n/** 未声明的属性落到 img 上 */\nexport interface ImageProps extends PartProps<'img', ImageManaged> {\n /** 图片地址 */\n src?: string;\n /** 宽度(px,或 CSS 长度) */\n width?: number | string;\n /** 高度(px,或 CSS 长度) */\n height?: number | string;\n /**\n * 填充方式\n * @default 'fill'\n */\n fit?: keyof ImageFits;\n /** 圆角档位 */\n radius?: 'sm' | 'md' | 'lg';\n /** 圆形 */\n round?: boolean;\n /** 进入视口才加载 */\n lazy?: boolean;\n /**\n * 加载中显示旋转指示\n * @default true\n */\n showLoading?: boolean;\n /**\n * 加载失败显示占位图标\n * @default true\n */\n showError?: boolean;\n /** 加载完成 */\n onLoad?: (event: Event) => void;\n /** 加载失败 */\n onError?: (event: Event) => void;\n /** 外层(裁切与占位)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 加载指示的部件属性 */\n propsLoading?: Partial<LoadingProps>;\n /** 失败图标的部件属性 */\n propsError?: Partial<IconProps>;\n}\n\n/**\n * 给小程序 image 组件的属性(mode、lazy-load):浏览器忽略不认识的属性;\n * 不在 img 的属性类型里,单独组一个对象再展开\n */\nconst miniImageAttrs = (fit: keyof ImageFits, lazy: boolean): Record<string, unknown> => ({\n mode: MINI_MODES[fit],\n 'lazy-load': lazy || undefined,\n});\n\nconst length = (value: number | string | undefined) =>\n typeof value === 'number' ? `${value}px` : value;\n\n/** Image 的样式:root、round、各圆角、img、hidden、placeholder */\nexport const imageStyles = css.create({\n root: {\n position: 'relative',\n display: 'inline-block',\n overflow: 'hidden',\n verticalAlign: 'middle',\n backgroundColor: {\n default: 'transparent',\n '[data-status=\"loading\"]': '_fill',\n '[data-status=\"error\"]': '_fill',\n },\n },\n round: { borderRadius: '_full' },\n sm: { borderRadius: '_sm' },\n md: { borderRadius: '_md' },\n lg: { borderRadius: '_lg' },\n img: { display: 'block', width: '100%', height: '100%' },\n hidden: { opacity: 0 },\n placeholder: {\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '_xxl',\n color: '_textPlaceholder',\n },\n});\n\n/** 图片(div > img + 占位) */\nexport const Image = _component(\n ({\n src,\n width,\n height,\n fit = 'fill',\n radius,\n round = false,\n lazy = false,\n showLoading = true,\n showError = true,\n onLoad,\n onError,\n propsRoot,\n propsLoading,\n propsError,\n ...rest\n }: ImageProps) => {\n // 加载完、失败时覆盖;换了 src 重新回到加载中\n let status = _derived<ImageStatus>(src ? 'loading' : 'error');\n return () => (\n <div\n {...mergeAttrs<'div'>(\n { sx: [imageStyles.root, round && imageStyles.round, radius && imageStyles[radius]] },\n propsRoot,\n {\n style: { width: length(width), height: length(height) },\n ...dataAttrs({ 'data-status': status }),\n },\n )}\n >\n {src && (\n <img\n {...mergeAttrs<'img'>(\n { sx: [imageStyles.img, status !== 'loaded' && imageStyles.hidden] },\n rest,\n {\n src,\n loading: lazy ? 'lazy' : undefined,\n style: { objectFit: fit },\n ...miniImageAttrs(fit, lazy),\n onLoad: (event: Event) => {\n status = 'loaded';\n onLoad?.(event);\n },\n onError: (event: Event) => {\n status = 'error';\n onError?.(event);\n },\n },\n )}\n />\n )}\n {status === 'loading' && showLoading && (\n <div {...mergeAttrs<'div'>({ sx: imageStyles.placeholder })}>\n <Loading {...mergePartProps<LoadingProps>({}, propsLoading)} />\n </div>\n )}\n {status === 'error' && showError && (\n <div {...mergeAttrs<'div'>({ sx: imageStyles.placeholder })}>\n <Icon {...mergePartProps<IconProps>({ icon: ImageOff }, propsError)} />\n </div>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,IAAM,aAAa;CACjB,OAAO;CACP,SAAS;CACT,MAAM;CACN,MAAM;AACR;;;;;;;;AAqDA,IAAM,kBAAkB,KAAsB,UAA4C;CACxF,MAAM,WAAW;CACjB,aAAa,QAAQ,KAAA;AACvB;AAEA,IAAM,UAAU,UACd,OAAO,UAAU,WAAW,GAAG,MAAK,MAAO;;AAG7C,IAAa,cAAc,IAAI,OAAO;CACpC,MAAM;EACJ,UAAU;EACV,SAAS;EACT,UAAU;EACV,eAAe;EACf,iBAAiB;GACf,SAAS;GACT,6BAA2B;GAC3B,2BAAyB;EAC3B;CACF;CACA,OAAO,EAAE,cAAc,QAAQ;CAC/B,IAAI,EAAE,cAAc,MAAM;CAC1B,IAAI,EAAE,cAAc,MAAM;CAC1B,IAAI,EAAE,cAAc,MAAM;CAC1B,KAAK;EAAE,SAAS;EAAS,OAAO;EAAQ,QAAQ;CAAO;CACvD,QAAQ,EAAE,SAAS,EAAE;CACrB,aAAa;EACX,UAAU;EACV,OAAO;EACP,SAAS;EACT,YAAY;EACZ,gBAAgB;EAChB,UAAU;EACV,OAAO;CACT;AACF,CAAC;;AAGD,IAAa,QAAQ,0BACnB,QAAA,SAgBkB;CAAA,MAAA,MAAAA,aAAA,QAAA,KAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,MAAAA,aAAA,QAAA,OAZV,MAAM;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,SAEJ,KAAK;CAAA,MAAA,OAAAA,aAAA,QAAA,QACN,KAAK;CAAA,MAAA,cAAAA,aAAA,QAAA,eACE,IAAI;CAAA,MAAA,YAAAA,aAAA,QAAA,aACN,IAAI;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAMb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAGP,IAAI,SAAMC,kBAAyB,IAAA,QAAM,YAAY,OAAO;CAC5D,aAAOC,YAAA,OAEC,WACF,EAAE,IAAI;EAAC,YAAY;EAAM,MAAA,SAAS,YAAY;EAAO,OAAA,SAAU,YAAW,OAAA;CAAQ,EAAE,GAAC,UAAA,OAErF;EACE,OAAO;GAAE,OAAO,OAAM,MAAA,KAAM;GAAG,QAAQ,OAAM,OAAA,KAAO;EAAE;EACtD,GAAG,UAAU,EAAE,eAAa,OAAA,MAAS,CAAC;CACxC,CACF,GAAC;EAEA,IAAA,SAAAA,YAAA,OAEO,WACF,EAAE,IAAI,CAAC,YAAY,KAAK,OAAA,UAAW,YAAY,YAAY,MAAM,EAAE,GACnE,MACA;GACE,KAAG,IAAA;GACH,SAAS,KAAA,QAAO,SAAS,KAAA;GACzB,OAAO,EAAE,WAAS,IAAA,MAAM;GACxB,GAAG,eAAc,IAAA,OAAA,KAAA,KAAU;GAC3B,SAAS,UAAiB;IACxB,OAAA,QAAS;IACT,OAAA,QAAS,KAAK;GAChB;GACA,UAAU,UAAiB;IACzB,OAAA,QAAS;IACT,QAAA,QAAU,KAAK;GACjB;EACF,CACF,GAAC,IAAA;EAGJ,OAAA,UAAW,aAAS,YAAA,SAAeA,YAAA,OACzB,WAAkB,EAAE,IAAI,YAAY,YAAY,CAAC,GAAC,CAAAA,YAAA,SAC5C,eAA6B,CAAC,GAAC,aAAA,KAAc,GAAC,IAAA,CAAA,CAAA;EAG9D,OAAA,UAAW,WAAO,UAAA,SAAaA,YAAA,OACrB,WAAkB,EAAE,IAAI,YAAY,YAAY,CAAC,GAAC,CAAAA,YAAA,MAC/C,eAA0B,EAAE,MAAM,SAAS,GAAC,WAAA,KAAY,GAAC,IAAA,CAAA,CAAA;CAEtE,CAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
|
+
import { type VNodeChild } from 'vue';
|
|
3
|
+
import { type PartProps } from '../utils/props';
|
|
4
|
+
/** 未声明的属性落到根元素(div)上 */
|
|
5
|
+
export interface IndexBarProps extends Omit<PartProps<'div'>, 'onSelect'> {
|
|
6
|
+
/**
|
|
7
|
+
* 组标题吸住时离顶部多远(CSS 长度;页面顶部有固定的导航栏时写它的高度)
|
|
8
|
+
* @default '0px'
|
|
9
|
+
*/
|
|
10
|
+
stickyOffsetTop?: string;
|
|
11
|
+
/** 点(或滑到)右边的一个字母 */
|
|
12
|
+
onSelect?: (index: string) => void;
|
|
13
|
+
/** 各组的 IndexAnchor 与内容 */
|
|
14
|
+
children?: VNodeChild;
|
|
15
|
+
/** 右边字母栏的部件属性 */
|
|
16
|
+
propsSidebar?: PartProps<'div'>;
|
|
17
|
+
}
|
|
18
|
+
/** IndexBar、IndexAnchor 的样式 */
|
|
19
|
+
export declare const indexBarStyles: Readonly<{
|
|
20
|
+
anchor: css.CompiledStyles;
|
|
21
|
+
letter: css.CompiledStyles;
|
|
22
|
+
sidebar: css.CompiledStyles;
|
|
23
|
+
}>;
|
|
24
|
+
/** 索引栏(div > 内容 + 右边的字母栏) */
|
|
25
|
+
export declare const IndexBar: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<IndexBarProps>;
|
|
26
|
+
/** 未声明的属性落到标题(div)上 */
|
|
27
|
+
export interface IndexAnchorProps extends PartProps<'div'> {
|
|
28
|
+
/** 这一组的字母(也是右边字母栏上的字) */
|
|
29
|
+
index: string;
|
|
30
|
+
/** 标题的内容;不给时显示 index */
|
|
31
|
+
children?: VNodeChild;
|
|
32
|
+
}
|
|
33
|
+
/** 一组的标题(div,吸顶) */
|
|
34
|
+
export declare const IndexAnchor: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<IndexAnchorProps>;
|