glib-web 3.0.5 → 3.0.6

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.
@@ -1,15 +1,254 @@
1
1
  <template>
2
- <v-list-item :key="spec.title" :title="spec.title" :subtitle="spec.subtitle" :prepend-avatar="spec.imageUrl"
3
- :prepend-icon="spec.icon?.material?.name" @click="$event => spec.onClick ? $onClick() : null"></v-list-item>
2
+ <component :is="componentName" :href="$href()" class="thumbnail" :class="cssClasses" @[clickCondition]="$onClick()">
3
+ <panels-responsive :spec="spec.header" />
4
+ <div style="display:flex;">
5
+ <!-- <div v-if="spec.leftOuterButtons" style="display:flex; margin-top:10px;">
6
+ <template v-for="(item, index) in spec.leftOuterButtons" :key="index">
7
+ <common-button
8
+ :spec="buttonSpec(item)"
9
+ :disabled="$isBusy"
10
+ />
11
+ </template>
12
+ </div> -->
13
+
14
+ <v-list-item
15
+ v-longclick="$onLongPress"
16
+ class="item-content"
17
+ :style="columnStyles()"
18
+
19
+ >
20
+ <!-- <v-icon v-if="spec.onReorder" class="handle">drag_indicator</v-icon> -->
21
+
22
+ <!-- Specify a key to prevent reuse which causes an issue where the checkbox would use the previous name. -->
23
+ <fields-check
24
+ v-if="checkSpec"
25
+ :key="checkSpec.name"
26
+ :spec="checkSpec"
27
+ />
28
+
29
+ <template v-slot:prepend>
30
+ <div style="display: flex">
31
+ <div v-if="spec.leftButtons">
32
+ <template v-for="(item, index) in spec.leftButtons" :key="index">
33
+ <glib-button
34
+ :spec="buttonSpec(item)"
35
+ :disabled="$isBusy"
36
+ />
37
+ </template>
38
+ </div>
39
+
40
+ <common-icon v-if="spec.icon" :spec="spec.icon" />
41
+ </div>
42
+ </template>
43
+
44
+ <!-- <v-list-item-avatar
45
+ v-if="$type.isString(spec.imageUrl)"
46
+ :tile="!spec.avatar"
47
+ style="display:flex;"
48
+ class="left-thumbnail"
49
+ :size="spec.imageSize"
50
+ >
51
+ <img :src="spec.imageUrl" />
52
+ </v-list-item-avatar> -->
53
+
54
+ <!-- <div v-else class="left-icon">
55
+ <v-list-item-avatar v-if="$type.isObject(spec.icon)">
56
+ <common-icon :spec="spec.icon" />
57
+ </v-list-item-avatar>
58
+ </div> -->
59
+
60
+ <div>
61
+ <v-text-field
62
+ v-if="spec.fieldTitleName"
63
+ :name="spec.fieldTitleName"
64
+ :value="spec.title"
65
+ />
66
+ <v-list-item-title v-else>{{ spec.title }}</v-list-item-title>
67
+
68
+ <v-list-item-subtitle v-if="spec.subtitle">{{
69
+ spec.subtitle
70
+ }}</v-list-item-subtitle>
71
+ <v-list-item-subtitle v-if="spec.subsubtitle">{{
72
+ spec.subsubtitle
73
+ }}</v-list-item-subtitle>
74
+
75
+ <div v-if="hasChips" class="chips">
76
+ <template v-for="(item, index) in chips" :key="index">
77
+ <common-chip :spec="item" />
78
+ </template>
79
+ </div>
80
+
81
+ <panels-responsive v-if="spec.body" :spec="spec.body" />
82
+ </div>
83
+
84
+ <template v-slot:append>
85
+ <template v-for="(item, index) in spec.rightButtons" :key="index">
86
+ <glib-button
87
+ :spec="buttonSpec(item)"
88
+ :disabled="$isBusy"
89
+ />
90
+ </template>
91
+ </template>
92
+
93
+ <!-- Deprecated -->
94
+ <!-- <templates-menu :edit-buttons="editButtons" /> -->
95
+ </v-list-item>
96
+ <panels-responsive :spec="spec.right" />
97
+ </div>
98
+ <panels-responsive :spec="spec.footer" />
99
+ </component>
4
100
  </template>
