@thinkpixellab-public/px-vue 4.1.9 → 4.1.14
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/bases/PxBaseItemsSelect.vue +7 -1
- package/bases/PxBaseUniqueId.vue +2 -2
- package/components/PxArrowScroller.vue +1 -1
- package/components/PxContain.vue +1 -1
- package/components/PxFloat.vue +10 -0
- package/components/PxIcon.vue +2 -2
- package/components/PxResizer.vue +34 -15
- package/components/PxToggle.vue +47 -4
- package/components/PxToggleButton.vue +6 -2
- package/components/PxToggleButtonList.vue +19 -1
- package/components/PxToolPanel.vue +606 -0
- package/composables/useSettings.js +68 -0
- package/package.json +1 -1
- package/stories/PxContain.stories.js +38 -0
- package/stories/PxToolPanel.stories.js +351 -0
- package/test/PxBaseItemsSelect.test.js +1 -0
- package/test/PxBaseUniqueId.test.js +4 -3
- package/test/utils.test.js +15 -1
- package/utils/balanceText.js +33 -1
- package/utils/drag.js +12 -0
- package/utils/utils.js +92 -0
- package/utils/utils.test.js +52 -0
|
@@ -37,6 +37,12 @@ export default {
|
|
|
37
37
|
* items is updated and no other item is selected
|
|
38
38
|
*/
|
|
39
39
|
autoSelectFirst: { type: Boolean, default: false },
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* If true, the update and change events will only be emitted after if the component is
|
|
43
|
+
* mounted.
|
|
44
|
+
*/
|
|
45
|
+
emitEventsBeforeMounted: { type: Boolean, default: false },
|
|
40
46
|
},
|
|
41
47
|
|
|
42
48
|
data() {
|
|
@@ -179,7 +185,7 @@ export default {
|
|
|
179
185
|
* Emit the change / update:selected event
|
|
180
186
|
*/
|
|
181
187
|
emitUpdateEvent() {
|
|
182
|
-
if (!this.isMounted) {
|
|
188
|
+
if (!this.isMounted && !this.emitEventsBeforeMounted) {
|
|
183
189
|
return;
|
|
184
190
|
}
|
|
185
191
|
|
package/bases/PxBaseUniqueId.vue
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
export default {
|
|
3
3
|
beforeCreate() {
|
|
4
|
-
const id =
|
|
5
|
-
this.$__uniqueId = id;
|
|
4
|
+
const id = this.$.uid || Math.floor(Math.random() * 1000);
|
|
5
|
+
this.$__uniqueId = String(id).padStart(4, '0');
|
|
6
6
|
},
|
|
7
7
|
methods: {
|
|
8
8
|
/**
|
package/components/PxContain.vue
CHANGED
package/components/PxFloat.vue
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
ref="popup"
|
|
40
40
|
:class="[bem('popup'), popupClass]"
|
|
41
41
|
:style="{
|
|
42
|
+
opacity: !popupPositioned ? 0 : null,
|
|
42
43
|
pointerEvents: visibleValue ? null : 'none',
|
|
43
44
|
userSelect: visibleValue ? null : 'none',
|
|
44
45
|
...(positionCss || {}),
|
|
@@ -274,6 +275,9 @@ export default {
|
|
|
274
275
|
// mirrors visibleValue but one tick behind (so that we can trigger actions that require the popup to be in the DOM)
|
|
275
276
|
visibleValueNext: false,
|
|
276
277
|
|
|
278
|
+
// whether the popup has been finally positioned (used to trigger opacity)
|
|
279
|
+
popupPositioned: false,
|
|
280
|
+
|
|
277
281
|
// mirrors reference
|
|
278
282
|
referenceValue: null,
|
|
279
283
|
|
|
@@ -357,6 +361,10 @@ export default {
|
|
|
357
361
|
|
|
358
362
|
// delayed actions (settimeout seems to work but $nextTick doesn't)
|
|
359
363
|
|
|
364
|
+
if (nv) {
|
|
365
|
+
this.popupPositioned = false;
|
|
366
|
+
}
|
|
367
|
+
|
|
360
368
|
setTimeout(() => {
|
|
361
369
|
// floating-ui
|
|
362
370
|
|
|
@@ -412,6 +420,8 @@ export default {
|
|
|
412
420
|
// see watcher for transitionVisible
|
|
413
421
|
}
|
|
414
422
|
|
|
423
|
+
this.popupPositioned = true;
|
|
424
|
+
|
|
415
425
|
// show and hide events (also see beforeshow/beforehide in visibleValue watcher)
|
|
416
426
|
|
|
417
427
|
if (nv) {
|
package/components/PxIcon.vue
CHANGED
|
@@ -136,8 +136,8 @@ const PxIcon = {
|
|
|
136
136
|
|
|
137
137
|
if (offset || spacing || this.strokeWidth) {
|
|
138
138
|
return {
|
|
139
|
-
transform: offset ? `translateY(${cssEmFallback(offset)})` : null,
|
|
140
|
-
margin: spacing ? `auto ${cssEmFallback(spacing)}` : null,
|
|
139
|
+
transform: offset ? `translateY(${cssEmFallback(this.offset)})` : null,
|
|
140
|
+
margin: spacing ? `auto ${cssEmFallback(this.spacing)}` : null,
|
|
141
141
|
strokeWidth: cssPx(this.strokeWidth, false),
|
|
142
142
|
};
|
|
143
143
|
}
|
package/components/PxResizer.vue
CHANGED
|
@@ -115,6 +115,7 @@ export default {
|
|
|
115
115
|
|
|
116
116
|
this.updateSize(r.width, r.height, this.downDirection);
|
|
117
117
|
|
|
118
|
+
document.body.style.userSelect = 'none';
|
|
118
119
|
document.addEventListener('mousemove', this.mousemove);
|
|
119
120
|
document.addEventListener('mouseup', this.mouseup);
|
|
120
121
|
}
|
|
@@ -130,6 +131,7 @@ export default {
|
|
|
130
131
|
e.preventDefault();
|
|
131
132
|
},
|
|
132
133
|
mouseup() {
|
|
134
|
+
document.body.style.removeProperty('user-select');
|
|
133
135
|
this.resizing = false;
|
|
134
136
|
this.emitResizeEnd();
|
|
135
137
|
document.removeEventListener('mousemove', this.mousemove);
|
|
@@ -143,6 +145,16 @@ export default {
|
|
|
143
145
|
@use '../styles/px.scss' as *;
|
|
144
146
|
@use 'sass:color';
|
|
145
147
|
|
|
148
|
+
@at-root {
|
|
149
|
+
:root {
|
|
150
|
+
--px-resizer-color: #{accent()};
|
|
151
|
+
--px-resizer-color-hover: #{color.adjust(accent(), $lightness: -10%)};
|
|
152
|
+
--px-resizer-width: 3px;
|
|
153
|
+
--px-resizer-height: 24px;
|
|
154
|
+
--px-resizer-hit-width: 24px;
|
|
155
|
+
--px-resizer-offset: 10px;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
146
158
|
.px-resizer {
|
|
147
159
|
position: relative;
|
|
148
160
|
margin: 0 auto;
|
|
@@ -165,16 +177,16 @@ export default {
|
|
|
165
177
|
|
|
166
178
|
&--show-overlay {
|
|
167
179
|
&::after {
|
|
168
|
-
border: 1px dashed
|
|
180
|
+
border: 1px dashed var(--px-resizer-color);
|
|
169
181
|
border-radius: inherit;
|
|
170
182
|
}
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
&__resize-x,
|
|
174
186
|
&__resize-y {
|
|
175
|
-
color:
|
|
187
|
+
color: var(--px-resizer-color);
|
|
176
188
|
&:hover {
|
|
177
|
-
color:
|
|
189
|
+
color: var(--px-resizer-color-hover);
|
|
178
190
|
}
|
|
179
191
|
&:active {
|
|
180
192
|
opacity: 0.5;
|
|
@@ -184,13 +196,16 @@ export default {
|
|
|
184
196
|
&__resize-x {
|
|
185
197
|
@include center-y();
|
|
186
198
|
cursor: ew-resize;
|
|
187
|
-
width:
|
|
188
|
-
height:
|
|
189
|
-
right: -
|
|
199
|
+
width: var(--px-resizer-hit-width);
|
|
200
|
+
height: var(--px-resizer-height);
|
|
201
|
+
right: calc(var(--px-resizer-hit-width) * -1);
|
|
202
|
+
|
|
190
203
|
@include after() {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
204
|
+
position: absolute;
|
|
205
|
+
top: 0;
|
|
206
|
+
left: var(--px-resizer-offset);
|
|
207
|
+
width: var(--px-resizer-width);
|
|
208
|
+
height: var(--px-resizer-height);
|
|
194
209
|
background-color: currentColor;
|
|
195
210
|
}
|
|
196
211
|
}
|
|
@@ -198,13 +213,17 @@ export default {
|
|
|
198
213
|
&__resize-y {
|
|
199
214
|
@include center-x();
|
|
200
215
|
cursor: ns-resize;
|
|
201
|
-
|
|
202
|
-
height:
|
|
203
|
-
|
|
216
|
+
|
|
217
|
+
height: var(--px-resizer-hit-width);
|
|
218
|
+
width: var(--px-resizer-height);
|
|
219
|
+
bottom: calc(var(--px-resizer-hit-width) * -1);
|
|
220
|
+
|
|
204
221
|
@include after() {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
222
|
+
position: absolute;
|
|
223
|
+
left: 0;
|
|
224
|
+
top: var(--px-resizer-offset);
|
|
225
|
+
height: var(--px-resizer-width);
|
|
226
|
+
width: var(--px-resizer-height);
|
|
208
227
|
background-color: currentColor;
|
|
209
228
|
}
|
|
210
229
|
}
|
package/components/PxToggle.vue
CHANGED
|
@@ -14,6 +14,19 @@
|
|
|
14
14
|
:style="{ backgroundColor: checkedValue ? checkedColor : uncheckedColor }"
|
|
15
15
|
>
|
|
16
16
|
<span :class="bem('spacer')"></span>
|
|
17
|
+
<transition name="px-toggle-icon">
|
|
18
|
+
<span v-if="$slots['icon-on'] && checkedValue" :class="bem('icon', { on: true })">
|
|
19
|
+
<slot name="icon-on" />
|
|
20
|
+
</span>
|
|
21
|
+
</transition>
|
|
22
|
+
<transition name="px-toggle-icon">
|
|
23
|
+
<span
|
|
24
|
+
v-if="$slots['icon-off'] && !checkedValue"
|
|
25
|
+
:class="bem('icon', { off: true })"
|
|
26
|
+
>
|
|
27
|
+
<slot name="icon-off" />
|
|
28
|
+
</span>
|
|
29
|
+
</transition>
|
|
17
30
|
<span
|
|
18
31
|
:class="[bem('thumb'), trackClass]"
|
|
19
32
|
:style="{ backroundColor: thumbColor }"
|
|
@@ -79,10 +92,18 @@ export default {
|
|
|
79
92
|
@use '@thinkpixellab-public/px-styles/src/modules/controls' as *;
|
|
80
93
|
|
|
81
94
|
.px-toggle {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
@at-root {
|
|
96
|
+
@include vue-transition-fade(px-toggle-icon);
|
|
97
|
+
|
|
98
|
+
:root {
|
|
99
|
+
--px-toggle-size: 1em;
|
|
100
|
+
--px-toggle-unchecked: #{gray(-8, 0.33)};
|
|
101
|
+
--px-toggle-checked: #{accent()};
|
|
102
|
+
--px-toggle-thumb: white;
|
|
103
|
+
--px-toggle-track-shadow: inset 0 1px 1px 0 rgba(0, 0, 0, 0.2);
|
|
104
|
+
--px-toggle-thumb-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.4);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
86
107
|
|
|
87
108
|
@include toggle-switch(
|
|
88
109
|
(
|
|
@@ -90,6 +111,8 @@ export default {
|
|
|
90
111
|
'--thumb.font-size': var(--px-toggle-size),
|
|
91
112
|
'--track.background-color': var(--px-toggle-unchecked),
|
|
92
113
|
'--track.font-size': var(--px-toggle-size),
|
|
114
|
+
'--track.box-shadow': var(--px-toggle-track-shadow),
|
|
115
|
+
'--thumb.box-shadow': var(--px-toggle-thumb-shadow),
|
|
93
116
|
'checked.--track.background-color': var(--px-toggle-checked),
|
|
94
117
|
),
|
|
95
118
|
'.px-toggle__track',
|
|
@@ -97,6 +120,26 @@ export default {
|
|
|
97
120
|
'.px-toggle__spacer'
|
|
98
121
|
);
|
|
99
122
|
|
|
123
|
+
&__icon {
|
|
124
|
+
position: absolute;
|
|
125
|
+
top: 0;
|
|
126
|
+
height: 100%;
|
|
127
|
+
aspect-ratio: 1;
|
|
128
|
+
border-radius: 50%;
|
|
129
|
+
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
justify-content: center;
|
|
133
|
+
|
|
134
|
+
&--on {
|
|
135
|
+
left: 0;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&--off {
|
|
139
|
+
right: 0;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
100
143
|
&--reverse {
|
|
101
144
|
flex-direction: row-reverse;
|
|
102
145
|
}
|
|
@@ -163,12 +163,16 @@ export default {
|
|
|
163
163
|
return this.mode === 'expander' ? 'button' : 'switch';
|
|
164
164
|
},
|
|
165
165
|
ariaChecked() {
|
|
166
|
-
if (!this.isSwitch)
|
|
166
|
+
if (!this.isSwitch) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
167
169
|
|
|
168
170
|
return this.checked ? 'true' : 'false';
|
|
169
171
|
},
|
|
170
172
|
ariaExpanded() {
|
|
171
|
-
if (this.isSwitch)
|
|
173
|
+
if (this.isSwitch) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
172
176
|
|
|
173
177
|
return this.checked ? 'true' : 'false';
|
|
174
178
|
},
|
|
@@ -28,7 +28,11 @@
|
|
|
28
28
|
v-for="item in items"
|
|
29
29
|
:key="getItemKey(item)"
|
|
30
30
|
:is="isVariant('radio') ? 'px-radio-button' : 'px-toggle-button'"
|
|
31
|
-
:class="[
|
|
31
|
+
:class="[
|
|
32
|
+
bem('button'),
|
|
33
|
+
buttonClass,
|
|
34
|
+
isItemSelected(item) ? buttonClass + '--checked' : null,
|
|
35
|
+
]"
|
|
32
36
|
:icon="icon"
|
|
33
37
|
:iconSize="iconSize"
|
|
34
38
|
:variant="isVariant('radio') ? 'default' : variant"
|
|
@@ -79,6 +83,11 @@ export default {
|
|
|
79
83
|
|
|
80
84
|
//
|
|
81
85
|
multiSelect: { type: Boolean, default: false },
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* When true, ensures that one item is always selected (radio button behavior)
|
|
89
|
+
*/
|
|
90
|
+
requireSelection: { type: Boolean, default: true },
|
|
82
91
|
},
|
|
83
92
|
computed: {
|
|
84
93
|
calculatedInputGroup() {
|
|
@@ -96,6 +105,15 @@ export default {
|
|
|
96
105
|
this.selectItems(item);
|
|
97
106
|
},
|
|
98
107
|
itemUncheck(item) {
|
|
108
|
+
// Prevent unchecking if requireSelection is true and this is the last selected item
|
|
109
|
+
if (
|
|
110
|
+
this.requireSelection &&
|
|
111
|
+
!this.multiSelect &&
|
|
112
|
+
this.selectedItems.length === 1 &&
|
|
113
|
+
this.isItemSelected(item)
|
|
114
|
+
) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
99
117
|
this.unselectItems(item);
|
|
100
118
|
},
|
|
101
119
|
},
|