@cloudron/pankow 3.5.9 → 3.5.10
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/components/EmailInput.vue +11 -2
- package/components/FileUploader.vue +20 -3
- package/components/Menu.vue +28 -1
- package/components/MultiSelect.vue +17 -12
- package/components/PasswordInput.vue +8 -2
- package/components/SingleSelect.vue +10 -9
- package/components/TextInput.vue +2 -0
- package/package.json +4 -4
- package/style.css +10 -0
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
|
|
3
|
+
import { useTemplateRef } from 'vue';
|
|
4
|
+
|
|
3
5
|
const model = defineModel();
|
|
4
6
|
const props = defineProps({
|
|
5
7
|
placeholder: String,
|
|
6
8
|
readonly: {
|
|
7
9
|
type: Boolean,
|
|
8
|
-
default: false
|
|
10
|
+
default: false,
|
|
9
11
|
},
|
|
10
12
|
});
|
|
13
|
+
const inputElement = useTemplateRef('inputElement');
|
|
14
|
+
|
|
15
|
+
function focus() {
|
|
16
|
+
inputElement.value.focus();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
defineExpose({ focus });
|
|
11
20
|
|
|
12
21
|
</script>
|
|
13
22
|
|
|
14
23
|
<template>
|
|
15
|
-
<input class="pankow-text-input" type="email" :placeholder="placeholder" :readonly="readonly"
|
|
24
|
+
<input ref="inputElement" class="pankow-text-input" type="email" :placeholder="placeholder" :readonly="readonly" v-model.trim="model"/>
|
|
16
25
|
</template>
|
|
17
26
|
|
|
18
27
|
<style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="file-uploader" v-show="uploadInProgress">
|
|
3
|
-
<div class="label">{{ tr('filemanager.uploader.uploading') }} {{ activeFile ? activeFile.name : '' }}
|
|
2
|
+
<div class="pankow-file-uploader" v-show="uploadInProgress">
|
|
3
|
+
<div class="pankow-file-uploader-label-and-speed-container"><div class="pankow-file-uploader-label">{{ tr('filemanager.uploader.uploading') }} {{ activeFile ? activeFile.name : '' }}</div><div class="pankow-file-uploader-speed">{{ prettyUploadSpeed }}</div></div>
|
|
4
4
|
<div style="display: flex;">
|
|
5
5
|
<ProgressBar :value="parseInt((this.uploadedSize * 100) / this.size) || 0" style="flex-grow: 1"></ProgressBar>
|
|
6
6
|
<Button danger small tool @click="onCancelUpload" icon="fa-solid fa-xmark"></Button>
|
|
@@ -195,10 +195,27 @@ export default {
|
|
|
195
195
|
|
|
196
196
|
<style>
|
|
197
197
|
|
|
198
|
-
.file-uploader {
|
|
198
|
+
.pankow-file-uploader {
|
|
199
199
|
width: 100%;
|
|
200
200
|
padding: 10px;
|
|
201
201
|
background-color: var(--pankow-color-background);
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
.pankow-file-uploader-label-and-speed-container {
|
|
205
|
+
display: flex;
|
|
206
|
+
gap: 10px;
|
|
207
|
+
margin-bottom: 5px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.pankow-file-uploader-label {
|
|
211
|
+
flex-grow: 1;
|
|
212
|
+
white-space: nowrap;
|
|
213
|
+
text-overflow: ellipsis;
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.pankow-file-uploader-speed {
|
|
218
|
+
white-space: nowrap;
|
|
219
|
+
}
|
|
220
|
+
|
|
204
221
|
</style>
|
package/components/Menu.vue
CHANGED
|
@@ -90,7 +90,34 @@ const hasIcons = computed(() => {
|
|
|
90
90
|
const visibleItems = computed(() => {
|
|
91
91
|
if (!searchString.value) return props.model;
|
|
92
92
|
const s = searchString.value.toLowerCase();
|
|
93
|
-
|
|
93
|
+
let results = [];
|
|
94
|
+
|
|
95
|
+
let group = null;
|
|
96
|
+
let filteredGroupItems = [];
|
|
97
|
+
|
|
98
|
+
for (let item of props.model) {
|
|
99
|
+
if (item.separator) {
|
|
100
|
+
if (group && filteredGroupItems.length) {
|
|
101
|
+
results.push(group);
|
|
102
|
+
results = results.concat(filteredGroupItems);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
group = item;
|
|
106
|
+
filteredGroupItems = [];
|
|
107
|
+
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (group && group.label?.toLowerCase().indexOf(s) !== -1) filteredGroupItems.push(item);
|
|
112
|
+
else if (item.label.toLowerCase().indexOf(s) !== -1) filteredGroupItems.push(item);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// add remaining group and filtered items (also matches if no group ever set)
|
|
116
|
+
if (group && filteredGroupItems.length) results.push(group);
|
|
117
|
+
if (filteredGroupItems.length) results = results.concat(filteredGroupItems);
|
|
118
|
+
|
|
119
|
+
return results;
|
|
120
|
+
// return props.model.filter((item) => item.label.toLowerCase().indexOf(s) !== -1);
|
|
94
121
|
});
|
|
95
122
|
|
|
96
123
|
// select menu item by .label
|
|
@@ -47,6 +47,7 @@ let selected = ref([]);
|
|
|
47
47
|
|
|
48
48
|
const elem = useTemplateRef('elem');
|
|
49
49
|
const menu = useTemplateRef('menu');
|
|
50
|
+
const nativeSelect = useTemplateRef('nativeSelect');
|
|
50
51
|
|
|
51
52
|
watch(model, (newValue, oldValue) => {
|
|
52
53
|
selected.value = newValue;
|
|
@@ -63,7 +64,7 @@ const menuModel = computed(() => {
|
|
|
63
64
|
if (item.separator) {
|
|
64
65
|
return {
|
|
65
66
|
separator: true,
|
|
66
|
-
label:
|
|
67
|
+
label: item[props.optionLabel],
|
|
67
68
|
};
|
|
68
69
|
} else {
|
|
69
70
|
return {
|
|
@@ -82,6 +83,11 @@ const menuModel = computed(() => {
|
|
|
82
83
|
|
|
83
84
|
model.value = selected.value;
|
|
84
85
|
emits('select', selected.value);
|
|
86
|
+
|
|
87
|
+
// let the browser know about the changes
|
|
88
|
+
nativeSelect.value.value = selected.value;
|
|
89
|
+
nativeSelect.value.dispatchEvent(new Event('input', { bubbles: true }));
|
|
90
|
+
nativeSelect.value.dispatchEvent(new Event('change', { bubbles: true }));
|
|
85
91
|
}
|
|
86
92
|
};
|
|
87
93
|
}
|
|
@@ -114,11 +120,6 @@ const menuModel = computed(() => {
|
|
|
114
120
|
return ret;
|
|
115
121
|
});
|
|
116
122
|
|
|
117
|
-
function onMenuClosed() {
|
|
118
|
-
elem.value.focus();
|
|
119
|
-
emits('close');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
123
|
function onClick(event) {
|
|
123
124
|
if (props.disabled) return;
|
|
124
125
|
|
|
@@ -132,9 +133,13 @@ function onOpen(event) {
|
|
|
132
133
|
menu.value.open(event, elem.value);
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
function onClose(event) {
|
|
136
|
-
menu.value.
|
|
137
|
-
|
|
136
|
+
function onClose(event = null) {
|
|
137
|
+
if (menu.value.isOpen) {
|
|
138
|
+
elem.value.focus();
|
|
139
|
+
if (event) event.stopPropagation();
|
|
140
|
+
menu.value.close();
|
|
141
|
+
emits('close');
|
|
142
|
+
}
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
onMounted(() => {
|
|
@@ -144,14 +149,14 @@ onMounted(() => {
|
|
|
144
149
|
</script>
|
|
145
150
|
|
|
146
151
|
<template>
|
|
147
|
-
<div class="pankow-multiselect" :class="{ 'pankow-multiselect-disabled': disabled }" ref="elem" tabindex="0" @click="onClick" @keydown.enter="onOpen" @keydown.down.stop="onOpen" @keydown.up.stop="onOpen" @keydown.esc
|
|
152
|
+
<div class="pankow-multiselect" :class="{ 'pankow-multiselect-disabled': disabled }" ref="elem" tabindex="0" @click="onClick" @keydown.enter="onOpen" @keydown.down.stop="onOpen" @keydown.up.stop="onOpen" @keydown.esc="onClose">
|
|
148
153
|
<!-- native select for required and accessibility handling -->
|
|
149
|
-
<select
|
|
154
|
+
<select ref="nativeSelect" :required="$attrs['required']" multiple style="display: none">
|
|
150
155
|
<option value=""></option>
|
|
151
156
|
<option v-for="item in options" :value="optionKey ? item[optionKey] : item">{{ optionKey }} - {{ item[optionLabel] }}</option>
|
|
152
157
|
</select>
|
|
153
158
|
|
|
154
|
-
<Menu ref="menu" :model="menuModel" :close-on-activation="false" @close="
|
|
159
|
+
<Menu ref="menu" :model="menuModel" :close-on-activation="false" @close="onClose" :search-threshold="searchThreshold"></Menu>
|
|
155
160
|
{{ buttonLabel }}
|
|
156
161
|
<Icon icon="fa-solid fa-chevron-down" class="pankow-button-icon-right-with-text" />
|
|
157
162
|
</div>
|
|
@@ -67,11 +67,17 @@ function toggleReveal() {
|
|
|
67
67
|
outline: none;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
.pankow-password-input
|
|
70
|
+
.pankow-password-input[readonly],
|
|
71
|
+
.pankow-password-input[disabled] {
|
|
71
72
|
cursor: not-allowed;
|
|
72
|
-
|
|
73
|
+
background-color: var(--pankow-input-readonly-background-color);
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
.pankow-password-input[disabled]:hover {
|
|
77
|
+
border-color: var(--pankow-input-border-color);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
75
81
|
.pankow-password-reveal {
|
|
76
82
|
display: inline-block;
|
|
77
83
|
position: absolute;
|
|
@@ -32,7 +32,7 @@ const props = defineProps({
|
|
|
32
32
|
},
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
const emits = defineEmits(['select']);
|
|
35
|
+
const emits = defineEmits(['select', 'close']);
|
|
36
36
|
|
|
37
37
|
const model = defineModel();
|
|
38
38
|
const selected = ref(null);
|
|
@@ -92,10 +92,6 @@ function selectIndex(index) {
|
|
|
92
92
|
nativeSelect.value.dispatchEvent(new Event('change', { bubbles: true }));
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
function onMenuClosed() {
|
|
96
|
-
elem.value.focus();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
95
|
function onClick(event) {
|
|
100
96
|
if (props.disabled) return;
|
|
101
97
|
|
|
@@ -109,8 +105,13 @@ function onOpen(event) {
|
|
|
109
105
|
menu.value.open(event, elem.value);
|
|
110
106
|
}
|
|
111
107
|
|
|
112
|
-
function onClose(event) {
|
|
113
|
-
menu.value.
|
|
108
|
+
function onClose(event = null) {
|
|
109
|
+
if (menu.value.isOpen) {
|
|
110
|
+
if (event) event.stopPropagation();
|
|
111
|
+
elem.value.focus();
|
|
112
|
+
menu.value.close();
|
|
113
|
+
emits('close');
|
|
114
|
+
}
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
function onClosed() {
|
|
@@ -169,14 +170,14 @@ watchEffect(handleDefaultSelect);
|
|
|
169
170
|
</script>
|
|
170
171
|
|
|
171
172
|
<template>
|
|
172
|
-
<div class="pankow-singleselect" :class="{ 'pankow-singleselect-disabled': disabled }" ref="elem" tabindex="0" @click="onClick" @keydown.enter="onOpen" @keydown.down.stop.prevent="onSelectNext" @keydown.up.stop.prevent="onSelectPrev" @keydown.esc
|
|
173
|
+
<div class="pankow-singleselect" :class="{ 'pankow-singleselect-disabled': disabled }" ref="elem" tabindex="0" @click="onClick" @keydown.enter="onOpen" @keydown.down.stop.prevent="onSelectNext" @keydown.up.stop.prevent="onSelectPrev" @keydown.esc="onClose" @keydown.stop="onKeyDown($event)">
|
|
173
174
|
<!-- native select for required and accessibility handling -->
|
|
174
175
|
<select v-model="selectedKey" ref="nativeSelect" :required="$attrs['required']" style="display: none">
|
|
175
176
|
<option value=""></option>
|
|
176
177
|
<option v-for="item in options" :value="optionKey ? item[optionKey] : item">{{ item[optionLabel] }}</option>
|
|
177
178
|
</select>
|
|
178
179
|
|
|
179
|
-
<Menu ref="menu" :model="menuModel" :search-threshold="searchThreshold" :close-on-activation="true" @close="
|
|
180
|
+
<Menu ref="menu" :model="menuModel" :search-threshold="searchThreshold" :close-on-activation="true" @close="onClose"/>
|
|
180
181
|
<span class="pankow-singleselect-label">
|
|
181
182
|
<Icon v-if="selected ? selected.icon : false" :icon="selected.icon" style="margin-right: 6px" />
|
|
182
183
|
{{ selected ? selected[optionLabel] : placeholder }}
|
package/components/TextInput.vue
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudron/pankow",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.5.
|
|
4
|
+
"version": "3.5.10",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"monaco-editor": "^0.54.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
25
|
+
"@vitejs/plugin-vue": "^6.0.2",
|
|
26
26
|
"typescript": "^5.9.3",
|
|
27
|
-
"vite": "^7.2.
|
|
28
|
-
"vue": "^3.5.
|
|
27
|
+
"vite": "^7.2.4",
|
|
28
|
+
"vue": "^3.5.25"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/style.css
CHANGED
|
@@ -183,6 +183,16 @@ textarea:focus {
|
|
|
183
183
|
outline: none;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
textarea[disabled],
|
|
187
|
+
textarea[readonly] {
|
|
188
|
+
cursor: not-allowed;
|
|
189
|
+
background-color: var(--pankow-input-readonly-background-color);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
textarea[disabled]:hover {
|
|
193
|
+
border-color: var(--pankow-input-border-color);
|
|
194
|
+
}
|
|
195
|
+
|
|
186
196
|
@media (max-width: 576px) {
|
|
187
197
|
.pankow-no-mobile {
|
|
188
198
|
display: none !important;
|