101
+
5
102
  <script>
103
+ import CheckField from "../components/fields/check.vue";
104
+
6
105
  export default {
106
+ components: {
107
+ "fields-check": CheckField
108
+ },
7
109
  props: {
8
110
  spec: { type: Object, required: true },
111
+ responsiveCols: { type: Number, default: () => 0 }
112
+ },
113
+ data() {
114
+ return {
115
+ // editButtons: []
116
+ };
117
+ },
118
+ computed: {
119
+ componentName() {
120
+ // Use `a` to enable "open in new tab".
121
+ return this.clickCondition ? "a" : "div";
122
+ // return "div"
123
+ },
124
+ cssClasses() {
125
+ return this.$classes(this.spec, "templates/thumbnail");
126
+ },
127
+ clickCondition() {
128
+ if (this.spec.onClick || this.spec.onLongPress) {
129
+ // This will show the clickable indication
130
+ return "click";
131
+ }
132
+ return null;
133
+ },
134
+ hasChips() {
135
+ return this.spec.chips && this.spec.chips.length > 0;
136
+ },
137
+ // Implemented as computed so that it gets reflected when reordering
138
+ chips() {
139
+ return (this.spec.chips || []).map(item => {
140
+ var color = null;
141
+ this.$type.ifArray(item.styleClasses, classes => {
142
+ for (const val of ["success", "info", "warning", "error"]) {
143
+ if (classes.includes(val)) {
144
+ color = val;
145
+ }
146
+ }
147
+ });
148
+ return Object.assign({}, item, { color: color, view: "chip" });
149
+ });
150
+ },
151
+ // Implemented as computed so that it gets reflected when navigating to another list containing check fields.
152
+ checkSpec() {
153
+ if (this.spec.fieldCheckName) {
154
+ return {
155
+ view: "fields/checkGroup",
156
+ name: this.spec.fieldCheckName,
157
+ checkValue: true,
158
+ valueIf: this.spec.fieldCheckValueIf,
159
+ padding: { left: 16 }
160
+ };
161
+ }
162
+ return null;
163
+ }
164
+ // cssStyles() {
165
+ // const styles = this.$styles();
166
+ // // switch(this.spec.align) {
167
+ // // case 'middle':
168
+ // // styles['align-items'] = 'center'
169
+ // // break
170
+ // // case 'bottom':
171
+ // // styles['align-items'] = 'flex-end'
172
+ // // break
173
+ // // default:
174
+ // // styles['align-items'] = 'flex-start'
175
+ // // }
176
+ // return styles;
177
+ // },
9
178
  },
10
179
  methods: {
11
180
  $ready() {
181
+ // this.editButtons = this.spec.editButtons || [];
182
+ },
183
+ buttonSpec(item) {
184
+ // Classes should be coming from the backend
185
+ // const styleClasses = ["text", "x-small"]
186
+ // if (!item.text) {
187
+ // styleClasses.push("icon")
188
+ // }
189
+
190
+ return Object.assign({}, item, {
191
+ view: "button"
192
+ });
193
+ },
194
+ columnStyles() {
195
+ if (this.responsiveCols) {
196
+ return `width: ${100 / this.responsiveCols}%; float: left;`;
197
+ }
12
198
  }
13
199
  }
200
+ };
201
+ </script>
202
+
203
+ <style lang="scss">
204
+ .chips > * {
205
+ margin-right: 10px;
206
+ }
207
+
208
+ .v-list-item__content {
209
+ width: 100%;
210
+ }
211
+
212
+ .thumbnail {
213
+ // Override this when using the `right` property.
214
+ .item-content {
215
+ width: 100%;
216
+ }
217
+ }
218
+ </style>
219
+
220
+ <style lang="scss" scoped>
221
+ a.thumbnail {
222
+ color: inherit;
223
+ text-decoration: inherit;
224
+ display: block;
225
+ }
226
+
227
+ .item-content {
228
+ display: flex;
229
+
230
+ &.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line {
231
+ padding-inline-start: 0;
232
+ padding-inline-end: 0;
233
+ }
234
+ }
235
+
236
+ @media (min-width: 600px) {
237
+ .left-thumbnail.v-avatar.v-list-item__avatar {
238
+ margin: 6px 6px 6px 6px;
239
+ width: 60px;
240
+ height: 60px;
241
+ }
242
+ .left-icon {
243
+ // margin-left: 16px;
244
+ margin-left: 4px;
245
+ }
246
+ // .left-universal {
247
+ // padding-left: 16px;
248
+ // }
249
+ // .handle {
250
+ // // margin-left: 10px;
251
+ // cursor: move;
252
+ // }
14
253
  }
