sard-uniapp 1.23.4 → 1.24.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/CHANGELOG.md +37 -0
- package/README.md +2 -2
- package/components/calendar-input/calendar-input.vue +1 -0
- package/components/card/README.md +7 -0
- package/components/card/card.vue +17 -8
- package/components/card/common.d.ts +1 -0
- package/components/card/index.scss +1 -1
- package/components/cascader-input/cascader-input.vue +1 -0
- package/components/checkbox-input/checkbox-input.vue +1 -0
- package/components/config/index.d.ts +21 -0
- package/components/config/index.js +19 -1
- package/components/cool-icon/README.md +81 -0
- package/components/cool-icon/common.d.ts +21 -0
- package/components/cool-icon/common.js +2 -0
- package/components/cool-icon/cool-icon.d.ts +16 -0
- package/components/cool-icon/cool-icon.vue +86 -0
- package/components/cool-icon/index.d.ts +1 -0
- package/components/cool-icon/index.js +1 -0
- package/components/cool-icon/index.scss +186 -0
- package/components/cool-icon/variables.scss +12 -0
- package/components/datetime-picker-input/datetime-picker-input.vue +1 -0
- package/components/datetime-range-picker-input/datetime-range-picker-input.vue +1 -0
- package/components/input/common.d.ts +2 -0
- package/components/input/input.d.ts +1 -0
- package/components/input/input.vue +7 -3
- package/components/keyboard/README.md +15 -14
- package/components/keyboard/common.d.ts +3 -1
- package/components/keyboard/keyboard.d.ts +2 -1
- package/components/keyboard/keyboard.vue +9 -7
- package/components/radio-input/radio-input.vue +1 -0
- package/components/segmented/README.md +147 -0
- package/components/segmented/common.d.ts +52 -0
- package/components/segmented/common.js +8 -0
- package/components/segmented/index.d.ts +1 -0
- package/components/segmented/index.js +1 -0
- package/components/segmented/index.scss +60 -0
- package/components/segmented/segmented.d.ts +21 -0
- package/components/segmented/segmented.vue +163 -0
- package/components/segmented/variables.scss +21 -0
- package/components/segmented-item/common.d.ts +21 -0
- package/components/segmented-item/common.js +1 -0
- package/components/segmented-item/index.d.ts +1 -0
- package/components/segmented-item/index.js +1 -0
- package/components/segmented-item/index.scss +60 -0
- package/components/segmented-item/segmented-item.d.ts +14 -0
- package/components/segmented-item/segmented-item.vue +99 -0
- package/components/sticky/README.md +4 -0
- package/components/tree/README.md +5 -4
- package/components/tree/common.d.ts +5 -1
- package/components/tree/tree.d.ts +8 -0
- package/components/tree/tree.vue +11 -2
- package/components/tree-node/tree-node.vue +1 -1
- package/components/upload/README.md +15 -1
- package/components/upload/common.d.ts +2 -2
- package/components/upload/upload.d.ts +0 -1
- package/components/upload/upload.vue +2 -2
- package/components/upload/utils.d.ts +2 -2
- package/components/upload/utils.js +33 -2
- package/components/watermark/README.md +74 -0
- package/components/watermark/common.d.ts +37 -0
- package/components/watermark/common.js +10 -0
- package/components/watermark/index.d.ts +1 -0
- package/components/watermark/index.js +1 -0
- package/components/watermark/index.scss +28 -0
- package/components/watermark/variables.scss +5 -0
- package/components/watermark/watermark.d.ts +16 -0
- package/components/watermark/watermark.vue +263 -0
- package/global.d.ts +4 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/index.scss +3 -0
- package/package.json +3 -2
- package/utils/array.d.ts +1 -1
- package/utils/geometry.d.ts +11 -0
- package/utils/geometry.js +28 -0
- package/utils/object.d.ts +2 -2
- package/utils/object.js +3 -3
- package/components/upload-preview/play.png +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@use '../style/base' as *;
|
|
2
|
+
|
|
3
|
+
@include bem(segmented) {
|
|
4
|
+
@include b() {
|
|
5
|
+
@include universal;
|
|
6
|
+
flex-direction: row;
|
|
7
|
+
align-items: stretch;
|
|
8
|
+
min-height: var(--sar-segmented-min-height);
|
|
9
|
+
padding: var(--sar-segmented-padding);
|
|
10
|
+
border-radius: var(--sar-segmented-border-radius);
|
|
11
|
+
background-color: var(--sar-segmented-bg);
|
|
12
|
+
font-size: var(--sar-segmented-font-size);
|
|
13
|
+
|
|
14
|
+
@include m(vertical) {
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
|
|
17
|
+
@include e(group) {
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@include e(pointer) {
|
|
22
|
+
width: 100%;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@include m(small) {
|
|
27
|
+
min-height: var(--sar-segmented-small-min-height);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@include m(large) {
|
|
31
|
+
min-height: var(--sar-segmented-large-min-height);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@include m(round) {
|
|
35
|
+
border-radius: var(--sar-rounded-full);
|
|
36
|
+
|
|
37
|
+
@include e(pointer) {
|
|
38
|
+
border-radius: var(--sar-rounded-full);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@include e(pointer) {
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: 0;
|
|
46
|
+
left: 0;
|
|
47
|
+
height: 100%;
|
|
48
|
+
border-radius: calc(var(--sar-segmented-border-radius) - 4rpx);
|
|
49
|
+
background-color: var(--sar-segmented-pointer-bg);
|
|
50
|
+
box-shadow: var(--sar-segmented-pointer-box-shadow);
|
|
51
|
+
transition: transform var(--sar-segmented-pointer-duration);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@include e(group) {
|
|
55
|
+
@include universal;
|
|
56
|
+
flex-direction: row;
|
|
57
|
+
align-items: stretch;
|
|
58
|
+
width: 100%;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SegmentedProps, type SegmentedSlots } from './common';
|
|
2
|
+
declare function __VLS_template(): Readonly<SegmentedSlots> & SegmentedSlots;
|
|
3
|
+
declare const __VLS_component: import("vue").DefineComponent<SegmentedProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
4
|
+
"update:model-value": (value: any) => any;
|
|
5
|
+
change: (value: any) => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<SegmentedProps> & Readonly<{
|
|
7
|
+
"onUpdate:model-value"?: ((value: any) => any) | undefined;
|
|
8
|
+
onChange?: ((value: any) => any) | undefined;
|
|
9
|
+
}>, {
|
|
10
|
+
size: import("./common").SegmentedSize;
|
|
11
|
+
shape: "square" | "round";
|
|
12
|
+
direction: "horizontal" | "vertical";
|
|
13
|
+
validateEvent: boolean;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view :class="segmentedClass" :style="segmentedStyle">
|
|
3
|
+
<view :class="groupClass">
|
|
4
|
+
<view :class="pointerClass" :style="pointerStyle"></view>
|
|
5
|
+
<slot>
|
|
6
|
+
<sar-segmented-item
|
|
7
|
+
v-for="(option, i) in convertedOptions"
|
|
8
|
+
:key="i"
|
|
9
|
+
:value="option.value"
|
|
10
|
+
:label="option.label"
|
|
11
|
+
:disabled="option.disabled"
|
|
12
|
+
:icon="option.icon"
|
|
13
|
+
:icon-family="option.iconFamily"
|
|
14
|
+
:icon-size="option.iconSize"
|
|
15
|
+
/>
|
|
16
|
+
</slot>
|
|
17
|
+
</view>
|
|
18
|
+
</view>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
|
|
23
|
+
import { computed, provide, reactive, ref, toRef, watch } from "vue";
|
|
24
|
+
import { classNames, stringifyStyle, createBem, isPrimitive } from "../../utils";
|
|
25
|
+
import {
|
|
26
|
+
defaultSegmentedProps,
|
|
27
|
+
defaultOptionKeys,
|
|
28
|
+
segmentedContextSymbol
|
|
29
|
+
} from "./common";
|
|
30
|
+
import SarSegmentedItem from "../segmented-item/segmented-item.vue";
|
|
31
|
+
import { useFormItemContext } from "../form";
|
|
32
|
+
/**
|
|
33
|
+
* @property {string} rootClass 组件根元素类名,默认值:-。
|
|
34
|
+
* @property {StyleValue} rootStyle 组件根元素样式,默认值:-。
|
|
35
|
+
* @property {any} modelValue 绑定值,默认值:-。
|
|
36
|
+
* @property {boolean} disabled 是否禁用,默认值:false。
|
|
37
|
+
* @property {boolean} readonly 是否只读,默认值:false。
|
|
38
|
+
* @property {'small' | 'middle' | 'large'} size 组件大小,默认值:'middle'。
|
|
39
|
+
* @property {'horizontal' | 'vertical'} direction 展示的方向,默认值:'horizontal'。
|
|
40
|
+
* @property {'square' | 'round'} shape 形状,默认值:'square'。
|
|
41
|
+
* @property {SegmentedOption[]} options 选项的数据,默认值:-。
|
|
42
|
+
* @property {SegmentedOptionKeys} optionKeys 自定义 options 的 label、value 的字段,默认值:{label: 'label', value: 'value'}。
|
|
43
|
+
* @property {boolean} validateEvent 是否触发表单验证,默认值:true。
|
|
44
|
+
* @event {(value: any) => void} update 当所选值更改时触发
|
|
45
|
+
* @event {(value: any) => void} change 当所选值更改时触发
|
|
46
|
+
*/
|
|
47
|
+
export default _defineComponent({
|
|
48
|
+
components: {
|
|
49
|
+
SarSegmentedItem,
|
|
50
|
+
},
|
|
51
|
+
...{
|
|
52
|
+
options: {
|
|
53
|
+
virtualHost: true,
|
|
54
|
+
styleIsolation: "shared"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
__name: "segmented",
|
|
58
|
+
props: _mergeDefaults({
|
|
59
|
+
rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
|
|
60
|
+
rootClass: { type: String, required: false },
|
|
61
|
+
modelValue: { type: null, required: false },
|
|
62
|
+
disabled: { type: Boolean, required: false },
|
|
63
|
+
readonly: { type: Boolean, required: false },
|
|
64
|
+
size: { type: String, required: false },
|
|
65
|
+
direction: { type: String, required: false },
|
|
66
|
+
shape: { type: String, required: false },
|
|
67
|
+
options: { type: Array, required: false },
|
|
68
|
+
optionKeys: { type: Object, required: false },
|
|
69
|
+
validateEvent: { type: Boolean, required: false }
|
|
70
|
+
}, defaultSegmentedProps),
|
|
71
|
+
emits: ["update:model-value", "change"],
|
|
72
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
73
|
+
const props = __props;
|
|
74
|
+
const emit = __emit;
|
|
75
|
+
const bem = createBem("segmented");
|
|
76
|
+
const formItemContext = useFormItemContext();
|
|
77
|
+
const innerValue = ref(props.modelValue);
|
|
78
|
+
watch(
|
|
79
|
+
() => props.modelValue,
|
|
80
|
+
() => {
|
|
81
|
+
innerValue.value = props.modelValue;
|
|
82
|
+
if (props.validateEvent) {
|
|
83
|
+
formItemContext?.onChange();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
const fieldKeys = computed(() => {
|
|
88
|
+
return Object.assign({}, defaultOptionKeys, props.optionKeys);
|
|
89
|
+
});
|
|
90
|
+
const convertedOptions = computed(() => {
|
|
91
|
+
return (props.options || []).map((option) => {
|
|
92
|
+
return isPrimitive(option) ? {
|
|
93
|
+
label: option,
|
|
94
|
+
value: option
|
|
95
|
+
} : {
|
|
96
|
+
label: option[fieldKeys.value.label],
|
|
97
|
+
value: option[fieldKeys.value.value],
|
|
98
|
+
disabled: option[fieldKeys.value.disabled],
|
|
99
|
+
icon: option.icon,
|
|
100
|
+
iconFamily: option.iconFamily,
|
|
101
|
+
iconSize: option.iconSize
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
const currentIndex = computed(() => {
|
|
106
|
+
return convertedOptions.value.findIndex(
|
|
107
|
+
(option) => option.value === innerValue.value
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
const optionsCount = computed(() => convertedOptions.value.length);
|
|
111
|
+
const toggle = (value) => {
|
|
112
|
+
if (value !== innerValue.value) {
|
|
113
|
+
innerValue.value = value;
|
|
114
|
+
emit("update:model-value", value);
|
|
115
|
+
emit("change", value);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
provide(
|
|
119
|
+
segmentedContextSymbol,
|
|
120
|
+
reactive({
|
|
121
|
+
disabled: toRef(() => props.disabled),
|
|
122
|
+
readonly: toRef(() => props.readonly),
|
|
123
|
+
size: toRef(() => props.size),
|
|
124
|
+
shape: toRef(() => props.shape),
|
|
125
|
+
value: innerValue,
|
|
126
|
+
toggle
|
|
127
|
+
})
|
|
128
|
+
);
|
|
129
|
+
__expose({});
|
|
130
|
+
const segmentedClass = computed(() => {
|
|
131
|
+
return classNames(
|
|
132
|
+
bem.b(),
|
|
133
|
+
bem.m(props.size),
|
|
134
|
+
bem.m(props.direction),
|
|
135
|
+
bem.m(props.shape),
|
|
136
|
+
props.rootClass
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
const segmentedStyle = computed(() => {
|
|
140
|
+
return stringifyStyle(props.rootStyle);
|
|
141
|
+
});
|
|
142
|
+
const groupClass = computed(() => {
|
|
143
|
+
return classNames(bem.e("group"));
|
|
144
|
+
});
|
|
145
|
+
const pointerClass = computed(() => {
|
|
146
|
+
return classNames(bem.e("pointer"));
|
|
147
|
+
});
|
|
148
|
+
const pointerStyle = computed(() => {
|
|
149
|
+
const isHorizontal = props.direction === "horizontal";
|
|
150
|
+
return {
|
|
151
|
+
[isHorizontal ? "width" : "height"]: 1 / optionsCount.value * 100 + "%",
|
|
152
|
+
transform: `translate${isHorizontal ? "X" : "Y"}(${currentIndex.value * 100}%)`
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
const __returned__ = { props, emit, bem, formItemContext, innerValue, fieldKeys, convertedOptions, currentIndex, optionsCount, toggle, segmentedClass, segmentedStyle, groupClass, pointerClass, pointerStyle, SarSegmentedItem };
|
|
156
|
+
return __returned__;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<style lang="scss">
|
|
162
|
+
@import './index.scss';
|
|
163
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// #variables
|
|
2
|
+
page,
|
|
3
|
+
.sar-portal {
|
|
4
|
+
--sar-segmented-min-height: 64rpx;
|
|
5
|
+
--sar-segmented-large-min-height: 80rpx;
|
|
6
|
+
--sar-segmented-small-min-height: 48rpx;
|
|
7
|
+
--sar-segmented-padding: 2px;
|
|
8
|
+
--sar-segmented-font-size: var(--sar-text-base);
|
|
9
|
+
--sar-segmented-bg: var(--sar-secondary-bg);
|
|
10
|
+
--sar-segmented-border-radius: var(--sar-rounded);
|
|
11
|
+
--sar-segmented-pointer-bg: var(--sar-emphasis-bg);
|
|
12
|
+
--sar-segmented-pointer-duration: var(--sar-duration);
|
|
13
|
+
--sar-segmented-pointer-box-shadow: var(--sar-shadow-sm);
|
|
14
|
+
--sar-segmented-item-padding: 24rpx;
|
|
15
|
+
--sar-segmented-item-small-padding: 16rpx;
|
|
16
|
+
--sar-segmented-item-color: var(--sar-secondary-color);
|
|
17
|
+
--sar-segmented-item-active-bg: var(--sar-active-deep-bg);
|
|
18
|
+
--sar-segmented-item-active-color: var(--sar-emphasis-color);
|
|
19
|
+
--sar-segmented-item-label-margin-left: 12rpx;
|
|
20
|
+
}
|
|
21
|
+
// #endvariables
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type StyleValue } from 'vue';
|
|
2
|
+
export interface SegmentedItemProps {
|
|
3
|
+
rootStyle?: StyleValue;
|
|
4
|
+
rootClass?: string;
|
|
5
|
+
label?: string | number;
|
|
6
|
+
value?: string | number | boolean;
|
|
7
|
+
icon?: string;
|
|
8
|
+
iconFamily?: string;
|
|
9
|
+
iconSize?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
readonly?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const defaultSegmentedItemProps: {};
|
|
14
|
+
export interface SegmentedItemSlots {
|
|
15
|
+
default?(props: Record<string, never>): any;
|
|
16
|
+
}
|
|
17
|
+
export interface SegmentedItemEmits {
|
|
18
|
+
(e: 'click', event: any): void;
|
|
19
|
+
}
|
|
20
|
+
export interface SegmentedItemExpose {
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const defaultSegmentedItemProps = {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { SegmentedItemProps, SegmentedItemSlots, SegmentedItemEmits, SegmentedItemExpose, } from './common';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@use '../style/base' as *;
|
|
2
|
+
|
|
3
|
+
@include bem(segmented-item) {
|
|
4
|
+
@include b() {
|
|
5
|
+
@include universal;
|
|
6
|
+
flex-direction: row;
|
|
7
|
+
flex: 1;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
align-items: center;
|
|
10
|
+
min-width: 0;
|
|
11
|
+
min-height: calc(
|
|
12
|
+
var(--sar-segmented-min-height) - var(--sar-segmented-padding) * 2
|
|
13
|
+
);
|
|
14
|
+
padding: 0 var(--sar-segmented-item-padding);
|
|
15
|
+
border-radius: calc(var(--sar-segmented-border-radius) - 4rpx);
|
|
16
|
+
color: var(--sar-segmented-item-color);
|
|
17
|
+
|
|
18
|
+
@include m(small) {
|
|
19
|
+
min-height: calc(
|
|
20
|
+
var(--sar-segmented-small-min-height) - var(--sar-segmented-padding) * 2
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@include m(large) {
|
|
25
|
+
min-height: calc(
|
|
26
|
+
var(--sar-segmented-large-min-height) - var(--sar-segmented-padding) * 2
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@include m(round) {
|
|
31
|
+
border-radius: var(--sar-rounded-full);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@include m(with-icon) {
|
|
35
|
+
@include e(label) {
|
|
36
|
+
margin-left: var(--sar-segmented-item-label-margin-left);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@include m-not(disabled, readonly, selected) {
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
|
|
43
|
+
&:active {
|
|
44
|
+
background-color: var(--sar-segmented-item-active-bg);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@include m(selected) {
|
|
49
|
+
color: var(--sar-segmented-item-active-color);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@include m(disabled) {
|
|
53
|
+
@include disabled-text;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@include e(label) {
|
|
58
|
+
@include ellipsis;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type SegmentedItemProps, type SegmentedItemSlots } from './common';
|
|
2
|
+
declare function __VLS_template(): Readonly<SegmentedItemSlots> & SegmentedItemSlots;
|
|
3
|
+
declare const __VLS_component: import("vue").DefineComponent<SegmentedItemProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
4
|
+
click: (event: any) => any;
|
|
5
|
+
}, string, import("vue").PublicProps, Readonly<SegmentedItemProps> & Readonly<{
|
|
6
|
+
onClick?: ((event: any) => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
|
|
9
|
+
export default _default;
|
|
10
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
11
|
+
new (): {
|
|
12
|
+
$slots: S;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view
|
|
3
|
+
:class="segmentedItemClass"
|
|
4
|
+
:style="segmentedItemStyle"
|
|
5
|
+
@click="onClick"
|
|
6
|
+
>
|
|
7
|
+
<slot>
|
|
8
|
+
<view :class="bem.e('icon')">
|
|
9
|
+
<sar-icon :name="icon" :family="iconFamily" :size="iconSize" />
|
|
10
|
+
</view>
|
|
11
|
+
<view v-if="label" :class="bem.e('label')">{{ label }}</view>
|
|
12
|
+
</slot>
|
|
13
|
+
</view>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script>
|
|
17
|
+
import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
|
|
18
|
+
import { computed, inject } from "vue";
|
|
19
|
+
import { classNames, stringifyStyle, createBem } from "../../utils";
|
|
20
|
+
import {
|
|
21
|
+
defaultSegmentedItemProps
|
|
22
|
+
} from "./common";
|
|
23
|
+
import {
|
|
24
|
+
segmentedContextSymbol
|
|
25
|
+
} from "../segmented/common";
|
|
26
|
+
import SarIcon from "../icon/icon.vue";
|
|
27
|
+
import { useFormContext } from "../form";
|
|
28
|
+
export default _defineComponent({
|
|
29
|
+
components: {
|
|
30
|
+
SarIcon,
|
|
31
|
+
},
|
|
32
|
+
...{
|
|
33
|
+
options: {
|
|
34
|
+
virtualHost: true,
|
|
35
|
+
styleIsolation: "shared"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
__name: "segmented-item",
|
|
39
|
+
props: _mergeDefaults({
|
|
40
|
+
rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
|
|
41
|
+
rootClass: { type: String, required: false },
|
|
42
|
+
label: { type: [String, Number], required: false },
|
|
43
|
+
value: { type: [String, Number, Boolean], required: false },
|
|
44
|
+
icon: { type: String, required: false },
|
|
45
|
+
iconFamily: { type: String, required: false },
|
|
46
|
+
iconSize: { type: String, required: false },
|
|
47
|
+
disabled: { type: Boolean, required: false },
|
|
48
|
+
readonly: { type: Boolean, required: false }
|
|
49
|
+
}, defaultSegmentedItemProps),
|
|
50
|
+
emits: ["click"],
|
|
51
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
52
|
+
const props = __props;
|
|
53
|
+
const emit = __emit;
|
|
54
|
+
const bem = createBem("segmented-item");
|
|
55
|
+
const context = inject(segmentedContextSymbol, null);
|
|
56
|
+
if (!context) {
|
|
57
|
+
throw new Error("SegmentedItem must be included in Segmented.");
|
|
58
|
+
}
|
|
59
|
+
const formContext = useFormContext();
|
|
60
|
+
const isSelected = computed(() => {
|
|
61
|
+
return context.value === props.value;
|
|
62
|
+
});
|
|
63
|
+
const isDisabled = computed(() => {
|
|
64
|
+
return formContext?.disabled || context?.disabled || props.disabled;
|
|
65
|
+
});
|
|
66
|
+
const isReadonly = computed(() => {
|
|
67
|
+
return formContext?.readonly || context?.readonly || props.readonly;
|
|
68
|
+
});
|
|
69
|
+
const onClick = (event) => {
|
|
70
|
+
if (!isDisabled.value && !isReadonly.value) {
|
|
71
|
+
context.toggle(props.value);
|
|
72
|
+
}
|
|
73
|
+
emit("click", event);
|
|
74
|
+
};
|
|
75
|
+
__expose({});
|
|
76
|
+
const segmentedItemClass = computed(() => {
|
|
77
|
+
return classNames(
|
|
78
|
+
bem.b(),
|
|
79
|
+
bem.m("selected", isSelected.value),
|
|
80
|
+
bem.m("disabled", isDisabled.value),
|
|
81
|
+
bem.m("readonly", isReadonly.value),
|
|
82
|
+
bem.m("with-icon", !!props.icon),
|
|
83
|
+
bem.m(context.size),
|
|
84
|
+
bem.m(context.shape),
|
|
85
|
+
props.rootClass
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
const segmentedItemStyle = computed(() => {
|
|
89
|
+
return stringifyStyle(props.rootStyle);
|
|
90
|
+
});
|
|
91
|
+
const __returned__ = { props, emit, bem, context, formContext, isSelected, isDisabled, isReadonly, onClick, segmentedItemClass, segmentedItemStyle, SarIcon };
|
|
92
|
+
return __returned__;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<style lang="scss">
|
|
98
|
+
@import './index.scss';
|
|
99
|
+
</style>
|
|
@@ -121,10 +121,11 @@ import Tree from 'sard-uniapp/components/tree/tree.vue'
|
|
|
121
121
|
|
|
122
122
|
### TreeEmits
|
|
123
123
|
|
|
124
|
-
| 事件 | 描述 | 类型
|
|
125
|
-
| ------------------------------- | ---------------------- |
|
|
126
|
-
| update:current <sup>1.17+</sup> | 选择节点后触发(单选) | (key: string \| number, node: TreeStateNode) => void
|
|
127
|
-
| select <sup>1.17+</sup> | 选择节点后触发(单选) | (key: string \| number, node: TreeStateNode) => void
|
|
124
|
+
| 事件 | 描述 | 类型 |
|
|
125
|
+
| ------------------------------- | ---------------------- | -------------------------------------------------------- |
|
|
126
|
+
| update:current <sup>1.17+</sup> | 选择节点后触发(单选) | (key: string \| number, node: TreeStateNode) => void |
|
|
127
|
+
| select <sup>1.17+</sup> | 选择节点后触发(单选) | (key: string \| number, node: TreeStateNode) => void |
|
|
128
|
+
| check <sup>1.24+</sup> | 点击树节点复选框时触发 | (event: {checked: boolean; node: TreeStateNode}) => void |
|
|
128
129
|
|
|
129
130
|
### TreeExpose
|
|
130
131
|
|
|
@@ -63,6 +63,10 @@ export declare const defaultTreeProps: () => {
|
|
|
63
63
|
export interface TreeEmits {
|
|
64
64
|
(e: 'update:current', key: string | number, node: TreeStateNode): void;
|
|
65
65
|
(e: 'select', key: string | number, node: TreeStateNode): void;
|
|
66
|
+
(e: 'check', event: {
|
|
67
|
+
checked: boolean;
|
|
68
|
+
node: TreeStateNode;
|
|
69
|
+
}): void;
|
|
66
70
|
}
|
|
67
71
|
export interface TreeExpose {
|
|
68
72
|
setExpanded: (key: string | number, expanded: boolean) => void;
|
|
@@ -93,7 +97,7 @@ export interface TreeContext {
|
|
|
93
97
|
treeData: TreeStateNode[];
|
|
94
98
|
setExpandedByNode: (node: TreeStateNode, expanded: boolean) => void;
|
|
95
99
|
toggleExpandedByNode: (node: TreeStateNode) => void;
|
|
96
|
-
|
|
100
|
+
toggleCheck: (node: TreeStateNode, checked: boolean) => void;
|
|
97
101
|
levelup: (node: TreeStateNode) => void;
|
|
98
102
|
leveldown: (node: TreeStateNode) => void;
|
|
99
103
|
edit: (node: TreeStateNode, getEditRect: () => Promise<NodeRect>) => void;
|
|
@@ -14,9 +14,17 @@ declare const _default: import("vue").DefineComponent<TreeProps, {
|
|
|
14
14
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
15
15
|
select: (key: string | number, node: TreeStateNode) => any;
|
|
16
16
|
"update:current": (key: string | number, node: TreeStateNode) => any;
|
|
17
|
+
check: (event: {
|
|
18
|
+
checked: boolean;
|
|
19
|
+
node: TreeStateNode;
|
|
20
|
+
}) => any;
|
|
17
21
|
}, string, import("vue").PublicProps, Readonly<TreeProps> & Readonly<{
|
|
18
22
|
onSelect?: ((key: string | number, node: TreeStateNode) => any) | undefined;
|
|
19
23
|
"onUpdate:current"?: ((key: string | number, node: TreeStateNode) => any) | undefined;
|
|
24
|
+
onCheck?: ((event: {
|
|
25
|
+
checked: boolean;
|
|
26
|
+
node: TreeStateNode;
|
|
27
|
+
}) => any) | undefined;
|
|
20
28
|
}>, {
|
|
21
29
|
data: TreeNode[];
|
|
22
30
|
accordion: boolean;
|
package/components/tree/tree.vue
CHANGED
|
@@ -75,6 +75,7 @@ import { recurAncestor, recurDescendant, recurNodes } from "./utils";
|
|
|
75
75
|
* @property {(value: string, node: TreeStateNode) => boolean} filterMethod 自定义过滤方法,默认值:-。
|
|
76
76
|
* @event {(key: string | number, node: TreeStateNode) => void} update 选择节点后触发(单选)
|
|
77
77
|
* @event {(key: string | number, node: TreeStateNode) => void} select 选择节点后触发(单选)
|
|
78
|
+
* @event {(event: {checked: boolean; node: TreeStateNode}) => void} check 点击树节点复选框时触发
|
|
78
79
|
*/
|
|
79
80
|
export default _defineComponent({
|
|
80
81
|
components: {
|
|
@@ -110,7 +111,7 @@ export default _defineComponent({
|
|
|
110
111
|
filterMode: { type: String, required: false },
|
|
111
112
|
filterMethod: { type: Function, required: false }
|
|
112
113
|
}, defaultTreeProps()),
|
|
113
|
-
emits: ["update:current", "select"],
|
|
114
|
+
emits: ["update:current", "select", "check"],
|
|
114
115
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
115
116
|
const props = __props;
|
|
116
117
|
const emit = __emit;
|
|
@@ -399,6 +400,13 @@ export default _defineComponent({
|
|
|
399
400
|
recur(treeData.value);
|
|
400
401
|
totalLevel.value = count;
|
|
401
402
|
};
|
|
403
|
+
const toggleCheck = (node, checked) => {
|
|
404
|
+
setCheckedByNode(node, checked);
|
|
405
|
+
emit("check", {
|
|
406
|
+
checked,
|
|
407
|
+
node
|
|
408
|
+
});
|
|
409
|
+
};
|
|
402
410
|
watch(
|
|
403
411
|
() => props.data,
|
|
404
412
|
() => {
|
|
@@ -559,6 +567,7 @@ export default _defineComponent({
|
|
|
559
567
|
levelup,
|
|
560
568
|
leveldown,
|
|
561
569
|
drop,
|
|
570
|
+
toggleCheck,
|
|
562
571
|
edit,
|
|
563
572
|
currentKey,
|
|
564
573
|
singleSelect
|
|
@@ -592,7 +601,7 @@ export default _defineComponent({
|
|
|
592
601
|
return treeMap;
|
|
593
602
|
}, set treeMap(v) {
|
|
594
603
|
treeMap = v;
|
|
595
|
-
}, totalLevel, recurRawNode, setExpandedByNode, toggleExpandedByNode, setExpanded, toggleExpanded, setExpandedKeys, getExpandedKeys, setCheckedByNode, updateAncestorChecked, setCheckedKeys, setChecked, getCheckedKeys, getHalfCheckedKeys, prepend, append, appendRoot, before, after, remove, levelup, leveldown, drop, addRootNode, getCleanTreeData, setRenderPosition, popoverOptions, popover, get currentEditNode() {
|
|
604
|
+
}, totalLevel, recurRawNode, setExpandedByNode, toggleExpandedByNode, setExpanded, toggleExpanded, setExpandedKeys, getExpandedKeys, setCheckedByNode, updateAncestorChecked, setCheckedKeys, setChecked, getCheckedKeys, getHalfCheckedKeys, prepend, append, appendRoot, before, after, remove, levelup, leveldown, drop, addRootNode, getCleanTreeData, setRenderPosition, toggleCheck, popoverOptions, popover, get currentEditNode() {
|
|
596
605
|
return currentEditNode;
|
|
597
606
|
}, set currentEditNode(v) {
|
|
598
607
|
currentEditNode = v;
|
|
@@ -299,7 +299,7 @@ export default _defineComponent({
|
|
|
299
299
|
const [onSelectionTouchStart, onSelectionTouchEnd] = useSimulatedClick(() => {
|
|
300
300
|
if (!props.node.disabled) {
|
|
301
301
|
if (treeContext.selectable) {
|
|
302
|
-
treeContext.
|
|
302
|
+
treeContext.toggleCheck(props.node, !props.node.checked);
|
|
303
303
|
}
|
|
304
304
|
if (canSingleSelectable.value) {
|
|
305
305
|
treeContext.singleSelect(props.node);
|
|
@@ -29,6 +29,20 @@ import Upload from 'sard-uniapp/components/upload/upload.vue'
|
|
|
29
29
|
|
|
30
30
|
@code('${DEMO_PATH}/upload/demo/Video.vue')
|
|
31
31
|
|
|
32
|
+
### 同时上传图片和视频 <sup>1.23.5+</sup>
|
|
33
|
+
|
|
34
|
+
@info
|
|
35
|
+
|
|
36
|
+
仅 app 和微信支持。
|
|
37
|
+
|
|
38
|
+
不支持的端,默认回退为选择图片。
|
|
39
|
+
|
|
40
|
+
@endinfo
|
|
41
|
+
|
|
42
|
+
设置 `:accept="['image', 'video']"` 允许同时选择图片和视频。
|
|
43
|
+
|
|
44
|
+
@code('${DEMO_PATH}/upload/demo/Mix.vue')
|
|
45
|
+
|
|
32
46
|
### 限定上传数量
|
|
33
47
|
|
|
34
48
|
通过 `maxCount` 属性可以限制上传文件的数量,上传数量达到限制后,会自动隐藏选择区域。
|
|
@@ -99,7 +113,7 @@ import Upload from 'sard-uniapp/components/upload/upload.vue'
|
|
|
99
113
|
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------------------- |
|
|
100
114
|
| root-class | 组件根元素类名 | string | - |
|
|
101
115
|
| root-style | 组件根元素样式 | StyleValue | - |
|
|
102
|
-
| accept | 允许上传的文件类型 | 'image' \| 'video'
|
|
116
|
+
| accept | 允许上传的文件类型 | 'image' \| 'video' \| ('image' \| 'video' )[] | 'image' |
|
|
103
117
|
| multiple | 是否开启图片多选 | boolean | false |
|
|
104
118
|
| source-type | 文件选择来源 | ('album' \| 'camera')[] | ['album', 'camera'] |
|
|
105
119
|
| size-type | 所选的图片的尺寸 | ('original' \| 'compressed')[] | ['original', 'compressed'] |
|
|
@@ -26,7 +26,7 @@ export interface UploadSelectOptions {
|
|
|
26
26
|
export interface UploadProps {
|
|
27
27
|
rootStyle?: StyleValue;
|
|
28
28
|
rootClass?: string;
|
|
29
|
-
accept?: 'image' | 'video';
|
|
29
|
+
accept?: 'image' | 'video' | ('image' | 'video')[];
|
|
30
30
|
multiple?: boolean;
|
|
31
31
|
sourceType?: ('album' | 'camera')[];
|
|
32
32
|
sizeType?: ('original' | 'compressed')[];
|
|
@@ -45,7 +45,7 @@ export interface UploadProps {
|
|
|
45
45
|
beforeRemove?: (index: number, fileItem: UploadFileItem) => boolean | Promise<void>;
|
|
46
46
|
validateEvent?: boolean;
|
|
47
47
|
}
|
|
48
|
-
export declare const defaultUploadProps: Omit<typeof defaultConfig.upload, "sourceType" | "sizeType">;
|
|
48
|
+
export declare const defaultUploadProps: Omit<typeof defaultConfig.upload, "sourceType" | "sizeType" | "accept">;
|
|
49
49
|
export interface UploadSlots {
|
|
50
50
|
default?(props: {
|
|
51
51
|
list: UploadFileItem[];
|
|
@@ -11,7 +11,6 @@ declare const __VLS_component: import("vue").DefineComponent<UploadProps, {}, {}
|
|
|
11
11
|
onRemove?: ((index: number, item: UploadFileItem) => any) | undefined;
|
|
12
12
|
"onItem-click"?: ((item: UploadFileItem, index: number) => any) | undefined;
|
|
13
13
|
}>, {
|
|
14
|
-
accept: "image" | "video";
|
|
15
14
|
validateEvent: boolean;
|
|
16
15
|
maxDuration: number;
|
|
17
16
|
maxCount: number;
|