@thinkpixellab-public/px-vue 4.1.13 → 4.1.15
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/PxArrowScroller.vue +1 -1
- package/components/PxFloat.vue +10 -0
- package/components/PxSticky.vue +1 -1
- 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 +24 -5
- package/package.json +23 -24
- package/stories/PxToolPanel.stories.js +351 -0
- package/utils/balanceText.js +33 -1
- package/utils/utils.js +63 -7
- package/utils/utils.test.js +52 -0
- package/utils/utilsSsr.js +8 -12
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/PxSticky.vue
CHANGED
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
|
},
|