glib-web 6.0.0 → 6.0.2
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/app.scss +19 -0
- package/components/composable/listAutoload.js +8 -4
- package/components/composable/selectable.js +2 -5
- package/components/fields/_select.vue +10 -20
- package/components/fields/_selectItemDefault.vue +1 -1
- package/components/fields/_selectItemWithIcon.vue +2 -2
- package/components/fields/_selectItemWithImage.vue +2 -2
- package/components/panels/flow.vue +19 -10
- package/components/panels/list.vue +2 -2
- package/package.json +2 -3
package/app.scss
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vuetify 3 bundled sanitize.css which reset all element margins via `* { margin: 0; padding: 0 }`.
|
|
3
|
+
* Vuetify 4 dropped sanitize.css in favour of a lighter CSS-layers reset that does NOT zero
|
|
4
|
+
* browser-default margins on block elements. We restore the relevant resets here explicitly so
|
|
5
|
+
* that layout behaves the same as it did under Vuetify 3.
|
|
6
|
+
*
|
|
7
|
+
* Padding is intentionally NOT reset on h1–h6, p, li, figure, figcaption, dl: browsers add no
|
|
8
|
+
* default padding to those elements, so a reset is a visual no-op — but an unlayered `padding: 0`
|
|
9
|
+
* would override Vuetify 4 spacing utilities (pb-*, pt-*, px-* …) which live in
|
|
10
|
+
* @layer vuetify-utilities and lose to any unlayered CSS.
|
|
11
|
+
*/
|
|
12
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre, ol, ul, li, figure, figcaption, dl, dd {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
// Only reset padding where the browser UA actually sets a non-zero default.
|
|
16
|
+
blockquote, pre, ol, ul, dd {
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
1
20
|
.border-\[2px\] {
|
|
2
21
|
border-width: 2px;
|
|
3
22
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCurrentInstance, nextTick, ref } from "vue";
|
|
1
|
+
import { getCurrentInstance, nextTick, ref, shallowRef } from "vue";
|
|
2
2
|
import { jsonView } from "../../store";
|
|
3
3
|
import { isArray, isFunction, isNotNull, isObject } from "../../utils/type";
|
|
4
4
|
|
|
@@ -8,6 +8,8 @@ function useListAutoload() {
|
|
|
8
8
|
const instance = getCurrentInstance();
|
|
9
9
|
const topScrollHandler = ref(null);
|
|
10
10
|
const bottomScrollHandler = ref(null);
|
|
11
|
+
const topAnchorEl = shallowRef(null);
|
|
12
|
+
const bottomAnchorEl = shallowRef(null);
|
|
11
13
|
const nextPageUrl = ref(null);
|
|
12
14
|
const prevPageUrl = ref(null);
|
|
13
15
|
const request = ref(null);
|
|
@@ -68,7 +70,7 @@ function useListAutoload() {
|
|
|
68
70
|
if (!proxy) return;
|
|
69
71
|
|
|
70
72
|
topScrollHandler.value = onVisibilityChange(
|
|
71
|
-
|
|
73
|
+
topAnchorEl.value,
|
|
72
74
|
(_el, visible) => {
|
|
73
75
|
if (visible) {
|
|
74
76
|
handleTopScroll(onScrollToTop);
|
|
@@ -85,7 +87,7 @@ function useListAutoload() {
|
|
|
85
87
|
const proxy = getProxy(instance);
|
|
86
88
|
if (!proxy) return;
|
|
87
89
|
|
|
88
|
-
const topAnchor =
|
|
90
|
+
const topAnchor = topAnchorEl.value;
|
|
89
91
|
const bodyRef = proxy.$refs?.body;
|
|
90
92
|
if (!isNotNull(topAnchor) || !isArray(bodyRef)) return;
|
|
91
93
|
|
|
@@ -153,7 +155,7 @@ function useListAutoload() {
|
|
|
153
155
|
if (!proxy) return;
|
|
154
156
|
|
|
155
157
|
bottomScrollHandler.value = onVisibilityChange(
|
|
156
|
-
|
|
158
|
+
bottomAnchorEl.value,
|
|
157
159
|
(_el, visible) => {
|
|
158
160
|
if (visible) {
|
|
159
161
|
handleBottomScroll(onScrollToBottom);
|
|
@@ -227,6 +229,8 @@ function useListAutoload() {
|
|
|
227
229
|
prevPageUrl,
|
|
228
230
|
request,
|
|
229
231
|
infiniteScroll,
|
|
232
|
+
setTopAnchorEl: (el) => { topAnchorEl.value = el; },
|
|
233
|
+
setBottomAnchorEl: (el) => { bottomAnchorEl.value = el; },
|
|
230
234
|
enableInfiniteScrollIfApplicable,
|
|
231
235
|
autoloadAll,
|
|
232
236
|
cancelAutoloadRequest,
|
|
@@ -14,7 +14,7 @@ function useGlibSelectable({ model, options, valueForDisableAll, itemKey = 'valu
|
|
|
14
14
|
model.value = Array.from(new Set([...model.value, ...values]));
|
|
15
15
|
};
|
|
16
16
|
const deselect = (values) => {
|
|
17
|
-
model.value = model.filter((v) => values.includes(v));
|
|
17
|
+
model.value = model.value.filter((v) => values.includes(v));
|
|
18
18
|
};
|
|
19
19
|
const selectAll = () => {
|
|
20
20
|
model.value = allItem.value.map((item) => item[itemKey]);
|
|
@@ -53,9 +53,7 @@ function watchNoneOfAbove({ model, options, valueForDisableAll, itemKey = 'value
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
if (hasNoneOfAbove) {
|
|
58
|
-
watch(model, (value, oldValue) => {
|
|
56
|
+
watch(model, (value, oldValue) => {
|
|
59
57
|
if (JSON.stringify(value) === JSON.stringify(oldValue)) return;
|
|
60
58
|
if (!isArray(value)) return;
|
|
61
59
|
if (value && !value.includes(valueForDisableAll) && oldValue && !oldValue.includes(valueForDisableAll)) return;
|
|
@@ -66,7 +64,6 @@ function watchNoneOfAbove({ model, options, valueForDisableAll, itemKey = 'value
|
|
|
66
64
|
disableExceptNoneOfAbove(false);
|
|
67
65
|
}
|
|
68
66
|
});
|
|
69
|
-
}
|
|
70
67
|
};
|
|
71
68
|
|
|
72
69
|
export { useGlibSelectable, watchNoneOfAbove };
|
|
@@ -9,18 +9,15 @@
|
|
|
9
9
|
:menu-props="{ maxWidth: 0 }" @update:modelValue="onChange" @focus="focused = true" @blur="focused = false">
|
|
10
10
|
|
|
11
11
|
<template #item="{ props, item }">
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
:spec="spec"></select-item-with-icon>
|
|
22
|
-
<select-item-default v-else :context="props" :item="item" :spec="spec"></select-item-default>
|
|
23
|
-
</div>
|
|
12
|
+
<v-list-subheader v-if="item.type == 'view'">
|
|
13
|
+
<glib-component :spec="item" />
|
|
14
|
+
</v-list-subheader>
|
|
15
|
+
<v-divider v-else-if="item.divider"></v-divider>
|
|
16
|
+
<select-item-with-image v-else-if="item.imageUrl" :context="props" :item="item"
|
|
17
|
+
:spec="spec"></select-item-with-image>
|
|
18
|
+
<select-item-with-icon v-else-if="item.icon" :context="props" :item="item"
|
|
19
|
+
:spec="spec"></select-item-with-icon>
|
|
20
|
+
<select-item-default v-else :context="props" :item="item" :spec="spec"></select-item-default>
|
|
24
21
|
</template>
|
|
25
22
|
|
|
26
23
|
<template #prepend-item>
|
|
@@ -38,7 +35,7 @@
|
|
|
38
35
|
|
|
39
36
|
<template v-if="useChips" #selection="{ item, index }">
|
|
40
37
|
<v-chip v-if="index < maxVisibleChips" :density="density" closable @click:close="removeItem(item)">
|
|
41
|
-
<span>{{ item.
|
|
38
|
+
<span>{{ item.text }}</span>
|
|
42
39
|
</v-chip>
|
|
43
40
|
<v-chip
|
|
44
41
|
v-if="!expanded && chipExceedsTwoLines && visibleChipCount < fieldModel.length && index === visibleChipCount"
|
|
@@ -67,10 +64,6 @@
|
|
|
67
64
|
|
|
68
65
|
<input v-for="(item, index) in values" :key="index" type="hidden" :disabled="inputDisabled" :name="fieldName"
|
|
69
66
|
:value="item" />
|
|
70
|
-
|
|
71
|
-
<select hidden aria-hidden="true">
|
|
72
|
-
<option v-for="(opt, i) in selectableOptions" :key="i" :value="opt.value">{{ opt.text }}</option>
|
|
73
|
-
</select>
|
|
74
67
|
</div>
|
|
75
68
|
</template>
|
|
76
69
|
|
|
@@ -366,9 +359,6 @@ export default {
|
|
|
366
359
|
emptyValue() {
|
|
367
360
|
return [null];
|
|
368
361
|
},
|
|
369
|
-
selectableOptions() {
|
|
370
|
-
return this.normalizedOptions.filter(o => !o.divider && o.type !== 'view');
|
|
371
|
-
},
|
|
372
362
|
density() {
|
|
373
363
|
return determineDensity(this.spec.styleClasses);
|
|
374
364
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-list-item v-bind="props.context" :disabled="props.item.
|
|
2
|
+
<v-list-item v-bind="props.context" :disabled="props.item.disabled">
|
|
3
3
|
<template #prepend="{ isActive }">
|
|
4
4
|
<v-checkbox-btn v-if="props.spec.multiple" :model-value="isActive"></v-checkbox-btn>
|
|
5
5
|
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-list-item v-bind="props.context" :disabled="props.item.
|
|
2
|
+
<v-list-item v-bind="props.context" :disabled="props.item.disabled">
|
|
3
3
|
<template #prepend="{ isActive }">
|
|
4
4
|
<v-checkbox-btn v-if="props.spec.multiple" :model-value="isActive"></v-checkbox-btn>
|
|
5
|
-
<glib-component :spec="itemIconSpec(props.item.
|
|
5
|
+
<glib-component :spec="itemIconSpec(props.item.icon)" />
|
|
6
6
|
</template>
|
|
7
7
|
</v-list-item>
|
|
8
8
|
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-list-item v-bind="props.context" :disabled="props.item.
|
|
2
|
+
<v-list-item v-bind="props.context" :disabled="props.item.disabled">
|
|
3
3
|
<template #prepend>
|
|
4
4
|
<v-avatar size="24" color="white">
|
|
5
|
-
<v-img :src="props.item.
|
|
5
|
+
<v-img :src="props.item.imageUrl"></v-img>
|
|
6
6
|
</v-avatar>
|
|
7
7
|
</template>
|
|
8
8
|
<template #append="{ isActive }">
|
|
@@ -35,6 +35,18 @@ export default {
|
|
|
35
35
|
cssClasses: function () {
|
|
36
36
|
const classes = this.$classes().concat("layouts-flow");
|
|
37
37
|
|
|
38
|
+
// Use Vuetify utility classes for display/flex-wrap so that responsive
|
|
39
|
+
// display overrides (d-sm-none, d-none, d-md-flex …) provided via the
|
|
40
|
+
// spec's styleClasses live in the same @layer vuetify-utilities.helpers
|
|
41
|
+
// and Vuetify's own CSS source order makes them win over these defaults.
|
|
42
|
+
if (!classes.includes("d-flex") && !classes.includes("d-none") &&
|
|
43
|
+
!classes.includes("d-block") && !classes.includes("d-inline")) {
|
|
44
|
+
classes.push("d-flex");
|
|
45
|
+
}
|
|
46
|
+
if (!classes.some((c) => typeof c === "string" && c.startsWith("flex-"))) {
|
|
47
|
+
classes.push("flex-wrap");
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
const configs = {
|
|
39
51
|
'top': 'align-start',
|
|
40
52
|
'middle': 'align-center',
|
|
@@ -148,13 +160,10 @@ export default {
|
|
|
148
160
|
};
|
|
149
161
|
</script>
|
|
150
162
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
display: inline-block;
|
|
159
|
-
} */
|
|
160
|
-
</style>
|
|
163
|
+
<!-- No CSS for display/flex-wrap here.
|
|
164
|
+
In Vuetify 4, responsive display classes (d-sm-none, d-none …) live in
|
|
165
|
+
@layer vuetify-utilities.helpers. Any author CSS that sets display
|
|
166
|
+
(even in a lower-priority layer) can interfere because of layer ordering
|
|
167
|
+
in the Vite module graph. Instead we add d-flex and flex-wrap as Vuetify
|
|
168
|
+
utility class strings in cssClasses() so they sit in the same layer as
|
|
169
|
+
d-sm-none/d-none and Vuetify's source order makes responsive classes win. -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-list v-if="loadIf" class="py-0" :class="$classes()" :style="$styles()">
|
|
3
|
-
<div ref="
|
|
3
|
+
<div :ref="setTopAnchorEl">
|
|
4
4
|
<div v-if="prevPageUrl" class="py-3 px-4">
|
|
5
5
|
Loading...
|
|
6
6
|
</div>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
</div>
|
|
38
38
|
</template>
|
|
39
39
|
|
|
40
|
-
<div ref="
|
|
40
|
+
<div :ref="setBottomAnchorEl">
|
|
41
41
|
<div v-if="nextPageUrl" class="py-3 px-4">
|
|
42
42
|
Loading...
|
|
43
43
|
</div>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "glib-web",
|
|
4
|
-
"version": "6.0.
|
|
4
|
+
"version": "6.0.2",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
"pretest": "eslint .",
|
|
10
10
|
"lint": "eslint .",
|
|
11
11
|
"lint:fix": "eslint . --fix",
|
|
12
|
-
"test": "env -u ELECTRON_RUN_AS_NODE cypress run --browser chrome
|
|
13
|
-
"test:component": "env -u ELECTRON_RUN_AS_NODE cypress run --component",
|
|
12
|
+
"test": "env -u ELECTRON_RUN_AS_NODE cypress run --browser chrome",
|
|
14
13
|
"test:coverage": "env -u ELECTRON_RUN_AS_NODE VITE_COVERAGE=true cypress run --browser chrome && env -u ELECTRON_RUN_AS_NODE VITE_COVERAGE=true cypress run --component && nyc report"
|
|
15
14
|
},
|
|
16
15
|
"author": "",
|