15
- </script>
254
+ </style>
package/utils/constant.js CHANGED
@@ -1,4 +1,47 @@
1
1
  const colors = ['primary', 'secondary', 'success', 'warning', 'info', 'error']
2
2
  const variants = ['text', 'flat', 'elevated', 'outlined', 'plain', 'tonal']
3
+ const densities = ['comfortable', 'compact']
4
+ const sizes = ['x-small', 'small', 'large', 'x-large']
5
+
6
+ function determineColor(styleClasses, defaultColor) {
7
+ const classes = styleClasses || []
8
+ for (const value of colors) {
9
+ if (classes.includes(value)) {
10
+ return value;
11
+ }
12
+ }
13
+ return defaultColor
14
+ }
15
+
16
+ function determineVariant(styleClasses, defaultVariant) {
17
+ const classes = styleClasses || []
18
+ for (const value of variants) {
19
+ if (classes.includes(value)) {
20
+ return value;
21
+ }
22
+ }
23
+ return defaultVariant
24
+ }
25
+
26
+ function determineDensity(styleClasses, defaultDensity) {
27
+ const classes = styleClasses || []
28
+ for (const value of densities) {
29
+ if (classes.includes(value)) {
30
+ return value;
31
+ }
32
+ }
33
+ return defaultDensity
34
+ }
35
+
36
+ function determineSize(styleClasses, defaultSize) {
37
+ const classes = styleClasses || []
38
+ for (const value of sizes) {
39
+ if (classes.includes(value)) {
40
+ return value;
41
+ }
42
+ }
43
+ return defaultSize
44
+ }
45
+
46
+ export { colors, variants, determineColor, determineVariant, determineDensity, determineSize }
3
47
 
4
- export { colors, variants }
package/utils/http.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import Type from "./type";
2
2
  import Action from "../action";
3
- import eventBus from "./eventBus";
4
3
  import { nextTick } from 'vue'
5
4
  import { vueApp } from "../store";
6
5
 
