@itfin/components 1.2.107 → 1.2.108
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/package.json +1 -1
- package/src/components/copyToClipboard/CopyToClipboard.vue +67 -0
- package/src/components/customize/Inline/Multiselect.vue +21 -3
- package/src/components/customize/Inline/Select.vue +4 -1
- package/src/components/customize/Inline/Text.vue +6 -1
- package/src/components/customize/PropertiesEditMenu.vue +3 -4
- package/src/components/customize/PropertiesList.vue +6 -2
- package/src/components/select/Select.vue +1 -2
- package/src/locales/en.js +3 -0
- package/src/locales/uk.js +3 -0
package/package.json
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<itf-button icon small @click.stop="copy">
|
|
3
|
+
<slot>
|
|
4
|
+
<itf-icon name="clipboard_copy" />
|
|
5
|
+
</slot>
|
|
6
|
+
</itf-button>
|
|
7
|
+
</template>
|
|
8
|
+
<script>
|
|
9
|
+
import { Vue, Component, Prop } from 'vue-property-decorator';
|
|
10
|
+
import itfIcon from '../icon/Icon';
|
|
11
|
+
import itfButton from '../button/Button';
|
|
12
|
+
|
|
13
|
+
export default @Component({
|
|
14
|
+
components: {
|
|
15
|
+
itfIcon,
|
|
16
|
+
itfButton
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
class CopyToClipboard extends Vue {
|
|
20
|
+
@Prop(String) value;
|
|
21
|
+
|
|
22
|
+
async copy () {
|
|
23
|
+
const showSuccess = this.$showSuccess;
|
|
24
|
+
const showError = this.$showError;
|
|
25
|
+
const $t = this.$t.bind(this);
|
|
26
|
+
|
|
27
|
+
function fallbackCopyTextToClipboard (text) {
|
|
28
|
+
const textArea = document.createElement('textarea');
|
|
29
|
+
textArea.value = text;
|
|
30
|
+
|
|
31
|
+
// Avoid scrolling to bottom
|
|
32
|
+
textArea.style.top = '0';
|
|
33
|
+
textArea.style.left = '0';
|
|
34
|
+
textArea.style.position = 'fixed';
|
|
35
|
+
|
|
36
|
+
document.body.appendChild(textArea);
|
|
37
|
+
textArea.focus();
|
|
38
|
+
textArea.select();
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
if (document.execCommand('copy')) {
|
|
42
|
+
showSuccess($t('components.copyToClipboard.copyingToClipboardWasSuccessful'));
|
|
43
|
+
}
|
|
44
|
+
} catch (err) {
|
|
45
|
+
showError(err.message);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
document.body.removeChild(textArea);
|
|
49
|
+
}
|
|
50
|
+
async function copyTextToClipboard (text) {
|
|
51
|
+
if (!navigator.clipboard) {
|
|
52
|
+
fallbackCopyTextToClipboard(text);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
await navigator.clipboard.writeText(text);
|
|
57
|
+
|
|
58
|
+
showSuccess($t('components.copyToClipboard.copyingToClipboardWasSuccessful'));
|
|
59
|
+
} catch (err) {
|
|
60
|
+
showError(err.message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await copyTextToClipboard(this.value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
<div class="itf-inline-edit">
|
|
3
3
|
<itf-select
|
|
4
4
|
ref="input"
|
|
5
|
-
class="input"
|
|
5
|
+
class="input flex-grow-1"
|
|
6
6
|
role="button"
|
|
7
7
|
multiple
|
|
8
8
|
:placeholder="focused ? 'Search for an option...' : 'Empty'"
|
|
9
9
|
:tabindex="1"
|
|
10
10
|
:disabled="!editable"
|
|
11
|
-
:options="
|
|
11
|
+
:options="options"
|
|
12
12
|
:reduce="option => option.Name"
|
|
13
13
|
:get-option-label="option => option.Name"
|
|
14
14
|
@search:focus="$emit('focus')"
|
|
15
|
-
@search:blur="$emit('blur')"
|
|
15
|
+
@search:blur="$emit('blur')"
|
|
16
|
+
:value="itemsValue"
|
|
17
|
+
@input="onInput"
|
|
18
|
+
>
|
|
16
19
|
<template #option="{ option }">
|
|
17
20
|
<div>{{ option.Name }}</div>
|
|
18
21
|
</template>
|
|
@@ -51,5 +54,20 @@ class itfCustomizeInlineMultiselect extends Vue {
|
|
|
51
54
|
@Prop(Boolean) focused;
|
|
52
55
|
@Prop(Boolean) editable;
|
|
53
56
|
@Prop() field;
|
|
57
|
+
|
|
58
|
+
get itemsValue () {
|
|
59
|
+
return (this.value || '').toString().split(';;;').filter(v => v.length);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get options() {
|
|
63
|
+
const list = (this.field && this.field.Options) || [];
|
|
64
|
+
const notExists = this.itemsValue.filter(v => !list.find(o => o.Name === v));
|
|
65
|
+
|
|
66
|
+
return [...list, ...notExists.map(v => ({ Name: v }))];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
onInput(val) {
|
|
70
|
+
this.$emit('input', val.join(';;;'));
|
|
71
|
+
}
|
|
54
72
|
}
|
|
55
73
|
</script>
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
:reduce="option => option.Name"
|
|
11
11
|
:get-option-label="option => option.Name"
|
|
12
12
|
@search:focus="$emit('focus')"
|
|
13
|
-
@search:blur="$emit('blur')"
|
|
13
|
+
@search:blur="$emit('blur')"
|
|
14
|
+
:value="value"
|
|
15
|
+
@input="$emit('input', $event)"
|
|
16
|
+
>
|
|
14
17
|
<template #option="{ option }">
|
|
15
18
|
<div>{{ option.Name }}</div>
|
|
16
19
|
</template>
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
:contenteditable="editable"
|
|
15
15
|
v-html="value">
|
|
16
16
|
</div>
|
|
17
|
+
<itf-copy-to-clipboard :value="value" />
|
|
17
18
|
</div>
|
|
18
19
|
</template>
|
|
19
20
|
<style lang="scss" scoped>
|
|
@@ -36,12 +37,16 @@
|
|
|
36
37
|
</style>
|
|
37
38
|
<script>
|
|
38
39
|
import { Vue, Component, Model, Prop } from 'vue-property-decorator';
|
|
40
|
+
import itfIcon from '../../icon/Icon.vue';
|
|
39
41
|
import itfTextField from '../../text-field/TextField.vue';
|
|
42
|
+
import itfCopyToClipboard from '../../copyToClipboard/CopyToClipboard';
|
|
40
43
|
|
|
41
44
|
export default @Component({
|
|
42
45
|
name: 'itfCustomizeInlineText',
|
|
43
46
|
components: {
|
|
44
|
-
|
|
47
|
+
itfIcon,
|
|
48
|
+
itfTextField,
|
|
49
|
+
itfCopyToClipboard
|
|
45
50
|
}
|
|
46
51
|
})
|
|
47
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="itf-append-context" style="min-width: 300px">
|
|
3
|
-
<div class="d-flex align-items-center px-3 py-2">
|
|
3
|
+
<div class="d-flex align-items-center px-3 py-2" sortable-skip>
|
|
4
4
|
<!--div class="me-1">
|
|
5
5
|
<itf-icon-popover title="Icon" removable :value="value.Icon" @input="setParam({ Icon: $event })">
|
|
6
6
|
<itf-button slot="activator" icon>
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
</itf-button>
|
|
9
9
|
</itf-icon-popover>
|
|
10
10
|
</div-->
|
|
11
|
-
|
|
12
11
|
<div class="flex-grow-1">
|
|
13
12
|
<itf-text-field ref="input" :value="value.Name" @input="setParam({ Name: $event })" />
|
|
14
13
|
</div>
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
</div>
|
|
40
39
|
</div>
|
|
41
40
|
|
|
42
|
-
<div v-if="isNewOptionVisible" class="px-3">
|
|
41
|
+
<div v-if="isNewOptionVisible" class="px-3" sortable-skip>
|
|
43
42
|
<itf-text-field
|
|
44
43
|
ref="newOptionInput"
|
|
45
44
|
v-model="newOption"
|
|
@@ -117,7 +116,7 @@ import itfIconPopover from '../popover/IconPopover.vue';
|
|
|
117
116
|
import { INLINE_TYPES } from './constants';
|
|
118
117
|
import itfDeleteConfirmModal from '../modal/DeleteConfirmModal.vue';
|
|
119
118
|
import PropertyItem from './PropertyItem.vue';
|
|
120
|
-
import PropertiesPopupMenu from
|
|
119
|
+
import PropertiesPopupMenu from './PropertiesPopupMenu.vue';
|
|
121
120
|
|
|
122
121
|
export default @Component({
|
|
123
122
|
components: {
|
|
@@ -165,7 +165,9 @@ class itfPropertiesList extends Vue {
|
|
|
165
165
|
prop.hideEditMenu();
|
|
166
166
|
}
|
|
167
167
|
setTimeout(() => {
|
|
168
|
-
this.$refs.properties[list.length - 1]
|
|
168
|
+
if (this.$refs.properties && this.$refs.properties[list.length - 1]) {
|
|
169
|
+
this.$refs.properties[list.length - 1].showEditMenu();
|
|
170
|
+
}
|
|
169
171
|
}, 10);
|
|
170
172
|
});
|
|
171
173
|
}
|
|
@@ -186,7 +188,9 @@ class itfPropertiesList extends Vue {
|
|
|
186
188
|
|
|
187
189
|
this.$nextTick(() => {
|
|
188
190
|
setTimeout(() => {
|
|
189
|
-
this.$refs.properties[list.length - 1]
|
|
191
|
+
if (this.$refs.properties && this.$refs.properties[list.length - 1]) {
|
|
192
|
+
this.$refs.properties[list.length - 1].showEditMenu();
|
|
193
|
+
}
|
|
190
194
|
}, 10);
|
|
191
195
|
});
|
|
192
196
|
}
|
|
@@ -32,9 +32,8 @@
|
|
|
32
32
|
<itf-button
|
|
33
33
|
icon
|
|
34
34
|
small
|
|
35
|
-
v-if="multiple"
|
|
35
|
+
v-if="multiple && !disabled"
|
|
36
36
|
ref="deselectButtons"
|
|
37
|
-
:disabled="disabled"
|
|
38
37
|
class="vs__deselect"
|
|
39
38
|
:title="`Deselect ${getOptionLabel(option)}`"
|
|
40
39
|
:aria-label="`Deselect ${getOptionLabel(option)}`"
|
package/src/locales/en.js
CHANGED
|
@@ -93,5 +93,8 @@ module.exports = {
|
|
|
93
93
|
hideMoreProperties: 'Hide {n} property|Hide {n} properties',
|
|
94
94
|
deleteItem: 'Delete',
|
|
95
95
|
areYouSureYouWantToDeleteThisItem: 'Are you sure you want to remove this option?',
|
|
96
|
+
},
|
|
97
|
+
copyToClipboard: {
|
|
98
|
+
copyingToClipboardWasSuccessful: 'Copying to clipboard was successful',
|
|
96
99
|
}
|
|
97
100
|
};
|
package/src/locales/uk.js
CHANGED
|
@@ -93,5 +93,8 @@ module.exports = {
|
|
|
93
93
|
hideMoreProperties: 'Приховати {n} поле|Приховати {n} полів',
|
|
94
94
|
deleteItem: 'Видалити',
|
|
95
95
|
areYouSureYouWantToDeleteThisItem: 'Ви впевнені, що хочете видалити цю опцію?',
|
|
96
|
+
},
|
|
97
|
+
copyToClipboard: {
|
|
98
|
+
copyingToClipboardWasSuccessful: 'Скопійовано в буфер',
|
|
96
99
|
}
|
|
97
100
|
};
|