@thinkpixellab-public/px-vue 3.0.44 → 4.0.1
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/README.md +22 -64
- package/{components → bases}/PxBase.vue +4 -0
- package/bases/PxBaseDate.vue +49 -0
- package/bases/PxBaseIcon.vue +32 -0
- package/bases/PxBaseItems.vue +105 -0
- package/bases/PxBaseItemsSelect.vue +415 -0
- package/{components → bases}/PxBaseMobileAware.vue +4 -2
- package/{components → bases}/PxBaseResize.vue +11 -4
- package/bases/PxBaseScroll.vue +46 -0
- package/bases/PxBaseToggle.vue +67 -0
- package/bases/PxBaseUniqueId.vue +18 -0
- package/{components → bases}/PxBaseVariants.vue +10 -0
- package/{components → bases}/PxBaseVariantsOverride.vue +4 -2
- package/{components → bases}/PxBaseVisible.vue +2 -0
- package/components/PxArrowScroller.vue +9 -7
- package/components/PxAspect.vue +28 -10
- package/components/PxAutoClamp.vue +3 -1
- package/components/PxBalancedText.vue +22 -9
- package/components/PxButton.vue +42 -0
- package/components/PxCalendar.vue +3 -2
- package/components/PxCard.vue +2 -3
- package/components/PxCardGrid.vue +3 -1
- package/components/PxClock.vue +5 -2
- package/components/PxContain.vue +3 -1
- package/components/PxCopyText.vue +6 -2
- package/components/PxDatePicker.vue +6 -4
- package/components/PxDropdown.vue +77 -61
- package/components/PxExpander.vue +36 -20
- package/components/PxFit.vue +4 -1
- package/components/PxFlex.vue +27 -17
- package/components/PxFloat.vue +152 -86
- package/components/PxIcon.vue +88 -15
- package/components/PxIconButton.vue +43 -29
- package/components/PxIdUniquer.vue +5 -1
- package/components/PxModal.vue +1 -0
- package/components/PxNineGrid.vue +4 -0
- package/components/PxPivot.vue +20 -8
- package/components/PxPopup.vue +8 -6
- package/components/PxProgressCircle.vue +3 -3
- package/components/PxQrCode.vue +6 -2
- package/components/PxRadioButton.vue +30 -10
- package/components/PxResizer.vue +207 -0
- package/components/PxSideDrawer.vue +16 -10
- package/components/PxSlideTransition.vue +3 -1
- package/components/PxSlides.vue +4 -3
- package/components/PxSpinner.vue +4 -2
- package/components/PxSvg.vue +97 -45
- package/components/PxSwiperSlide.vue +3 -7
- package/components/PxSyncHeight.vue +3 -0
- package/components/PxTable.vue +8 -2
- package/components/PxToggle.vue +9 -7
- package/components/PxToggleButton.vue +94 -60
- package/components/PxToggleButtonList.vue +61 -38
- package/components/PxTransitionExpand.vue +8 -1
- package/components/PxValidator.vue +5 -2
- package/package.json +37 -29
- package/plugins/common-client.js +19 -8
- package/plugins/common.js +35 -53
- package/plugins/filters/kebab.js +1 -1
- package/plugins/filters/unkebab.js +11 -0
- package/stories/PxAspect.stories.js +62 -0
- package/stories/PxBalancedText.stories.js +57 -0
- package/stories/PxButton.stories.js +44 -0
- package/stories/PxDropdown.stories.js +49 -0
- package/stories/PxExpander.stories.js +31 -0
- package/stories/PxFloat.stories.js +69 -0
- package/stories/PxIcon.mdx +62 -0
- package/stories/PxIcon.stories.js +70 -0
- package/stories/PxPivot.stories.js +38 -0
- package/stories/PxRadioButton.stories.js +33 -0
- package/stories/PxSvg.stories.js +37 -0
- package/stories/PxToggleButton.stories.js +86 -0
- package/stories/PxToggleButtonList.stories.js +97 -0
- package/stories/assets/alpha.svg +6 -0
- package/stories/helpers/extractArgTypes.js +31 -0
- package/stories/helpers/sampleData.js +28 -0
- package/stories/helpers/scratch.vue +30 -0
- package/styles/px.scss +1 -1
- package/test/PxBaseItems.test.js +92 -0
- package/test/PxBaseItemsSelect.test.js +430 -0
- package/utils/getFeatherIcons.js +25 -0
- package/utils/hasSlot.js +9 -0
- package/utils/uniqueId.js +30 -0
- package/vite.config.js +34 -0
- package/assets/icons/calendar.svg +0 -6
- package/assets/icons/check.svg +0 -1
- package/assets/icons/close-sm.svg +0 -1
- package/assets/icons/close.svg +0 -1
- package/assets/icons/copy.svg +0 -1
- package/assets/icons/dropdown.svg +0 -1
- package/assets/icons/invalid.svg +0 -1
- package/assets/icons/menu.svg +0 -1
- package/assets/icons/nav-next.svg +0 -1
- package/assets/icons/nav-prev.svg +0 -1
- package/assets/icons/sort-asc.svg +0 -1
- package/assets/icons/sort-desc.svg +0 -1
- package/assets/test/README.md +0 -1
- package/assets/test/trash.svg +0 -8
- package/components/PxBaseDate.vue +0 -27
- package/components/PxBaseItems.vue +0 -72
- package/components/PxBaseItemsSelect.vue +0 -230
- package/components/PxBaseToggle.vue +0 -56
- package/components/PxFeatherIcon.vue +0 -29
- package/components/PxFeatherIconButton.vue +0 -19
- package/components/PxPortal.vue +0 -138
- package/components/PxPortalTarget.vue +0 -27
- package/components/PxStylesPreview.vue +0 -159
- package/components/PxSwiper.vue +0 -271
- package/components/PxTabs.vue +0 -1
- package/components/PxTextbox.vue +0 -90
- package/components/README.md +0 -0
- package/plugins/common-lib.js +0 -4
- package/plugins/common-vue3.js +0 -60
- package/plugins/mixins/eventBus.js +0 -30
- package/styles/helpers.scss +0 -14
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
#VUE3 Done (has breaking changes)
|
|
3
|
+
-->
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
import PxBaseItems from './PxBaseItems.vue';
|
|
7
|
+
import utils from '../utils/utils.js';
|
|
8
|
+
|
|
9
|
+
// helper to define what an "empty" key or set of keys looks like
|
|
10
|
+
const isKeySetEmpty = keyOrKeys => {
|
|
11
|
+
return (
|
|
12
|
+
keyOrKeys == null ||
|
|
13
|
+
keyOrKeys == undefined ||
|
|
14
|
+
(Array.isArray(keyOrKeys) && keyOrKeys.length == 0)
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// helper to ensure that a potential key or set of keys is an array
|
|
19
|
+
const ensureSet = valueOrArray => {
|
|
20
|
+
if (isKeySetEmpty(valueOrArray)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return Array.isArray(valueOrArray) ? valueOrArray : [valueOrArray];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
mixins: [PxBaseItems],
|
|
29
|
+
|
|
30
|
+
props: {
|
|
31
|
+
/**
|
|
32
|
+
* Set the selection as either a single item key or an array of item keys.
|
|
33
|
+
*/
|
|
34
|
+
selected: { default: null },
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* If true, the first item in a collection will be automatically selected on load or when
|
|
38
|
+
* items is updated and no other item is selected
|
|
39
|
+
*/
|
|
40
|
+
autoSelectFirst: { type: Boolean, default: false },
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
selectedKeys: [],
|
|
46
|
+
baseUpdateMode: 'single',
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
computed: {
|
|
51
|
+
/**
|
|
52
|
+
* Indicates whether the update event arg is a single key or an array of keys. Note that
|
|
53
|
+
* selection is always stored internally (selectedKeys) as an array of keys.
|
|
54
|
+
*
|
|
55
|
+
* Derived classes should override this to indicate the current update mode and can expose
|
|
56
|
+
* an additional prop to control it. We're returning the value of a data value so that it
|
|
57
|
+
* can be set when testing but there's no internal process that would ever change this
|
|
58
|
+
* value.
|
|
59
|
+
*
|
|
60
|
+
* In `single` mode the event is the first selected item or null when empty. The intended
|
|
61
|
+
* use is components that don't support multiselection.
|
|
62
|
+
*
|
|
63
|
+
* In `multi` mode the event is always an array with all selected items.
|
|
64
|
+
*
|
|
65
|
+
* @values single, multi
|
|
66
|
+
*/
|
|
67
|
+
updateMode() {
|
|
68
|
+
return this.baseUpdateMode;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns an array that contains the keys for all fo the items in items.
|
|
73
|
+
*/
|
|
74
|
+
itemKeys() {
|
|
75
|
+
return this.items.map(item => this.getItemKey(item));
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns the first selected key
|
|
80
|
+
*/
|
|
81
|
+
selectedKey() {
|
|
82
|
+
return this.selectedKeys?.length ? this.selectKeys[0] : null;
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns the currently selected items.
|
|
87
|
+
*/
|
|
88
|
+
selectedItems() {
|
|
89
|
+
return (this.selectedKeys || []).map(key => {
|
|
90
|
+
return this.getItem(key);
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns the first selected item or null if selection is empty.
|
|
96
|
+
*/
|
|
97
|
+
selectedItem() {
|
|
98
|
+
return this.selectedItems.length ? this.selectedItems[0] : null;
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns the indices of the currently selected items.
|
|
103
|
+
*/
|
|
104
|
+
selectedIndices() {
|
|
105
|
+
return (this.selectedKeys || []).map(key => {
|
|
106
|
+
return this.getItemKeyIndex(key);
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Returns the index of the first selected item or null if selection is empty.
|
|
112
|
+
*/
|
|
113
|
+
selectedIndex() {
|
|
114
|
+
return this.selectedIndices.length ? this.selectedIndices[0] : null;
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
watch: {
|
|
119
|
+
selected: {
|
|
120
|
+
immediate: true,
|
|
121
|
+
handler(nv, ov) {
|
|
122
|
+
// check for matching values
|
|
123
|
+
if (nv && ov && nv.length == ov.length) {
|
|
124
|
+
let match = true;
|
|
125
|
+
for (let i = 0; i < nv.length; i++) {
|
|
126
|
+
match = match && nv[i] == ov[i];
|
|
127
|
+
}
|
|
128
|
+
if (match) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
this.setSelection(nv);
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
selectedKeys: {
|
|
136
|
+
immediate: true,
|
|
137
|
+
handler() {
|
|
138
|
+
this.emitUpdateEvent();
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// selected(nv) {
|
|
143
|
+
// this.selectedKeys = this.ensureCorrectValue(nv);
|
|
144
|
+
// },
|
|
145
|
+
|
|
146
|
+
// items() {
|
|
147
|
+
// this.tryAutoSelect();
|
|
148
|
+
// },
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
mounted() {
|
|
152
|
+
if (this.autoSelectFirst && isKeySetEmpty(this.selected) && this.items?.length) {
|
|
153
|
+
this.selectAt(0);
|
|
154
|
+
}
|
|
155
|
+
// this.$nextTick(() => {
|
|
156
|
+
// this.tryAutoSelect();
|
|
157
|
+
// });
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
methods: {
|
|
161
|
+
/**
|
|
162
|
+
* Emit the change / update:selected event
|
|
163
|
+
*/
|
|
164
|
+
emitUpdateEvent() {
|
|
165
|
+
let updateArg;
|
|
166
|
+
|
|
167
|
+
if (this.updateMode == 'single') {
|
|
168
|
+
updateArg = this.selectedKeys.length ? this.selectedKeys[0] : null;
|
|
169
|
+
} else {
|
|
170
|
+
updateArg = this.selectedKeys;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this.$emit('change', updateArg);
|
|
174
|
+
this.$emit('update:selected', updateArg);
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Replace the current set of selected keys with the keys provided here. Keys that don't
|
|
179
|
+
* have a corresponding item in the items collection in items will be ignored.
|
|
180
|
+
*/
|
|
181
|
+
setSelection(keyOrKeys) {
|
|
182
|
+
const validKeys = ensureSet(keyOrKeys).filter(key => this.isValidItemKey(key));
|
|
183
|
+
this.selectedKeys = validKeys;
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// ----------------------------------------------------------------------
|
|
187
|
+
// Key-based methods
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Check if the provided key is selected.
|
|
191
|
+
*/
|
|
192
|
+
isSelected(key) {
|
|
193
|
+
return !!(this.selectedKeys?.length && this.selectedKeys.includes(key));
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Add the provided key or keys to the current selection.
|
|
198
|
+
*/
|
|
199
|
+
selectKeys(addKeyOrKeys, replaceSelection = 'auto') {
|
|
200
|
+
const replace = this.getShouldReplace(replaceSelection);
|
|
201
|
+
|
|
202
|
+
if (isKeySetEmpty(addKeyOrKeys)) {
|
|
203
|
+
if (replace) {
|
|
204
|
+
this.selectedKeys = [];
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const addKeys = ensureSet(addKeyOrKeys).filter(key => this.isValidItemKey(key));
|
|
210
|
+
|
|
211
|
+
if (replace) {
|
|
212
|
+
this.selectedKeys = addKeys;
|
|
213
|
+
return;
|
|
214
|
+
} else {
|
|
215
|
+
this.selectedKeys = [
|
|
216
|
+
...this.selectedKeys,
|
|
217
|
+
...addKeys.filter(key => !this.selectedKeys.includes(key)),
|
|
218
|
+
];
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Select the provided key and replace the selection if updateMode is 'single' or add to the
|
|
224
|
+
* selection if updateMode is 'multi'
|
|
225
|
+
*/
|
|
226
|
+
selectKey(key, replaceSelection = 'auto') {
|
|
227
|
+
this.selectKeys(key, this.getShouldReplace(replaceSelection));
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Select the provided key (and replace the current selection)
|
|
232
|
+
*/
|
|
233
|
+
selectKeyOnly(key) {
|
|
234
|
+
this.selectKeys(key, true);
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Select the provided key or keys (and replace the current selection)
|
|
239
|
+
*/
|
|
240
|
+
selectKeysOnly(addKeyOrKeys) {
|
|
241
|
+
this.selectKeys(addKeyOrKeys, true);
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Remove the provided key or keys from the current selection.
|
|
246
|
+
*/
|
|
247
|
+
unselectKeys(removeKeyOrKeys) {
|
|
248
|
+
const removeKeys = ensureSet(removeKeyOrKeys);
|
|
249
|
+
if (removeKeys.length) {
|
|
250
|
+
this.selectedKeys = this.selectedKeys.filter(key => !removeKeys.includes(key));
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Remove the provided key from the current selection (convenience for better syntax when
|
|
256
|
+
* working with 'single' mode).
|
|
257
|
+
*/
|
|
258
|
+
unselectKey(key) {
|
|
259
|
+
this.unselectKeys(key);
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Toggle selection of the given key.
|
|
264
|
+
*/
|
|
265
|
+
toggleKey(key) {
|
|
266
|
+
if (this.isSelected(key)) {
|
|
267
|
+
this.unselectKeys(key);
|
|
268
|
+
} else {
|
|
269
|
+
this.selectKeys(key);
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
// ----------------------------------------------------------------------
|
|
274
|
+
// Item-based methods
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Check if the provided key is selected.
|
|
278
|
+
*/
|
|
279
|
+
isItemSelected(item) {
|
|
280
|
+
return this.isSelected(this.getItemKey(item));
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Add the provided item or items to the current selection. (Note: this is a convenience
|
|
285
|
+
* method and selection will continue to be stored as keys.)
|
|
286
|
+
*/
|
|
287
|
+
selectItems(items, replaceSelection = 'auto') {
|
|
288
|
+
const keys = ensureSet(items).map(item => this.getItemKey(item));
|
|
289
|
+
this.selectKeys(keys, this.getShouldReplace(replaceSelection));
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Select the provided item and replace the selection if updateMode is 'single' or add to
|
|
294
|
+
* the selection if updateMode is 'multi'. (Note: this is a convenience method and selection
|
|
295
|
+
* will continue to be stored as keys.)
|
|
296
|
+
*/
|
|
297
|
+
selectItem(item, replaceSelection = 'auto') {
|
|
298
|
+
this.selectItems(item, this.getShouldReplace(replaceSelection));
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Select the provided item (and replace the current selection). (Note: this is a convenience
|
|
303
|
+
* method and selection will continue to be stored as keys.)
|
|
304
|
+
*/
|
|
305
|
+
selectItemOnly(item) {
|
|
306
|
+
this.selectItem(item, true);
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Select the provided item or items (and replace the current selection). (Note: this is a
|
|
311
|
+
* convenience method and selection will continue to be stored as keys.)
|
|
312
|
+
*/
|
|
313
|
+
selectItemsOnly(items) {
|
|
314
|
+
this.selectItems(items, true);
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Remove the provided item or items from the current selection.
|
|
319
|
+
*/
|
|
320
|
+
unselectItems(itemOrItems) {
|
|
321
|
+
const keys = ensureSet(itemOrItems).map(item => this.getItemKey(item));
|
|
322
|
+
this.unselectKeys(keys);
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Remove the provided key from the current selection (convenience for better syntax when
|
|
327
|
+
* working with 'single' mode).
|
|
328
|
+
*/
|
|
329
|
+
unselectItem(item) {
|
|
330
|
+
this.unselectItems(item);
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Toggle selection of the given item.
|
|
335
|
+
*/
|
|
336
|
+
toggleItem(item) {
|
|
337
|
+
const key = this.getItemKey(item);
|
|
338
|
+
if (key) {
|
|
339
|
+
this.toggleKey(key);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
// ----------------------------------------------------------------------
|
|
344
|
+
// Index-based methods
|
|
345
|
+
|
|
346
|
+
selectAt(index, replaceSelection = 'auto') {
|
|
347
|
+
const keyAtIndex = this.itemKeys[index];
|
|
348
|
+
|
|
349
|
+
const replace =
|
|
350
|
+
replaceSelection == 'auto' ? this.updateMode == 'single' : replaceSelection;
|
|
351
|
+
|
|
352
|
+
this.selectKeys(keyAtIndex, replace);
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
selectAtSafe(index, wrap = false, replaceSelection = 'auto') {
|
|
356
|
+
const replace =
|
|
357
|
+
replaceSelection == 'auto' ? this.updateMode == 'single' : replaceSelection;
|
|
358
|
+
|
|
359
|
+
index = utils.arraySafeIndex(this.items, index, 0, wrap);
|
|
360
|
+
this.selectAt(index, replace);
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
selectOffset(offsetFromSelectedIndex, wrap = true) {
|
|
364
|
+
if (this.selectedIndex === null) {
|
|
365
|
+
this.selectAt(0);
|
|
366
|
+
} else {
|
|
367
|
+
const index = utils.arraySafeIndex(
|
|
368
|
+
this.items,
|
|
369
|
+
this.selectedIndex,
|
|
370
|
+
offsetFromSelectedIndex,
|
|
371
|
+
wrap
|
|
372
|
+
);
|
|
373
|
+
this.selectAt(index, true);
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
selectNext(wrap = true) {
|
|
378
|
+
this.selectOffset(1, wrap);
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
selectPrevious(wrap = true) {
|
|
382
|
+
this.selectOffset(-1, wrap);
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
unselectAt(index) {},
|
|
386
|
+
|
|
387
|
+
// ----------------------------------------------------------------------
|
|
388
|
+
// Other Selection
|
|
389
|
+
|
|
390
|
+
selectAll() {
|
|
391
|
+
if (Array.isArray(this.items) && this.items.length) {
|
|
392
|
+
if (this.updateMode == 'multi') {
|
|
393
|
+
this.selectedKeys = this.itemKeys;
|
|
394
|
+
} else {
|
|
395
|
+
this.selectedKeys = ensureSet(this.getItemKey(this.items[0]));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
selectNone() {
|
|
401
|
+
this.selectedKeys = [];
|
|
402
|
+
},
|
|
403
|
+
|
|
404
|
+
// ----------------------------------------------------------------------
|
|
405
|
+
// Internal / helper
|
|
406
|
+
|
|
407
|
+
getShouldReplace(value) {
|
|
408
|
+
if (value == 'auto') {
|
|
409
|
+
return this.updateMode == 'single';
|
|
410
|
+
}
|
|
411
|
+
return value;
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
</script>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
+
#VUE3 Todo
|
|
3
|
+
|
|
2
4
|
Use for global mobile awareness in javascript. This doesn't actually handle mobile detection
|
|
3
5
|
but provides a consistent interface for communicating between a single component that does
|
|
4
6
|
the detection and other components that subscribe to an eventbus and update a property called
|
|
@@ -9,7 +11,7 @@
|
|
|
9
11
|
### MyLayout.vue (or other global component)
|
|
10
12
|
|
|
11
13
|
// add PxBaseMobileAware as a mixin
|
|
12
|
-
import PxBaseMobileAware from '@thinkpixellab-public/px-vue/
|
|
14
|
+
import PxBaseMobileAware from '@thinkpixellab-public/px-vue/bases/PxBaseMobileAware.vue';
|
|
13
15
|
mixins: [PxBaseMobileAware],
|
|
14
16
|
|
|
15
17
|
// add a resize handler and call setGlobalIsMobile
|
|
@@ -32,7 +34,7 @@
|
|
|
32
34
|
### MyComponent.vue
|
|
33
35
|
|
|
34
36
|
// use PxBaseMobileAware as a mixin
|
|
35
|
-
import PxBaseMobileAware from '@thinkpixellab-public/px-vue/
|
|
37
|
+
import PxBaseMobileAware from '@thinkpixellab-public/px-vue/bases/PxBaseMobileAware.vue';
|
|
36
38
|
mixins: [PxBaseMobileAware]
|
|
37
39
|
|
|
38
40
|
// use the isMobile property as needed in a template
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
#VUE3 Todo
|
|
3
|
+
-->
|
|
4
|
+
|
|
1
5
|
<script>
|
|
2
|
-
import { debounce } from 'debounce';
|
|
6
|
+
import { debounce } from 'throttle-debounce';
|
|
3
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Mixin that provides size watch capabilities using the ResizeObserver api.
|
|
10
|
+
*/
|
|
4
11
|
export default {
|
|
5
12
|
data() {
|
|
6
13
|
return {
|
|
@@ -23,10 +30,10 @@ export default {
|
|
|
23
30
|
mounted() {
|
|
24
31
|
const resizeDebouncedFn =
|
|
25
32
|
this.resizeDebounceValue && this.resize
|
|
26
|
-
? debounce(e => {
|
|
33
|
+
? debounce(this.resizeDebounceValue, e => {
|
|
27
34
|
this.resize(e);
|
|
28
35
|
this.resizing = false;
|
|
29
|
-
}
|
|
36
|
+
})
|
|
30
37
|
: null;
|
|
31
38
|
|
|
32
39
|
const resizeFn = () => {
|
|
@@ -52,7 +59,7 @@ export default {
|
|
|
52
59
|
this.resizeObserver = new ResizeObserver(resizeFn);
|
|
53
60
|
this.resizeObserver.observe(this.observeElementValue);
|
|
54
61
|
},
|
|
55
|
-
|
|
62
|
+
beforeUnmount() {
|
|
56
63
|
this.resizeObserver.disconnect();
|
|
57
64
|
delete this.resizeObserver;
|
|
58
65
|
},
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
#VUE3 Todo
|
|
3
|
+
-->
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
// components: { Component },
|
|
9
|
+
// mixins: [ Mixin ],
|
|
10
|
+
// props: { a: { type: Boolean, default: false } },
|
|
11
|
+
data() {
|
|
12
|
+
return { scrollPosition: { x: 0, y: 0 } };
|
|
13
|
+
},
|
|
14
|
+
computed: {
|
|
15
|
+
scrollingElement() {
|
|
16
|
+
// derived classes can return something here to watch somethign other than document
|
|
17
|
+
return window !== undefined ? window : null;
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
// watch: {},
|
|
21
|
+
mounted() {
|
|
22
|
+
if (this.scrollingElement && this.scroll) {
|
|
23
|
+
let scroller = this.scrollingElement;
|
|
24
|
+
let ticking = false;
|
|
25
|
+
|
|
26
|
+
scroller.addEventListener('scroll', event => {
|
|
27
|
+
this.scrollPosition.x = scroller.scrollX;
|
|
28
|
+
this.scrollPosition.y = scroller.scrollY;
|
|
29
|
+
|
|
30
|
+
if (!ticking) {
|
|
31
|
+
window.requestAnimationFrame(() => {
|
|
32
|
+
this.scroll();
|
|
33
|
+
ticking = false;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
ticking = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
methods: {
|
|
42
|
+
// base class should override
|
|
43
|
+
// onScroll() {},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
#VUE3 Todo
|
|
3
|
+
|
|
4
|
+
Base class for classes that manage a checked state. In order to simplify the data
|
|
5
|
+
synchronization with the input, we enable v-model binding by also providing a data property
|
|
6
|
+
(checkedValue) that mirrors the checked prop. The intention is that this property will only be
|
|
7
|
+
used internally as v-model.
|
|
8
|
+
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
export default {
|
|
13
|
+
props: {
|
|
14
|
+
/**
|
|
15
|
+
* The value of the checked property.
|
|
16
|
+
*/
|
|
17
|
+
checked: { type: Boolean, default: false },
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Class that should be set on the component when checked.
|
|
21
|
+
*/
|
|
22
|
+
checkedClass: { type: String, default: null },
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Disables interaction.
|
|
26
|
+
*/
|
|
27
|
+
disabled: { type: Boolean, default: false },
|
|
28
|
+
},
|
|
29
|
+
data() {
|
|
30
|
+
return {
|
|
31
|
+
checkedValue: this.checked,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
watch: {
|
|
36
|
+
checked(nv) {
|
|
37
|
+
// update checkedValue when checked changes
|
|
38
|
+
this.checkedValue = nv;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
checkedValue(nv) {
|
|
42
|
+
// emit update when checkedValue changes (enables .sync on parent)
|
|
43
|
+
this.$emit('update:checked', nv);
|
|
44
|
+
|
|
45
|
+
if (nv) {
|
|
46
|
+
this.$emit('checked');
|
|
47
|
+
}
|
|
48
|
+
if (!nv) {
|
|
49
|
+
this.$emit('unchecked');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
computed: {
|
|
54
|
+
calcCheckedClass() {
|
|
55
|
+
return this.checkedValue && this.checkedClass ? this.checkedClass : null;
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
methods: {
|
|
59
|
+
toggleChecked() {
|
|
60
|
+
if (this.disabled) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.checkedValue = !this.checkedValue;
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
#VUE3 Todo
|
|
3
|
+
-->
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
// TODO: this is currently not compatible with SSR
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
methods: {
|
|
10
|
+
uniqueId(prefix) {
|
|
11
|
+
if (!this.__uniqueId) {
|
|
12
|
+
this.__uniqueId = Math.random().toString(36).substring(2);
|
|
13
|
+
}
|
|
14
|
+
return (prefix ? `${prefix}-` : '') + this.__uniqueId;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
</script>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
+
#VUE3 Done
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
Provides a standardized way of specifying variants of a component. Variants are typically css-based
|
|
4
6
|
modifications to a component and might be defined by the component or declared in the app. Typical
|
|
@@ -19,6 +21,11 @@ usage might look like:
|
|
|
19
21
|
import variants from '../utils/variants.js';
|
|
20
22
|
export default {
|
|
21
23
|
props: {
|
|
24
|
+
/**
|
|
25
|
+
* The variant property is intepreted in different ways by different components, but
|
|
26
|
+
* typically used to trigger a different style or layout otherwise effect the way the
|
|
27
|
+
* component is rendered or used.
|
|
28
|
+
*/
|
|
22
29
|
variant: { type: String, default: 'default' },
|
|
23
30
|
},
|
|
24
31
|
computed: {
|
|
@@ -42,6 +49,7 @@ export default {
|
|
|
42
49
|
isVariant(variantName) {
|
|
43
50
|
return this.variants?.includes(variantName);
|
|
44
51
|
},
|
|
52
|
+
|
|
45
53
|
// find the first matching variant key in a map and return the correspond value
|
|
46
54
|
variantsToValue(valueMap, fallback) {
|
|
47
55
|
for (let key in valueMap) {
|
|
@@ -51,9 +59,11 @@ export default {
|
|
|
51
59
|
}
|
|
52
60
|
return fallback;
|
|
53
61
|
},
|
|
62
|
+
|
|
54
63
|
stringToVariants: str => {
|
|
55
64
|
return variants.stringToVariants(str);
|
|
56
65
|
},
|
|
66
|
+
|
|
57
67
|
stringToVariantsMap: str => {
|
|
58
68
|
return variants.stringToVariantsMap(str);
|
|
59
69
|
},
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<!--
|
|
2
|
+
#VUE3 Done
|
|
3
|
+
|
|
2
4
|
Extends PxBaseVariants with the ability to specify default and base variants
|
|
3
5
|
(see descriptions of props below).
|
|
4
6
|
-->
|
|
5
7
|
|
|
6
8
|
<script>
|
|
7
|
-
import PxBaseVariants from '
|
|
9
|
+
import PxBaseVariants from '../bases/PxBaseVariants.vue';
|
|
8
10
|
export default {
|
|
9
11
|
mixins: [PxBaseVariants],
|
|
10
12
|
props: {
|
|
@@ -18,7 +20,7 @@ export default {
|
|
|
18
20
|
variantValue() {
|
|
19
21
|
return (
|
|
20
22
|
(this.variantBase ? `${this.variantBase} ` : '') +
|
|
21
|
-
(this.
|
|
23
|
+
(this.variantDefault ? this.variantDefault : this.variant)
|
|
22
24
|
);
|
|
23
25
|
},
|
|
24
26
|
},
|