package/utils/launch.js CHANGED
@@ -39,17 +39,27 @@ class LaunchPopover {
39
39
 
40
40
  if (component) {
41
41
  const placeholder = document.createElement('div')
42
- component.$el.parentElement.appendChild(placeholder)
42
+
43
+ // component.$el.parentElement.appendChild(placeholder)
44
+
45
+ // Attach the popover to the document body to prevent clipping caused by the parent's `overflow` property.
46
+ // See https://stackoverflow.com/questions/51393427/z-index-to-ignore-max-height-and-always-come-on-top
47
+ document.body.appendChild(placeholder);
48
+
43
49
  instance.mount(placeholder);
44
50
 
45
51
  const reference = component.$el instanceof HTMLElement ? component.$el : component.$el.nextElementSibling
46
52
 
47
53
  const floating = placeholder
48
- const placement = properties.location || 'right'
54
+ const placement = properties.placement || 'right'
49
55
  const offsetSize = properties.offset || 8
56
+
57
+ // These properties need to be set to get an accurate calculation. See https://floating-ui.com/docs/computeposition
58
+ Object.assign(placeholder.style, { position: 'absolute', display: 'block', top: 0, left: 0 });
59
+
50
60
  computePosition(reference, floating, { placement: placement, middleware: [shift(), offset(offsetSize)] })
51
61
  .then(({ x, y }) => {
52
- Object.assign(placeholder.style, { top: `${y}px`, left: `${x}px`, position: 'absolute', zIndex: 1000, display: 'block' })
62
+ Object.assign(placeholder.style, { top: `${y}px`, left: `${x}px`, zIndex: 1200 });
53
63
  })
54
64
  } else {
55
65
  console.error("A popover has to be displayed in a component");
@@ -1,188 +0,0 @@
1
- <template>
2
- <div style="display:flex;" class="thumbnail" :class="cssClasses">
3
- <div v-if="spec.leftOuterButtons" class="left-universal" style="display:flex; margin-top:10px;">
4
- <template v-for="(item, index) in spec.leftOuterButtons" :key="index">
5
- <common-button :spec="buttonSpec(item)" :disabled="$isBusy" />
6
- </template>
7
- </div>
8
-
9
- <v-list-item v-longclick="$onLongPress" :href="$href()" class="item-content" :style="columnStyles()"
10
- @[clickCondition]="$onClick()">
11
- <!-- <v-icon v-if="spec.onReorder" class="handle">drag_indicator</v-icon> -->
12
-
13
- <!-- Specify a key to prevent reuse which causes an issue where the checkbox would use the previous name. -->
14
- <fields-check v-if="checkSpec" :key="checkSpec.name" :spec="checkSpec" />
15
-
16
- <div v-if="spec.leftButtons" class="left-universal">
17
- <template v-for="(item, index) in spec.leftButtons" :key="index">
18
- <rich-button :spec="buttonSpec(item)" :disabled="$isBusy" />
19
- </template>
20
- </div>
21
-
22
- <!-- <v-list-item-avatar v-if="$type.isString(spec.imageUrl)" :tile="!spec.avatar || null" style="display:flex;"
23
- class="left-thumbnail" :size="spec.imageSize">
24
- <img :src="spec.imageUrl" />
25
- </v-list-item-avatar> -->
26
- <!-- <v-list-item-avatar v-else-if="$type.isObject(spec.icon)">
27
- <common-icon :spec="spec.icon" />
28
- </v-list-item-avatar> -->
29
- <div v-else class="left-icon" v-if="$type.isObject(spec.icon)">
30
- <common-icon :spec="spec.icon" />
31
- </div>
32
-
33
- <div style="display:flex;width: 100%">
34
- <v-text-field v-if="spec.fieldTitleName" :name="spec.fieldTitleName" :value="spec.title" />
35
- <v-list-item-title v-else>{{ spec.title }}</v-list-item-title>
36
-
37
- <v-list-item-subtitle v-if="spec.subtitle">{{
38
- spec.subtitle
39
- }}</v-list-item-subtitle>
40
- <v-list-item-subtitle v-if="spec.subsubtitle">{{
41
- spec.subsubtitle
42
- }}</v-list-item-subtitle>
43
-
44
- <div class="chips">
45
- <template v-for="(item, index) in chips" :key="index">
46
- <common-chip :spec="item" />
47
- </template>
48
- </div>
49
-
50
- <!-- NOTE: Experimental -->
51
- <panels-responsive :spec="spec.accessory" />
52
- </div>
53
-
54
- <template v-for="(item, index) in spec.rightButtons" :key="index">
55
- <rich-button :spec="buttonSpec(item)" :disabled="$isBusy" />
56
- </template>
57
-
58
- <templates-menu :edit-buttons="editButtons" />
59
- </v-list-item>
60
- </div>
61
- </template>
62
-
63
- <script>
64
- import CheckField from "../components/fields/check.vue";
65
-
66
- export default {
67
- components: {
68
- "fields-check": CheckField,
69
- },
70
- props: {
71
- spec: { type: Object, required: true },
72
- responsiveCols: { type: Number, default: () => 0 },
73
- },
74
- data() {
75
- return {
76
- // accessory: {},
77
- editButtons: []
78
- // checkSpec: null
79
- };
80
- },
81
- computed: {
82
- cssClasses() {
83
- return this.$classes(this.spec, "templates/thumbnail");
84
- },
85
- clickCondition() {
86
- if (this.spec.onClick || this.spec.onLongPress) {
87
- // This will show the clickable indication
88
- return "click";
89
- }
90
- return null;
91
- },
92
- // Implemented as computed so that it gets reflected when reordering
93
- chips() {
94
- return (this.spec.chips || []).map((item) => {
95
- var color = null;
96
- this.$type.ifArray(item.styleClasses, (classes) => {
97
- for (const val of ["success", "info", "warning", "error"]) {
98
- if (classes.includes(val)) {
99
- color = val;
100
- }
101
- }
102
- });
103
- return Object.assign({}, item, { color: color, view: "chip" });
104
- });
105
- },
106
- // Implemented as computed so that it gets reflected when navigating to another list containing check fields.
107
- checkSpec() {
108
- if (this.spec.fieldCheckName) {
109
- return {
110
- view: "fields/checkGroup",
111
- name: this.spec.fieldCheckName,
112
- checkValue: true,
113
- valueIf: this.spec.fieldCheckValueIf,
114
- padding: { left: 16 },
115
- };
116
- }
117
- return null;
118
- }
119
- // cssStyles() {
120
- // const styles = this.$styles();
121
- // // switch(this.spec.align) {
122
- // // case 'middle':
123
- // // styles['align-items'] = 'center'
124
- // // break
125
- // // case 'bottom':
126
- // // styles['align-items'] = 'flex-end'
127
- // // break
128
- // // default:
129
- // // styles['align-items'] = 'flex-start'
130
- // // }
131
- // return styles;
132
- // },
133
- },
134
- methods: {
135
- $ready() {
136
- // this.accessory = { childViews: this.spec.accessoryViews };
137
- this.editButtons = this.spec.editButtons || [];
138
- },
139
- buttonSpec(item) {
140
- return Object.assign({}, item, {
141
- view: "button-v1",
142
- styleClasses: item.text ? ["text"] : ["icon"],
143
- });
144
- },
145
- columnStyles() {
146
- if (this.responsiveCols) {
147
- return `width: ${100 / this.responsiveCols}%; float: left;`;
148
- }
149
- },
150
- },
151
- };
152
- </script>
153
-
154
- <style lang="scss">
155
- .chips>* {
156
- margin-right: 10px;
157
- }
158
- </style>
159
-
160
- <style lang="scss" scoped>
161
- .item-content {
162
- padding-left: 0;
163
- padding-right: 0;
164
- display: flex;
165
- }
166
-
167
- @media (min-width: 600px) {
168
- .left-thumbnail.v-avatar.v-list-item__avatar {
169
- margin: 6px 6px 6px 6px;
170
- width: 60px;
171
- height: 60px;
172
- }
173
-
174
- .left-icon {
175
- // margin-left: 16px;
176
- margin-left: 4px;
177
- }
178
-
179
- .left-universal {
180
- padding-left: 16px;
181
- }
182
-
183
- // .handle {
184
- // // margin-left: 10px;
185
- // cursor: move;
186
- // }
187
- }
188
- </style>