@opentiny/vue-renderless 3.28.2 → 3.30.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/alert/vue.js +4 -1
- package/anchor/index.js +11 -1
- package/anchor/vue.js +2 -2
- package/base-select/index.js +6 -3
- package/base-select/vue.js +1 -1
- package/calendar-view/index.js +44 -2
- package/calendar-view/vue.js +6 -0
- package/date-range/index.js +1 -1
- package/dialog-box/vue.js +4 -1
- package/dialog-select/index.js +1 -1
- package/drawer/index.js +13 -1
- package/drawer/vue.js +13 -3
- package/fluent-editor/index.js +142 -10
- package/fluent-editor/vue.js +30 -8
- package/form-item/index.js +1 -1
- package/form-item/vue.js +11 -1
- package/grid-select/index.js +3 -3
- package/guide/index.js +17 -11
- package/guide/vue.js +2 -1
- package/input/vue.js +3 -2
- package/modal/index.js +11 -11
- package/modal/vue.js +3 -0
- package/notify/vue.js +4 -1
- package/package.json +3 -3
- package/picker/vue.js +3 -2
- package/qr-code/vue.js +3 -1
- package/rate/index.js +5 -4
- package/rate/vue.js +1 -1
- package/rich-text/index.js +91 -2
- package/rich-text/vue.js +11 -2
- package/search/vue.js +6 -1
- package/select/index.js +11 -3
- package/select/vue.js +5 -4
- package/statistic/index.js +48 -1
- package/statistic/vue.js +31 -11
- package/tabs-mf/index.js +10 -2
- package/tag-group/index.js +3 -0
- package/tag-input/index.js +91 -0
- package/tag-input/vue.js +72 -0
- package/time/index.js +22 -0
- package/time/vue.js +14 -2
- package/time-spinner/index.js +2 -2
- package/tree-select/index.js +49 -14
- package/types/action-menu.type.d.ts +4 -0
- package/types/alert.type.d.ts +2 -0
- package/types/anchor.type.d.ts +1 -1
- package/types/button-group.type.d.ts +5 -0
- package/types/date-picker.type.d.ts +1 -1
- package/types/dialog-box.type.d.ts +2 -0
- package/types/drawer.type.d.ts +7 -1
- package/types/{dropdown-item.type-b3ced3ce.d.ts → dropdown-item.type-f83b014f.d.ts} +1 -1
- package/types/dropdown-item.type.d.ts +1 -1
- package/types/dropdown-menu.type.d.ts +1 -1
- package/types/form-item.type.d.ts +1 -1
- package/types/{form.type-a54e1c06.d.ts → form.type-e0db2f7c.d.ts} +9 -0
- package/types/form.type.d.ts +1 -1
- package/types/modal.type.d.ts +2 -0
- package/types/popeditor.type.d.ts +2 -2
- package/types/rate.type.d.ts +5 -2
- package/types/search.type.d.ts +1 -0
- package/types/statistic.type.d.ts +17 -1
- package/types/tag-input.type.d.ts +113 -0
- package/types/tree-menu.type.d.ts +1 -1
- package/user/index.js +5 -5
package/form-item/vue.js
CHANGED
|
@@ -32,9 +32,11 @@ import {
|
|
|
32
32
|
handleMouseenter,
|
|
33
33
|
handleMouseleave
|
|
34
34
|
} from "./index";
|
|
35
|
+
import { nanoid } from "@opentiny/utils";
|
|
35
36
|
const api = [
|
|
36
37
|
"state",
|
|
37
38
|
"validate",
|
|
39
|
+
"validateOrigin",
|
|
38
40
|
"clearValidate",
|
|
39
41
|
"resetField",
|
|
40
42
|
"getRules",
|
|
@@ -58,6 +60,9 @@ const initState = ({
|
|
|
58
60
|
inject,
|
|
59
61
|
props
|
|
60
62
|
}) => {
|
|
63
|
+
const uniqueId = nanoid.api.nanoid(8);
|
|
64
|
+
const errorId = `tiny-form-item-error-${uniqueId}`;
|
|
65
|
+
const labelId = `tiny-form-item-label-${uniqueId}`;
|
|
61
66
|
const state = reactive({
|
|
62
67
|
mode,
|
|
63
68
|
validateState: "",
|
|
@@ -77,6 +82,9 @@ const initState = ({
|
|
|
77
82
|
showTooltip: false,
|
|
78
83
|
typeName: "",
|
|
79
84
|
formInstance: inject("form"),
|
|
85
|
+
// 无障碍支持:为错误信息和标签生成唯一 ID
|
|
86
|
+
errorId,
|
|
87
|
+
labelId,
|
|
80
88
|
labelFor: computed(() => props.for || props.prop || ""),
|
|
81
89
|
labelStyle: computed(() => api2.computedLabelStyle()),
|
|
82
90
|
valueStyle: computed(() => api2.computedValueStyle()),
|
|
@@ -142,6 +150,7 @@ const initState = ({
|
|
|
142
150
|
return state;
|
|
143
151
|
};
|
|
144
152
|
const initApi = ({ api: api2, state, dispatch, broadcast, props, constants, vm, t, nextTick, slots }) => {
|
|
153
|
+
const validateOriginFunc = validate({ api: api2, props, state, t });
|
|
145
154
|
Object.assign(api2, {
|
|
146
155
|
state,
|
|
147
156
|
dispatch,
|
|
@@ -170,7 +179,8 @@ const initApi = ({ api: api2, state, dispatch, broadcast, props, constants, vm,
|
|
|
170
179
|
onFieldBlur: onFieldBlur(api2),
|
|
171
180
|
onFieldChange: onFieldChange({ api: api2, state }),
|
|
172
181
|
addValidateEvents: addValidateEvents({ api: api2, vm, props, state }),
|
|
173
|
-
|
|
182
|
+
validateOrigin: validateOriginFunc,
|
|
183
|
+
validate: wrapValidate({ validateFunc: validateOriginFunc, props }),
|
|
174
184
|
getDisplayedValue: getDisplayedValue({ state }),
|
|
175
185
|
clearDisplayedValue: clearDisplayedValue({ state }),
|
|
176
186
|
handleLabelMouseenter: handleLabelMouseenter({ props, state, slots }),
|
package/grid-select/index.js
CHANGED
|
@@ -31,7 +31,7 @@ const syncGridSelection = ({ props, vm, state, nextTick }) => () => {
|
|
|
31
31
|
const fullData = (tableData == null ? void 0 : tableData.fullData) || [];
|
|
32
32
|
if (props.multiple) {
|
|
33
33
|
if (Array.isArray(state.modelValue) && state.modelValue.length > 0) {
|
|
34
|
-
const rowsToSelect = fullData.filter((row) => state.modelValue.
|
|
34
|
+
const rowsToSelect = fullData.filter((row) => state.modelValue.includes(row[props.valueField]));
|
|
35
35
|
vm.$refs.gridRef.clearSelection();
|
|
36
36
|
if (rowsToSelect.length > 0) {
|
|
37
37
|
vm.$refs.gridRef.setSelection(rowsToSelect, true);
|
|
@@ -93,7 +93,7 @@ const filter = ({ props, state, vm }) => async (value) => {
|
|
|
93
93
|
if (multiple) {
|
|
94
94
|
const selectedIds = Array.isArray(state.selected) ? state.selected.map((sel) => sel[valueField]) : [];
|
|
95
95
|
vm.$refs.gridRef.clearSelection();
|
|
96
|
-
const selectedRows = data.filter((row) => selectedIds.
|
|
96
|
+
const selectedRows = data.filter((row) => selectedIds.includes(row[valueField]));
|
|
97
97
|
if (selectedRows.length > 0) {
|
|
98
98
|
vm.$refs.gridRef.setSelection(selectedRows, true);
|
|
99
99
|
}
|
|
@@ -441,7 +441,7 @@ const selectChange = ({ props, vm, emit, state, nextTick }) => ({ $table, select
|
|
|
441
441
|
try {
|
|
442
442
|
const tableData = vm.$refs.gridRef.getTableData();
|
|
443
443
|
const fullData = (tableData == null ? void 0 : tableData.fullData) || [];
|
|
444
|
-
const rowsToSelect = fullData.filter((row2) => currentValue.
|
|
444
|
+
const rowsToSelect = fullData.filter((row2) => currentValue.includes(row2[valueField]));
|
|
445
445
|
vm.$refs.gridRef.clearSelection();
|
|
446
446
|
if (rowsToSelect.length > 0) {
|
|
447
447
|
vm.$refs.gridRef.setSelection(rowsToSelect, true);
|
package/guide/index.js
CHANGED
|
@@ -103,7 +103,7 @@ const itemStep = (item, state, deepCopy, index, Shepherd) => {
|
|
|
103
103
|
hightBox: item.hightBox || null,
|
|
104
104
|
buttons: deepCopy[index].button,
|
|
105
105
|
cancelIcon: {
|
|
106
|
-
enabled:
|
|
106
|
+
enabled: state.showClose
|
|
107
107
|
},
|
|
108
108
|
id: item.id,
|
|
109
109
|
scrollTo: true,
|
|
@@ -122,16 +122,22 @@ const itemStep = (item, state, deepCopy, index, Shepherd) => {
|
|
|
122
122
|
const currentStepElement = currentStep && currentStep.getElement();
|
|
123
123
|
const footer = currentStepElement && currentStepElement.querySelector(".shepherd-footer");
|
|
124
124
|
const cancelIcon = currentStepElement && currentStepElement.querySelector(".shepherd-header .shepherd-cancel-icon span");
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
if (cancelIcon) {
|
|
126
|
+
if (state.showClose) {
|
|
127
|
+
const cloesIcon = `<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
128
|
+
<desc fill="none">
|
|
129
|
+
Created with Pixso.
|
|
130
|
+
</desc>
|
|
131
|
+
<defs fill="none" />
|
|
132
|
+
<g>
|
|
133
|
+
<path id="path" d="M12.49 3.3C12.66 3.47 12.66 3.74 12.54 3.92L8.58 7.89L12.49 11.77C12.7 11.96 12.72 12.25 12.54 12.48C12.37 12.67 12.05 12.72 11.83 12.54L7.88 8.58L4 12.49C3.82 12.66 3.5 12.67 3.32 12.5C3.13 12.33 3.08 12.05 3.24 11.83L7.17 7.89L3.29 4C3.12 3.79 3.13 3.48 3.33 3.29C3.5 3.15 3.75 3.13 3.91 3.24L7.88 7.17L11.78 3.3C11.96 3.08 12.29 3.08 12.49 3.3Z" fill-opacity="1.000000" fill-rule="evenodd"/>
|
|
134
|
+
</g>
|
|
135
|
+
</svg>`;
|
|
136
|
+
cancelIcon.innerHTML = cloesIcon;
|
|
137
|
+
} else {
|
|
138
|
+
cancelIcon.parentElement.style.display = "none";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
135
141
|
const progress = document.createElement("span");
|
|
136
142
|
progress.classList.add("progress-style");
|
|
137
143
|
progress.innerText = `${Shepherd.activeTour && Shepherd.activeTour.steps.indexOf(currentStep) + 1}/${Shepherd.activeTour && Shepherd.activeTour.steps.length}`;
|
package/guide/vue.js
CHANGED
|
@@ -17,7 +17,8 @@ const renderless = (props, { reactive, onMounted, onBeforeUnmount, watch }, { de
|
|
|
17
17
|
modalOverlayOpeningPadding: props.modalOverlayOpeningPadding,
|
|
18
18
|
modalOverlayOpeningRadius: props.modalOverlayOpeningRadius,
|
|
19
19
|
arrow: props.arrow,
|
|
20
|
-
lightClass: props.lightClass
|
|
20
|
+
lightClass: props.lightClass,
|
|
21
|
+
showClose: props.showClose
|
|
21
22
|
});
|
|
22
23
|
let baseApi = {
|
|
23
24
|
state,
|
package/input/vue.js
CHANGED
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./index";
|
|
42
42
|
import useStorageBox from "../tall-storage/vue-storage-box";
|
|
43
43
|
import { on, off } from "@opentiny/utils";
|
|
44
|
-
import {
|
|
44
|
+
import { debounceBoth } from "@opentiny/utils";
|
|
45
45
|
const api = [
|
|
46
46
|
"blur",
|
|
47
47
|
"showBox",
|
|
@@ -222,7 +222,8 @@ const mergeApi = ({
|
|
|
222
222
|
}),
|
|
223
223
|
handleFocus: handleFocus({ api: api2, emit, state }),
|
|
224
224
|
handleInput: handleInput({ api: api2, emit, nextTick, state }),
|
|
225
|
-
resizeTextarea:
|
|
225
|
+
resizeTextarea: debounceBoth(200, resizeTextarea({ api: api2, parent, vm, state, props })),
|
|
226
|
+
// 抖动的首尾都要执行一次
|
|
226
227
|
updateIconOffset: updateIconOffset(api2),
|
|
227
228
|
calcTextareaHeight: calcTextareaHeight({
|
|
228
229
|
api: api2,
|
package/modal/index.js
CHANGED
|
@@ -87,12 +87,12 @@ const mouseEnterEvent = (state) => () => {
|
|
|
87
87
|
};
|
|
88
88
|
const mouseLeaveEvent = ({ api, props, state }) => () => {
|
|
89
89
|
api.addMsgQueue();
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
const duration = parseFloat(props.duration);
|
|
91
|
+
if (duration > 0) {
|
|
92
|
+
state.timer = window.setTimeout(() => {
|
|
92
93
|
api.close("close");
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
);
|
|
94
|
+
}, duration);
|
|
95
|
+
}
|
|
96
96
|
};
|
|
97
97
|
const updateZindex = ({ state, props }) => () => {
|
|
98
98
|
state.modalZindex = props.zIndex || PopupManager.nextZIndex();
|
|
@@ -157,12 +157,12 @@ const open = ({
|
|
|
157
157
|
}, 10);
|
|
158
158
|
if (state.isMsg) {
|
|
159
159
|
api.addMsgQueue();
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
const duration = parseFloat(props.duration);
|
|
161
|
+
if (duration > 0) {
|
|
162
|
+
state.timer = window.setTimeout(() => {
|
|
162
163
|
api.close(params.type);
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
);
|
|
164
|
+
}, duration);
|
|
165
|
+
}
|
|
166
166
|
} else {
|
|
167
167
|
nextTick(() => {
|
|
168
168
|
if (!isMobileFirstMode) {
|
|
@@ -233,7 +233,7 @@ const close = ({ emit, parent, props, state }) => (type) => {
|
|
|
233
233
|
emit("update:modelValue", false);
|
|
234
234
|
emit("hide", params);
|
|
235
235
|
}
|
|
236
|
-
},
|
|
236
|
+
}, 400);
|
|
237
237
|
}
|
|
238
238
|
};
|
|
239
239
|
const handleGlobalKeydownEvent = (api) => (event) => {
|
package/modal/vue.js
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
hideScrollbar,
|
|
34
34
|
watchVisible
|
|
35
35
|
} from "./index";
|
|
36
|
+
import { nanoid } from "@opentiny/utils";
|
|
36
37
|
const api = [
|
|
37
38
|
"state",
|
|
38
39
|
"dragEvent",
|
|
@@ -59,6 +60,8 @@ const renderless = (props, { computed, onMounted, onBeforeUnmount, reactive, wat
|
|
|
59
60
|
const api2 = {};
|
|
60
61
|
const lockScrollClass = constants.SCROLL_LOCK_CLASS(mode);
|
|
61
62
|
const state = reactive({
|
|
63
|
+
titleId: "tiny-modal-title-" + nanoid.api.nanoid(8),
|
|
64
|
+
contentId: "tiny-modal-content-" + nanoid.api.nanoid(8),
|
|
62
65
|
emitter: emitter(),
|
|
63
66
|
visible: false,
|
|
64
67
|
contentVisible: false,
|
package/notify/vue.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
getPositionSide,
|
|
12
12
|
getZindex
|
|
13
13
|
} from "./index";
|
|
14
|
+
import { nanoid } from "@opentiny/utils";
|
|
14
15
|
const api = [
|
|
15
16
|
"state",
|
|
16
17
|
"clearTimer",
|
|
@@ -37,7 +38,9 @@ const renderless = (props, { computed, onBeforeUnmount, onMounted, reactive, wat
|
|
|
37
38
|
dangerouslyUseHTMLString: false,
|
|
38
39
|
positionStyle: computed(() => api2.getOffsetStyle(state)),
|
|
39
40
|
verticalProperty: computed(() => api2.getPositionSide(state)),
|
|
40
|
-
customClass: computed(() => props.customClass)
|
|
41
|
+
customClass: computed(() => props.customClass),
|
|
42
|
+
titleId: `tiny-notify-title-${nanoid.api.nanoid(8)}`,
|
|
43
|
+
contentId: `tiny-notify-content-${nanoid.api.nanoid(8)}`
|
|
41
44
|
});
|
|
42
45
|
Object.assign(api2, {
|
|
43
46
|
state,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/vue-renderless",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.30.0",
|
|
4
4
|
"description": "An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.",
|
|
5
5
|
"author": "OpenTiny Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
],
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@opentiny/utils": "~3.
|
|
29
|
-
"@opentiny/vue-hooks": "~3.
|
|
28
|
+
"@opentiny/utils": "~3.30.0",
|
|
29
|
+
"@opentiny/vue-hooks": "~3.30.0",
|
|
30
30
|
"color": "4.2.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
package/picker/vue.js
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
formatInputValue
|
|
60
60
|
} from "./index";
|
|
61
61
|
import { dateMobileToggle, timeMobileToggle, dateToTimeArray, timeArrayToDate, timeMobileConfirm } from "./mb";
|
|
62
|
-
import { DATEPICKER } from "@opentiny/utils";
|
|
62
|
+
import { DATEPICKER, nanoid } from "@opentiny/utils";
|
|
63
63
|
const api = [
|
|
64
64
|
"state",
|
|
65
65
|
"btnClick",
|
|
@@ -154,7 +154,8 @@ const initState = ({ api: api2, reactive, vm, computed, props, utils, parent, br
|
|
|
154
154
|
innerWidth: 0,
|
|
155
155
|
breakLine: computed(
|
|
156
156
|
() => (state.innerWidth < 230 && state.type === "daterange" || state.innerWidth < 335 && state.type === "datetimerange") && state.displayValue && state.displayValue[1]
|
|
157
|
-
)
|
|
157
|
+
),
|
|
158
|
+
ariaPanelId: "panel-" + nanoid.api.nanoid(8)
|
|
158
159
|
});
|
|
159
160
|
return state;
|
|
160
161
|
};
|
package/qr-code/vue.js
CHANGED
package/rate/index.js
CHANGED
|
@@ -52,7 +52,9 @@ const selectValue = ({ emit, props, state }) => (value) => {
|
|
|
52
52
|
if (props.disabled) {
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
-
if (props.
|
|
55
|
+
if (props.clearable && props.modelValue === value) {
|
|
56
|
+
value = 0;
|
|
57
|
+
} else if (props.allowHalf && state.pointerAtLeftHalf) {
|
|
56
58
|
value = state.currentValue;
|
|
57
59
|
}
|
|
58
60
|
emit("update:modelValue", value);
|
|
@@ -112,8 +114,7 @@ const showDecimalIcon = ({ props, state }) => (item) => {
|
|
|
112
114
|
const showWhenAllowHalf = props.allowHalf && state.pointerAtLeftHalf && item - 0.5 <= state.currentValue && item > state.currentValue;
|
|
113
115
|
return showWhenDisabled || showWhenAllowHalf;
|
|
114
116
|
};
|
|
115
|
-
const getIconStyle = ({
|
|
116
|
-
const isHalf = api.showDecimalIcon(item);
|
|
117
|
+
const getIconStyle = ({ props, state }) => (item) => {
|
|
117
118
|
const voidColor = props.disabled ? props.disabledVoidColor : props.voidColor;
|
|
118
119
|
if (props.radio) {
|
|
119
120
|
return {
|
|
@@ -122,7 +123,7 @@ const getIconStyle = ({ api, props, state }) => (item) => {
|
|
|
122
123
|
};
|
|
123
124
|
}
|
|
124
125
|
return {
|
|
125
|
-
fill:
|
|
126
|
+
fill: item <= state.currentValue ? state.activeColor : voidColor,
|
|
126
127
|
"font-size": props.size || "18px"
|
|
127
128
|
};
|
|
128
129
|
};
|
package/rate/vue.js
CHANGED
|
@@ -120,7 +120,7 @@ const renderless = (props, { computed, reactive, toRefs, watch, onMounted, onUnm
|
|
|
120
120
|
computedActiveColor: computedActiveColor(props),
|
|
121
121
|
computedActiveClass: computedActiveClass(props),
|
|
122
122
|
showDecimalIcon: showDecimalIcon({ props, state }),
|
|
123
|
-
getIconStyle: getIconStyle({
|
|
123
|
+
getIconStyle: getIconStyle({ props, state })
|
|
124
124
|
}, changeValue.api));
|
|
125
125
|
return api2;
|
|
126
126
|
};
|
package/rich-text/index.js
CHANGED
|
@@ -106,6 +106,26 @@ const initQuill = ({ api, emit, props, vm, service, state, Quill, ImageDrop, Ima
|
|
|
106
106
|
}
|
|
107
107
|
emit("ready", state.quill);
|
|
108
108
|
api.setToolbarTips();
|
|
109
|
+
api.setTooltipI18n();
|
|
110
|
+
state.tooltipI18nHandler = () => setTimeout(() => {
|
|
111
|
+
api.setTooltipI18n();
|
|
112
|
+
api.adjustTooltipPosition();
|
|
113
|
+
});
|
|
114
|
+
state.tooltipResizeHandler = () => api.adjustTooltipPosition();
|
|
115
|
+
vm.$el.addEventListener("click", state.tooltipI18nHandler);
|
|
116
|
+
vm.$el.addEventListener("keyup", state.tooltipI18nHandler);
|
|
117
|
+
window.addEventListener("resize", state.tooltipResizeHandler);
|
|
118
|
+
if (typeof MutationObserver !== "undefined") {
|
|
119
|
+
state.tooltipObserver = new MutationObserver(() => {
|
|
120
|
+
requestAnimationFrame(() => api.adjustTooltipPosition());
|
|
121
|
+
});
|
|
122
|
+
state.tooltipObserver.observe(vm.$el, {
|
|
123
|
+
childList: true,
|
|
124
|
+
subtree: true,
|
|
125
|
+
attributes: true,
|
|
126
|
+
attributeFilter: ["style", "class", "data-mode"]
|
|
127
|
+
});
|
|
128
|
+
}
|
|
109
129
|
};
|
|
110
130
|
const handleClick = ({ state, Quill }) => (event) => {
|
|
111
131
|
const el = event.target;
|
|
@@ -138,6 +158,64 @@ const setToolbarTips = ({ t, vm }) => () => {
|
|
|
138
158
|
});
|
|
139
159
|
}
|
|
140
160
|
};
|
|
161
|
+
const setTooltipI18n = ({ t, vm }) => () => {
|
|
162
|
+
const richTextEl = vm.$el;
|
|
163
|
+
const tips = richTextEl.querySelectorAll(".ql-container .ql-tooltip");
|
|
164
|
+
const getPlaceholderByMode = (mode) => {
|
|
165
|
+
if (mode === "video")
|
|
166
|
+
return t("ui.richText.enterVideo");
|
|
167
|
+
if (mode === "formula")
|
|
168
|
+
return t("ui.richText.enterFormula");
|
|
169
|
+
return t("ui.richText.enterLink");
|
|
170
|
+
};
|
|
171
|
+
if (tips.length) {
|
|
172
|
+
Array.prototype.slice.call(tips).forEach((tip) => {
|
|
173
|
+
const mode = tip.getAttribute("data-mode") || "link";
|
|
174
|
+
const input = tip.querySelector("input[type='text']");
|
|
175
|
+
tip.setAttribute("data-visit-url-text", `${t("ui.richText.visitUrl")}:`);
|
|
176
|
+
tip.setAttribute("data-edit-text", t("ui.richText.edit"));
|
|
177
|
+
tip.setAttribute("data-remove-text", t("ui.richText.remove"));
|
|
178
|
+
tip.setAttribute("data-save-text", t("ui.richText.save"));
|
|
179
|
+
tip.setAttribute("data-enter-link-text", `${t("ui.richText.enterLink")}:`);
|
|
180
|
+
tip.setAttribute("data-enter-formula-text", `${t("ui.richText.enterFormula")}:`);
|
|
181
|
+
tip.setAttribute("data-enter-video-text", `${t("ui.richText.enterVideo")}:`);
|
|
182
|
+
if (input) {
|
|
183
|
+
input.setAttribute("placeholder", getPlaceholderByMode(mode));
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const adjustTooltipPosition = ({ vm }) => () => {
|
|
189
|
+
const container = vm.$el.querySelector(".ql-container");
|
|
190
|
+
const tips = vm.$el.querySelectorAll(".ql-container .ql-tooltip");
|
|
191
|
+
const minGap = 8;
|
|
192
|
+
if (!container) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const containerRect = container.getBoundingClientRect();
|
|
196
|
+
if (tips.length) {
|
|
197
|
+
Array.prototype.slice.call(tips).forEach((tip) => {
|
|
198
|
+
if (!tip.classList.contains("ql-editing")) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const offsetParent = tip.offsetParent || tip.parentElement;
|
|
202
|
+
if (!offsetParent) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const parentRect = offsetParent.getBoundingClientRect();
|
|
206
|
+
const currentLeft = parseFloat(tip.style.left || "0");
|
|
207
|
+
const safeCurrentLeft = Number.isFinite(currentLeft) ? currentLeft : 0;
|
|
208
|
+
const minLeft = containerRect.left - parentRect.left + minGap;
|
|
209
|
+
const maxLeft = containerRect.right - parentRect.left - tip.offsetWidth - minGap;
|
|
210
|
+
if (maxLeft <= minLeft) {
|
|
211
|
+
tip.style.left = `${minLeft}px`;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const clampedLeft = Math.min(Math.max(safeCurrentLeft, minLeft), maxLeft);
|
|
215
|
+
tip.style.left = `${clampedLeft}px`;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
};
|
|
141
219
|
const setPlaceholder = ({ state, props }) => () => {
|
|
142
220
|
if (state.quill) {
|
|
143
221
|
state.quill.root.setAttribute("data-placeholder", props.options.placeholder);
|
|
@@ -220,17 +298,27 @@ const mounted = ({ api, props, state, i18n, watch }) => () => {
|
|
|
220
298
|
api.initQuill();
|
|
221
299
|
}
|
|
222
300
|
if (i18n) {
|
|
223
|
-
watch(() => i18n.locale,
|
|
301
|
+
watch(() => i18n.locale, () => {
|
|
302
|
+
api.setToolbarTips();
|
|
303
|
+
api.setTooltipI18n();
|
|
304
|
+
api.adjustTooltipPosition();
|
|
305
|
+
});
|
|
224
306
|
}
|
|
225
307
|
};
|
|
226
|
-
const beforeUnmount = ({ api, state }) => () => {
|
|
308
|
+
const beforeUnmount = ({ api, state, vm }) => () => {
|
|
227
309
|
state.quill.off("selection-change", api.selectionChange);
|
|
228
310
|
state.quill.off("text-change", api.textChange);
|
|
229
311
|
state.quill.root.removeEventListener("click", api.handleClick);
|
|
312
|
+
state.tooltipI18nHandler && vm.$el.removeEventListener("click", state.tooltipI18nHandler);
|
|
313
|
+
state.tooltipI18nHandler && vm.$el.removeEventListener("keyup", state.tooltipI18nHandler);
|
|
314
|
+
state.tooltipResizeHandler && window.removeEventListener("resize", state.tooltipResizeHandler);
|
|
315
|
+
state.tooltipObserver && state.tooltipObserver.disconnect();
|
|
316
|
+
state.tooltipObserver = null;
|
|
230
317
|
state.quill = null;
|
|
231
318
|
delete state.quill;
|
|
232
319
|
};
|
|
233
320
|
export {
|
|
321
|
+
adjustTooltipPosition,
|
|
234
322
|
beforeUnmount,
|
|
235
323
|
getFileUploadUrl,
|
|
236
324
|
handleClick,
|
|
@@ -243,5 +331,6 @@ export {
|
|
|
243
331
|
selectionChange,
|
|
244
332
|
setPlaceholder,
|
|
245
333
|
setToolbarTips,
|
|
334
|
+
setTooltipI18n,
|
|
246
335
|
textChange
|
|
247
336
|
};
|
package/rich-text/vue.js
CHANGED
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
initContent,
|
|
4
4
|
initQuill,
|
|
5
5
|
setToolbarTips,
|
|
6
|
+
setTooltipI18n,
|
|
7
|
+
adjustTooltipPosition,
|
|
6
8
|
setPlaceholder,
|
|
7
9
|
getFileUploadUrl,
|
|
8
10
|
selectionChange,
|
|
@@ -19,6 +21,8 @@ const api = [
|
|
|
19
21
|
"initContent",
|
|
20
22
|
"initQuill",
|
|
21
23
|
"setToolbarTips",
|
|
24
|
+
"setTooltipI18n",
|
|
25
|
+
"adjustTooltipPosition",
|
|
22
26
|
"setPlaceholder",
|
|
23
27
|
"selectionChange",
|
|
24
28
|
"textChange",
|
|
@@ -32,7 +36,10 @@ const initState = ({ reactive, props, computed, api: api2 }) => {
|
|
|
32
36
|
content: props.modelValue || props.content,
|
|
33
37
|
maxLength: computed(() => api2.maxLength()),
|
|
34
38
|
pasteCanceled: false,
|
|
35
|
-
isDisplayOnly: computed(() => api2.isDisplayOnly())
|
|
39
|
+
isDisplayOnly: computed(() => api2.isDisplayOnly()),
|
|
40
|
+
tooltipI18nHandler: null,
|
|
41
|
+
tooltipResizeHandler: null,
|
|
42
|
+
tooltipObserver: null
|
|
36
43
|
});
|
|
37
44
|
return state;
|
|
38
45
|
};
|
|
@@ -44,12 +51,14 @@ const initApi = (args) => {
|
|
|
44
51
|
initContent: initContent({ state, props, nextTick }),
|
|
45
52
|
initQuill: initQuill({ service, emit, props, api: api2, state, vm, ImageDrop, FileUpload, ImageUpload, Quill }),
|
|
46
53
|
setToolbarTips: setToolbarTips({ t, vm }),
|
|
54
|
+
setTooltipI18n: setTooltipI18n({ t, vm }),
|
|
55
|
+
adjustTooltipPosition: adjustTooltipPosition({ vm }),
|
|
47
56
|
setPlaceholder: setPlaceholder({ state, props }),
|
|
48
57
|
getFileUploadUrl: getFileUploadUrl({ service }),
|
|
49
58
|
selectionChange: selectionChange({ emit, state }),
|
|
50
59
|
textChange: textChange({ emit, vm, state, Modal, t }),
|
|
51
60
|
mounted: mounted({ api: api2, props, state, i18n, watch }),
|
|
52
|
-
beforeUnmount: beforeUnmount({ api: api2, state }),
|
|
61
|
+
beforeUnmount: beforeUnmount({ api: api2, state, vm }),
|
|
53
62
|
maxLength: maxLength({ props, constants }),
|
|
54
63
|
handlePaste: handlePaste({ state }),
|
|
55
64
|
isDisplayOnly: isDisplayOnly({ state, props, parent, nextTick }),
|
package/search/vue.js
CHANGED
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
searchEnterKey,
|
|
18
18
|
emitInput
|
|
19
19
|
} from "./index";
|
|
20
|
+
const generateUniqueId = () => {
|
|
21
|
+
return `search-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
22
|
+
};
|
|
20
23
|
const api = [
|
|
21
24
|
"state",
|
|
22
25
|
"handleChange",
|
|
@@ -68,7 +71,9 @@ const renderless = (props, { computed, onBeforeUnmount, onMounted, reactive, toR
|
|
|
68
71
|
}, formatSearchTypes2.state), {
|
|
69
72
|
showClear: computed(() => props.clearable && (state.focus || state.hovering) && state.currentValue),
|
|
70
73
|
formItemSize: computed(() => (parent.formItem || {}).formItemSize),
|
|
71
|
-
searchSize: computed(() => props.size || state.formItemSize)
|
|
74
|
+
searchSize: computed(() => props.size || state.formItemSize),
|
|
75
|
+
instanceId: generateUniqueId()
|
|
76
|
+
// 生成唯一 ID,用于避免多个组件实例时 id 重复
|
|
72
77
|
}));
|
|
73
78
|
const api2 = __spreadValues({
|
|
74
79
|
state,
|
package/select/index.js
CHANGED
|
@@ -1131,6 +1131,11 @@ const watchVisible = ({ api, constants, emit, state, vm, props, isMobileFirstMod
|
|
|
1131
1131
|
vm.$refs.scrollbar.handleScroll();
|
|
1132
1132
|
}
|
|
1133
1133
|
}
|
|
1134
|
+
if (value && state.device === "mb" && state.breakpoint === "default") {
|
|
1135
|
+
if (document.activeElement) {
|
|
1136
|
+
document.activeElement.blur();
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1134
1139
|
}, props.updateDelay);
|
|
1135
1140
|
if (!value && props.shape === "filter") {
|
|
1136
1141
|
state.softFocus = false;
|
|
@@ -1498,11 +1503,10 @@ const computedCurrentSizeMap = ({ state, designConfig }) => () => {
|
|
|
1498
1503
|
const sizeMap = ((_a = designConfig == null ? void 0 : designConfig.state) == null ? void 0 : _a.sizeMap) || defaultSizeMap;
|
|
1499
1504
|
return sizeMap[state.selectSize || "default"];
|
|
1500
1505
|
};
|
|
1501
|
-
const mounted = ({ api, parent, state, props, vm, designConfig }) => () => {
|
|
1506
|
+
const mounted = ({ api, parent, state, props, vm, designConfig, nextTick }) => () => {
|
|
1502
1507
|
state.defaultCheckedKeys = props.multiple ? state.gridCheckedData : props.treeOp.defaultCheckedKeys || [];
|
|
1503
1508
|
const parentEl = parent.$el;
|
|
1504
1509
|
const inputEl = parentEl.querySelector('input[data-tag="tiny-input-inner"]');
|
|
1505
|
-
const inputClientRect = inputEl && inputEl.getBoundingClientRect() || {};
|
|
1506
1510
|
if (inputEl === document.activeElement) {
|
|
1507
1511
|
document.activeElement.blur();
|
|
1508
1512
|
}
|
|
@@ -1514,10 +1518,14 @@ const mounted = ({ api, parent, state, props, vm, designConfig }) => () => {
|
|
|
1514
1518
|
if (vm.$refs.tags) {
|
|
1515
1519
|
addResizeListener(vm.$refs.tags, api.resetInputHeight);
|
|
1516
1520
|
}
|
|
1521
|
+
nextTick(() => {
|
|
1522
|
+
if (inputEl) {
|
|
1523
|
+
state.inputWidth = inputEl.offsetWidth || 0;
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1517
1526
|
if (props.remote && props.multiple) {
|
|
1518
1527
|
api.resetInputHeight();
|
|
1519
1528
|
}
|
|
1520
|
-
state.inputWidth = inputClientRect.width;
|
|
1521
1529
|
api.initQuery({ init: true }).then(() => {
|
|
1522
1530
|
api.setSelected(true);
|
|
1523
1531
|
if (props.modelValue && props.initLabel) {
|
package/select/vue.js
CHANGED
|
@@ -116,10 +116,10 @@ import {
|
|
|
116
116
|
computedCurrentSizeMap,
|
|
117
117
|
watchOptionsWhenAutoSelect
|
|
118
118
|
} from "./index";
|
|
119
|
-
import { debounce
|
|
119
|
+
import { debounce } from "@opentiny/utils";
|
|
120
120
|
import { isNumber } from "@opentiny/utils";
|
|
121
121
|
import { useUserAgent } from "@opentiny/vue-hooks";
|
|
122
|
-
import { isServer } from "@opentiny/utils";
|
|
122
|
+
import { isServer, nanoid } from "@opentiny/utils";
|
|
123
123
|
const api = [
|
|
124
124
|
"state",
|
|
125
125
|
"nodeCollapse",
|
|
@@ -288,7 +288,8 @@ const initState = ({
|
|
|
288
288
|
currentSizeMap: computed(() => api2.computedCurrentSizeMap()),
|
|
289
289
|
rootAutoTipConfig: computed(() => __spreadValues({
|
|
290
290
|
content: state.displayOnlyContent,
|
|
291
|
-
always: !!state.displayOnlyContent
|
|
291
|
+
always: !!state.displayOnlyContent,
|
|
292
|
+
popperClass: "tiny-select__popper-maxh-50"
|
|
292
293
|
}, props.tooltipConfig)),
|
|
293
294
|
ariaListId: "tiny-select-" + nanoid.api.nanoid(8)
|
|
294
295
|
}));
|
|
@@ -506,7 +507,7 @@ const addApi = ({
|
|
|
506
507
|
debouncRquest: debouncRquest({ api: api2, state, props }),
|
|
507
508
|
defaultOnQueryChange: defaultOnQueryChange({ props, state, constants, api: api2, nextTick, vm }),
|
|
508
509
|
queryChange: queryChange({ props, state, constants, api: api2, nextTick, vm }),
|
|
509
|
-
mounted: mounted({ api: api2, parent, state, props, vm, designConfig }),
|
|
510
|
+
mounted: mounted({ api: api2, parent, state, props, vm, designConfig, nextTick }),
|
|
510
511
|
unMount: unMount({ api: api2, parent, vm, state }),
|
|
511
512
|
watchOptimizeOpts: watchOptimizeOpts({ props, state }),
|
|
512
513
|
handleDropdownClick: handleDropdownClick({ props, vm, state, emit }),
|
package/statistic/index.js
CHANGED
|
@@ -8,7 +8,7 @@ const getIntegerAndDecimal = ({ props }) => () => {
|
|
|
8
8
|
if (isFunction(props.formatter)) {
|
|
9
9
|
return props.formatter(props.value);
|
|
10
10
|
}
|
|
11
|
-
if (
|
|
11
|
+
if (typeof props.value !== "number") {
|
|
12
12
|
return props.value;
|
|
13
13
|
}
|
|
14
14
|
let displayValue = String(props.value).split(".");
|
|
@@ -26,7 +26,54 @@ const getIntegerAndDecimal = ({ props }) => () => {
|
|
|
26
26
|
}
|
|
27
27
|
return [integer, decimal].join(decimal ? "." : "");
|
|
28
28
|
};
|
|
29
|
+
const animateValue = ({ props, state }) => () => {
|
|
30
|
+
if (!props.useAnimation)
|
|
31
|
+
return;
|
|
32
|
+
let AnimationId = null;
|
|
33
|
+
const start = props.startValue;
|
|
34
|
+
const end = Number(props.value);
|
|
35
|
+
const duration = props.duration;
|
|
36
|
+
if (Number.isNaN(end)) {
|
|
37
|
+
state.animatingValue = props.value;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const startTime = performance.now();
|
|
41
|
+
const cancel = () => {
|
|
42
|
+
if (AnimationId) {
|
|
43
|
+
cancelAnimationFrame(AnimationId);
|
|
44
|
+
AnimationId = null;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
if (AnimationId) {
|
|
48
|
+
cancel();
|
|
49
|
+
}
|
|
50
|
+
const getDecimalPlaces = (num) => {
|
|
51
|
+
if (Math.floor(num) === num)
|
|
52
|
+
return 0;
|
|
53
|
+
const decimalPart = num.toString().split(".")[1];
|
|
54
|
+
return decimalPart ? decimalPart.length : 0;
|
|
55
|
+
};
|
|
56
|
+
const decimalPlaces = getDecimalPlaces(end);
|
|
57
|
+
const multiplier = 10 ** decimalPlaces;
|
|
58
|
+
const animate = (currentTime) => {
|
|
59
|
+
const elapsed = currentTime - startTime;
|
|
60
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
61
|
+
const easeOutExpo = (t) => t === 1 ? 1 : 1 - 2 ** (-10 * t);
|
|
62
|
+
const current = start + (end - start) * easeOutExpo(progress);
|
|
63
|
+
state.animatingValue = Math.round(current * multiplier) / multiplier;
|
|
64
|
+
if (progress < 1) {
|
|
65
|
+
AnimationId = requestAnimationFrame(animate);
|
|
66
|
+
} else {
|
|
67
|
+
state.animatingValue = end;
|
|
68
|
+
AnimationId = null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
AnimationId = requestAnimationFrame(() => {
|
|
72
|
+
AnimationId = requestAnimationFrame(animate);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
29
75
|
export {
|
|
76
|
+
animateValue,
|
|
30
77
|
getIntegerAndDecimal,
|
|
31
78
|
isNumber
|
|
32
79
|
};
|