@dumiflex/wp-kit 0.4.0 → 0.6.0
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/CHANGELOG.md +47 -0
- package/README.md +5 -0
- package/package.json +4 -3
- package/src/Avatar.vue +1 -1
- package/src/Banner.vue +4 -4
- package/src/Button.vue +73 -44
- package/src/Checkbox.vue +201 -63
- package/src/Chip.vue +5 -2
- package/src/CodeBlock.vue +33 -6
- package/src/ColorField.vue +60 -6
- package/src/Combobox.vue +10 -14
- package/src/ConfirmModal.vue +12 -22
- package/src/ContextMenu.vue +11 -30
- package/src/CopyButton.vue +1 -1
- package/src/DataTable.vue +3 -4
- package/src/DatePicker.vue +1 -1
- package/src/Disclosure.vue +2 -1
- package/src/Drawer.vue +2 -2
- package/src/DropZone.vue +2 -2
- package/src/HsvPicker.vue +2 -2
- package/src/IconPicker.vue +1 -1
- package/src/ImageGrid.vue +17 -15
- package/src/Lightbox.vue +6 -3
- package/src/LoadingMark.vue +93 -51
- package/src/Modal.vue +109 -44
- package/src/ModalShell.vue +26 -5
- package/src/Pagination.vue +4 -4
- package/src/Popover.vue +68 -12
- package/src/RadioGroup.vue +5 -4
- package/src/SearchInput.vue +1 -1
- package/src/Select.vue +53 -158
- package/src/Skeleton.vue +21 -5
- package/src/Slider.vue +166 -55
- package/src/SortableList.vue +1 -1
- package/src/TagInput.vue +1 -1
- package/src/Timeline.vue +2 -2
- package/src/WorkingLine.vue +320 -0
- package/src/WpIconButton.vue +3 -2
- package/src/WpImageZoom.vue +7 -7
- package/src/WpSegmented.vue +3 -1
- package/src/WpSwitch.vue +1 -1
- package/src/WpTabs.vue +1 -1
- package/src/_modal-motion.css +1 -1
- package/src/button.css +8 -6
- package/src/floating.ts +5 -0
- package/src/highlight.ts +199 -0
- package/src/hsv.ts +1 -1
- package/src/loading-mark-motion.ts +249 -0
- package/src/menu.css +51 -0
- package/src/motion.css +73 -0
- package/src/slider-math.ts +45 -1
- package/src/theme/looks.css +6 -19
- package/src/theme/tokens.css +12 -1108
- package/src/tokens.ts +8 -3
- package/src/tooltip.css +8 -5
- package/src/useDialogFocus.ts +11 -2
- package/src/CloseButton.vue +0 -69
- package/src/ColorPicker.vue +0 -201
- package/src/ConfirmDialog.vue +0 -165
- package/src/RangeSlider.vue +0 -183
- package/src/Toggle.vue +0 -36
- package/src/WpButton.vue +0 -75
- package/src/WpCheck.vue +0 -104
- package/src/_skeleton.css +0 -50
package/src/Slider.vue
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
1
|
+
<script setup lang="ts" generic="T extends number | [number, number]">
|
|
2
2
|
/**
|
|
3
3
|
* Slider: a number picked by dragging along a range (a weight, a threshold,
|
|
4
4
|
* a size). Use it when the feel of "more or less" matters more than the
|
|
@@ -8,92 +8,190 @@
|
|
|
8
8
|
* <Slider v-model="weight" :min="0" :max="2" :step="0.05" aria-label="Weight" with-input />
|
|
9
9
|
* <Slider v-model="size" :min="4" :max="160" :marks="[{ value: 32, label: '32' }]" :format="(v) => `${v} px`" />
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Give it a pair (`v-model="range"` with `[low, high]`) for a low and a high
|
|
12
|
+
* number on one track (a weight range, a token budget, a sweep's from–to):
|
|
13
|
+
* two thumbs that can't cross, kept at least `min-gap` apart, and with
|
|
14
|
+
* `with-input` a WpNumber for each end. A click on the track moves the
|
|
15
|
+
* nearer thumb.
|
|
16
|
+
*
|
|
17
|
+
* <Slider v-model="range" :min="0" :max="2" :step="0.1" :min-gap="0.2" aria-label="Weight" with-input />
|
|
18
|
+
*
|
|
19
|
+
* `snap` settles the thumb on the marks. `snap` (true) makes the marks the only
|
|
20
|
+
* values: a drag, a click or a typed number lands on the nearest mark and
|
|
21
|
+
* the arrows go mark to mark. A number pulls the thumb onto a mark only once
|
|
22
|
+
* the pointer comes within that distance of one, and moves it by `step`
|
|
23
|
+
* elsewhere (keys and typing stay exact, so a thumb can always leave a mark).
|
|
24
|
+
*
|
|
25
|
+
* <Slider v-model="cfg" :min="1" :max="30" :marks="[{ value: 7, label: '7' }]" :snap="1" />
|
|
26
|
+
*
|
|
27
|
+
* APG slider: each thumb is a focus stop; arrows move one step, PageUp /
|
|
28
|
+
* PageDown ten, Home / End jump to the ends (for a pair, the ends that thumb
|
|
29
|
+
* can reach), and `format` gives screen readers the value as words ("32 px").
|
|
30
|
+
* A pair's thumbs are "<label>, low end" / "high end", their min and max the
|
|
31
|
+
* other thumb, so screen readers hear the real limits. Clicking the track
|
|
32
|
+
* jumps there and the drag carries on from it.
|
|
15
33
|
*/
|
|
16
34
|
import { computed, ref } from "vue";
|
|
17
|
-
import { keyStep, percentOf, snap, valueAt } from "./slider-math";
|
|
35
|
+
import { keyStep, keyToMark, percentOf, snap, snapToMarks, valueAt } from "./slider-math";
|
|
18
36
|
import WpNumber from "./WpNumber.vue";
|
|
19
37
|
|
|
20
38
|
const props = withDefaults(defineProps<{
|
|
21
|
-
modelValue:
|
|
39
|
+
modelValue: T;
|
|
22
40
|
min?: number | undefined;
|
|
23
41
|
max?: number | undefined;
|
|
24
42
|
step?: number | undefined;
|
|
43
|
+
/** A pair only: the smallest distance between the two ends. */
|
|
44
|
+
minGap?: number | undefined;
|
|
25
45
|
size?: "sm" | "md" | "lg" | undefined;
|
|
26
46
|
disabled?: boolean | undefined;
|
|
27
47
|
ariaLabel?: string | undefined;
|
|
28
48
|
/** Labelled ticks under the track. */
|
|
29
49
|
marks?: { value: number; label?: string }[] | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Settle on the marks: true allows only mark values (drag, click, typing,
|
|
52
|
+
* arrows mark to mark); a number pulls the dragged thumb onto a mark within
|
|
53
|
+
* that distance of it and leaves it free elsewhere.
|
|
54
|
+
*/
|
|
55
|
+
snap?: boolean | number | undefined;
|
|
30
56
|
/** How the value reads (the tooltip-free label and screen readers). */
|
|
31
57
|
format?: ((v: number) => string) | undefined;
|
|
32
|
-
/** Show the value after the track. */
|
|
58
|
+
/** Show the value (a pair: "low – high") after the track. */
|
|
33
59
|
showValue?: boolean | undefined;
|
|
34
|
-
/** Put a WpNumber after the track to type the exact value. */
|
|
60
|
+
/** Put a WpNumber after the track (a pair: one at each side) to type the exact value. */
|
|
35
61
|
withInput?: boolean | undefined;
|
|
36
|
-
}>(), { min: 0, max: 100, step: 1, size: "md", ariaLabel: undefined, marks: undefined });
|
|
62
|
+
}>(), { min: 0, max: 100, step: 1, minGap: 0, size: "md", ariaLabel: undefined, marks: undefined });
|
|
37
63
|
|
|
38
|
-
const emit = defineEmits<{ (e: "update:modelValue", v:
|
|
64
|
+
const emit = defineEmits<{ (e: "update:modelValue", v: T): void; (e: "change", v: T): void }>();
|
|
39
65
|
|
|
40
66
|
const trackEl = ref<HTMLElement | null>(null);
|
|
41
|
-
|
|
67
|
+
/** The thumb being dragged (0 = the only one, or a pair's low end). */
|
|
68
|
+
const active = ref<0 | 1 | null>(null);
|
|
42
69
|
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
70
|
+
const isPair = computed(() => Array.isArray(props.modelValue));
|
|
71
|
+
const sn = (v: number): number => snap(v, props.min, props.max, props.step);
|
|
72
|
+
/** The marks' values inside the range, for `snap`. */
|
|
73
|
+
const markValues = computed(() => (props.marks ?? []).map((m) => m.value).filter((v) => v >= props.min && v <= props.max));
|
|
74
|
+
/** Only marks can be picked (`snap` true with marks). */
|
|
75
|
+
const marksOnly = computed(() => props.snap === true && markValues.value.length > 0);
|
|
76
|
+
const toMark = (v: number): number => snapToMarks(v, markValues.value, props.snap);
|
|
46
77
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
78
|
+
/** The thumbs' values: one, or a pair sorted low to high. */
|
|
79
|
+
const ends = computed<number[]>(() => {
|
|
80
|
+
const m = props.modelValue;
|
|
81
|
+
if (typeof m === "number") return [sn(m)];
|
|
82
|
+
return [sn(Math.min(m[0], m[1])), sn(Math.max(m[0], m[1]))];
|
|
83
|
+
});
|
|
84
|
+
const lo = computed(() => ends.value[0] ?? props.min);
|
|
85
|
+
const hi = computed(() => ends.value[ends.value.length - 1] ?? props.max);
|
|
86
|
+
const pcts = computed(() => ends.value.map((v) => percentOf(v, props.min, props.max)));
|
|
87
|
+
const loPct = computed(() => pcts.value[0] ?? 0);
|
|
88
|
+
const hiPct = computed(() => pcts.value[pcts.value.length - 1] ?? 0);
|
|
89
|
+
|
|
90
|
+
const text = (v: number): string => (props.format ? props.format(v) : String(v));
|
|
91
|
+
const label = computed(() => props.ariaLabel ?? (isPair.value ? "Range" : undefined));
|
|
92
|
+
|
|
93
|
+
/** The lowest and highest value thumb `i` can take. */
|
|
94
|
+
function limits(i: number): [number, number] {
|
|
95
|
+
if (!isPair.value) return [props.min, props.max];
|
|
96
|
+
return i === 0 ? [props.min, hi.value - props.minGap] : [lo.value + props.minGap, props.max];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function thumbLabel(i: number): string | undefined {
|
|
100
|
+
if (!isPair.value) return label.value;
|
|
101
|
+
return `${label.value ?? "Range"}, ${i === 0 ? "low" : "high"} end`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function asModel(vals: number[]): T {
|
|
105
|
+
const out = isPair.value ? [vals[0] ?? lo.value, vals[1] ?? hi.value] : (vals[0] ?? lo.value);
|
|
106
|
+
return out as T;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Put thumb `i` at `v` (a pair's thumb kept inside the other end minus the gap); returns the new model. */
|
|
110
|
+
function setEnd(i: 0 | 1, v: number): T {
|
|
111
|
+
let vals: number[];
|
|
112
|
+
if (!isPair.value) vals = [v];
|
|
113
|
+
else if (i === 0) vals = [Math.min(v, sn(hi.value - props.minGap)), hi.value];
|
|
114
|
+
else vals = [lo.value, Math.max(v, sn(lo.value + props.minGap))];
|
|
115
|
+
const next = asModel(vals);
|
|
116
|
+
if (!props.disabled && JSON.stringify(next) !== JSON.stringify(props.modelValue)) emit("update:modelValue", next);
|
|
117
|
+
return next;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function current(): T {
|
|
121
|
+
return asModel(ends.value);
|
|
50
122
|
}
|
|
51
123
|
|
|
52
124
|
function fromPointer(ev: PointerEvent): number {
|
|
53
125
|
const r = trackEl.value?.getBoundingClientRect();
|
|
54
|
-
|
|
55
|
-
return valueAt(ev.clientX, r.left, r.width, props.min, props.max, props.step);
|
|
126
|
+
return r ? toMark(valueAt(ev.clientX, r.left, r.width, props.min, props.max, props.step)) : lo.value;
|
|
56
127
|
}
|
|
57
128
|
|
|
58
129
|
function onPointerDown(ev: PointerEvent): void {
|
|
59
130
|
if (props.disabled || ev.button !== 0) return;
|
|
60
131
|
ev.preventDefault();
|
|
61
|
-
|
|
132
|
+
const v = fromPointer(ev);
|
|
133
|
+
const i: 0 | 1 = isPair.value && (Math.abs(v - lo.value) > Math.abs(v - hi.value) || v > hi.value) ? 1 : 0;
|
|
134
|
+
active.value = i;
|
|
62
135
|
(ev.currentTarget as HTMLElement).setPointerCapture?.(ev.pointerId);
|
|
63
|
-
|
|
64
|
-
|
|
136
|
+
setEnd(i, v);
|
|
137
|
+
trackEl.value?.querySelectorAll<HTMLElement>("[role=slider]")[i]?.focus();
|
|
65
138
|
}
|
|
66
139
|
|
|
67
140
|
function onPointerMove(ev: PointerEvent): void {
|
|
68
|
-
if (
|
|
141
|
+
if (active.value !== null) setEnd(active.value, fromPointer(ev));
|
|
69
142
|
}
|
|
70
143
|
|
|
71
144
|
function onPointerUp(ev: PointerEvent): void {
|
|
72
|
-
if (
|
|
73
|
-
|
|
145
|
+
if (active.value === null) return;
|
|
146
|
+
active.value = null;
|
|
74
147
|
(ev.currentTarget as HTMLElement).releasePointerCapture?.(ev.pointerId);
|
|
75
|
-
emit("change",
|
|
148
|
+
emit("change", current());
|
|
76
149
|
}
|
|
77
150
|
|
|
78
|
-
function onKeydown(ev: KeyboardEvent): void {
|
|
151
|
+
function onKeydown(ev: KeyboardEvent, i: 0 | 1): void {
|
|
79
152
|
if (props.disabled) return;
|
|
80
|
-
const
|
|
153
|
+
const now = i === 0 ? lo.value : hi.value;
|
|
154
|
+
const next = marksOnly.value
|
|
155
|
+
? keyToMark(ev.key, now, markValues.value)
|
|
156
|
+
: keyStep(ev.key, now, props.min, props.max, props.step);
|
|
81
157
|
if (next === null) return;
|
|
82
158
|
ev.preventDefault();
|
|
83
|
-
|
|
84
|
-
|
|
159
|
+
const [low, high] = limits(i);
|
|
160
|
+
const v = marksOnly.value ? next : ev.key === "Home" ? low : ev.key === "End" ? high : next;
|
|
161
|
+
emit("change", setEnd(i, v));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function onTyped(i: 0 | 1, v: number | null): void {
|
|
165
|
+
if (v === null || props.disabled) return;
|
|
166
|
+
emit("change", setEnd(i, marksOnly.value ? toMark(sn(v)) : sn(v)));
|
|
85
167
|
}
|
|
86
168
|
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
const next = snap(v, props.min, props.max, props.step);
|
|
90
|
-
set(next);
|
|
91
|
-
emit("change", next);
|
|
169
|
+
function passed(v: number): boolean {
|
|
170
|
+
return isPair.value ? v >= lo.value && v <= hi.value : v <= lo.value;
|
|
92
171
|
}
|
|
93
172
|
</script>
|
|
94
173
|
|
|
95
174
|
<template>
|
|
96
|
-
<div
|
|
175
|
+
<div
|
|
176
|
+
class="wp-slider"
|
|
177
|
+
:data-size="size"
|
|
178
|
+
:data-pair="isPair || undefined"
|
|
179
|
+
:data-disabled="disabled || undefined"
|
|
180
|
+
:data-dragging="active !== null || undefined"
|
|
181
|
+
:data-marked="marks?.length ? 'true' : undefined"
|
|
182
|
+
>
|
|
183
|
+
<WpNumber
|
|
184
|
+
v-if="withInput && isPair"
|
|
185
|
+
class="wp-slider__input"
|
|
186
|
+
:model-value="lo"
|
|
187
|
+
:min="min"
|
|
188
|
+
:max="hi - props.minGap"
|
|
189
|
+
:step="step"
|
|
190
|
+
:size="size"
|
|
191
|
+
:disabled="disabled"
|
|
192
|
+
:aria-label="thumbLabel(0)"
|
|
193
|
+
@update:model-value="onTyped(0, $event)"
|
|
194
|
+
/>
|
|
97
195
|
<div
|
|
98
196
|
ref="trackEl"
|
|
99
197
|
class="wp-slider__track"
|
|
@@ -103,43 +201,51 @@ function onTyped(v: number | null): void {
|
|
|
103
201
|
@pointercancel="onPointerUp"
|
|
104
202
|
>
|
|
105
203
|
<div class="wp-slider__rail" />
|
|
106
|
-
<div
|
|
204
|
+
<div
|
|
205
|
+
class="wp-slider__fill"
|
|
206
|
+
:style="isPair
|
|
207
|
+
? { left: `${loPct}%`, width: `${hiPct - loPct}%` }
|
|
208
|
+
: { width: `calc(${loPct}% + var(--_thumb) / 2)` }"
|
|
209
|
+
/>
|
|
107
210
|
<span
|
|
108
211
|
v-for="m in marks ?? []"
|
|
109
212
|
:key="m.value"
|
|
110
213
|
class="wp-slider__mark"
|
|
111
|
-
:data-passed="m.value
|
|
214
|
+
:data-passed="passed(m.value) || undefined"
|
|
112
215
|
:style="{ left: `${percentOf(m.value, props.min, props.max)}%` }"
|
|
113
216
|
aria-hidden="true"
|
|
114
217
|
><span v-if="m.label" class="wp-slider__mark-label">{{ m.label }}</span></span>
|
|
115
218
|
<!-- Focusable unless disabled (tabindex is bound). -->
|
|
116
219
|
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
|
|
117
220
|
<div
|
|
221
|
+
v-for="(v, i) in ends"
|
|
222
|
+
:key="i"
|
|
118
223
|
class="wp-slider__thumb"
|
|
119
224
|
role="slider"
|
|
120
225
|
:tabindex="disabled ? -1 : 0"
|
|
121
|
-
:aria-label="
|
|
122
|
-
:aria-valuemin="
|
|
123
|
-
:aria-valuemax="
|
|
124
|
-
:aria-valuenow="
|
|
125
|
-
:aria-valuetext="format ? text : undefined"
|
|
226
|
+
:aria-label="thumbLabel(i)"
|
|
227
|
+
:aria-valuemin="limits(i)[0]"
|
|
228
|
+
:aria-valuemax="limits(i)[1]"
|
|
229
|
+
:aria-valuenow="v"
|
|
230
|
+
:aria-valuetext="format ? text(v) : undefined"
|
|
126
231
|
:aria-disabled="disabled || undefined"
|
|
127
|
-
:
|
|
128
|
-
|
|
232
|
+
:data-active="active === i || undefined"
|
|
233
|
+
:style="{ left: `${pcts[i]}%` }"
|
|
234
|
+
@keydown="onKeydown($event, i === 1 ? 1 : 0)"
|
|
129
235
|
/>
|
|
130
236
|
</div>
|
|
131
|
-
<span v-if="showValue && !withInput" class="wp-slider__value" aria-hidden="true">{{ text }}</span>
|
|
237
|
+
<span v-if="showValue && !withInput" class="wp-slider__value" aria-hidden="true">{{ isPair ? `${text(lo)} – ${text(hi)}` : text(lo) }}</span>
|
|
132
238
|
<WpNumber
|
|
133
239
|
v-if="withInput"
|
|
134
240
|
class="wp-slider__input"
|
|
135
|
-
:model-value="
|
|
136
|
-
:min="min"
|
|
241
|
+
:model-value="isPair ? hi : lo"
|
|
242
|
+
:min="isPair ? lo + props.minGap : min"
|
|
137
243
|
:max="max"
|
|
138
244
|
:step="step"
|
|
139
245
|
:size="size"
|
|
140
246
|
:disabled="disabled"
|
|
141
|
-
:aria-label="ariaLabel ? `${ariaLabel}, exact value` : 'Exact value'"
|
|
142
|
-
@update:model-value="onTyped"
|
|
247
|
+
:aria-label="isPair ? thumbLabel(1) : (ariaLabel ? `${ariaLabel}, exact value` : 'Exact value')"
|
|
248
|
+
@update:model-value="onTyped(isPair ? 1 : 0, $event)"
|
|
143
249
|
/>
|
|
144
250
|
</div>
|
|
145
251
|
</template>
|
|
@@ -158,10 +264,11 @@ function onTyped(v: number | null): void {
|
|
|
158
264
|
position: relative; flex: 1; min-width: 60px; height: var(--_h);
|
|
159
265
|
margin: 0 calc(var(--_thumb) / 2); cursor: pointer; touch-action: none;
|
|
160
266
|
}
|
|
267
|
+
.wp-slider[data-pair] .wp-slider__track { min-width: 80px; }
|
|
161
268
|
.wp-slider__rail, .wp-slider__fill {
|
|
162
269
|
position: absolute; top: 50%; left: 0; height: 4px; margin-top: -2px; border-radius: var(--wp-radius-cap, 999px);
|
|
163
270
|
}
|
|
164
|
-
.wp-slider__rail {
|
|
271
|
+
.wp-slider__rail { left: calc(var(--_thumb) / -2); right: calc(var(--_thumb) / -2); background: var(--wp-bg-3); box-shadow: inset 0 0 0 1px var(--wp-border-soft); }
|
|
165
272
|
.wp-slider__fill { left: calc(var(--_thumb) / -2); background: var(--wp-accent); }
|
|
166
273
|
.wp-slider[data-size="sm"] .wp-slider__rail, .wp-slider[data-size="sm"] .wp-slider__fill { height: 3px; margin-top: -1.5px; }
|
|
167
274
|
.wp-slider__thumb {
|
|
@@ -171,8 +278,10 @@ function onTyped(v: number | null): void {
|
|
|
171
278
|
box-shadow: var(--wp-shadow-sm); outline: none;
|
|
172
279
|
transition: transform var(--wp-motion-quick), box-shadow var(--wp-motion-quick);
|
|
173
280
|
}
|
|
174
|
-
.wp-
|
|
175
|
-
.wp-
|
|
281
|
+
.wp-slider:not([data-pair]) .wp-slider__track:hover .wp-slider__thumb,
|
|
282
|
+
.wp-slider[data-pair] .wp-slider__thumb:hover,
|
|
283
|
+
.wp-slider__thumb[data-active] { transform: scale(1.12); }
|
|
284
|
+
.wp-slider__thumb:focus-visible { box-shadow: var(--wp-focus-ring); z-index: 1; }
|
|
176
285
|
.wp-slider__mark {
|
|
177
286
|
position: absolute; top: 50%; width: 2px; height: 8px; margin: -4px 0 0 -1px; border-radius: min(1px, var(--wp-radius-cap, 999px));
|
|
178
287
|
background: var(--wp-border-strong); pointer-events: none;
|
|
@@ -184,11 +293,13 @@ function onTyped(v: number | null): void {
|
|
|
184
293
|
}
|
|
185
294
|
.wp-slider__value {
|
|
186
295
|
flex: none; min-width: 3ch; text-align: right; color: var(--wp-text); font: 500 var(--wp-text-sm)/1 var(--wp-font-sans);
|
|
187
|
-
font-variant-numeric: tabular-nums;
|
|
296
|
+
font-variant-numeric: tabular-nums; white-space: nowrap;
|
|
188
297
|
}
|
|
189
298
|
.wp-slider[data-size="sm"] .wp-slider__value { font-size: var(--wp-text-xs); }
|
|
190
299
|
.wp-slider__input { flex: none; width: 84px; }
|
|
300
|
+
.wp-slider[data-pair] .wp-slider__input { width: 76px; }
|
|
191
301
|
.wp-slider[data-size="sm"] .wp-slider__input { width: 64px; }
|
|
302
|
+
.wp-slider[data-pair][data-size="sm"] .wp-slider__input { width: 60px; }
|
|
192
303
|
.wp-slider[data-disabled] { opacity: 0.45; }
|
|
193
304
|
.wp-slider[data-disabled] .wp-slider__track { cursor: not-allowed; }
|
|
194
305
|
.wp-slider[data-disabled] .wp-slider__thumb { transform: none; }
|
package/src/SortableList.vue
CHANGED
|
@@ -241,7 +241,7 @@ function onGripBlur(i: number): void {
|
|
|
241
241
|
background: transparent; color: var(--wp-text-dim); cursor: grab; touch-action: none;
|
|
242
242
|
}
|
|
243
243
|
.wp-sortable[data-size="sm"] .wp-sortable__grip { width: 20px; min-height: 20px; }
|
|
244
|
-
.wp-sortable__grip .pi { font-size:
|
|
244
|
+
.wp-sortable__grip .pi { font-size: 12px; }
|
|
245
245
|
.wp-sortable[data-size="sm"] .wp-sortable__grip .pi { font-size: 10px; }
|
|
246
246
|
.wp-sortable__grip:hover:not(:disabled) { color: var(--wp-text); background: var(--wp-row-hover); }
|
|
247
247
|
.wp-sortable__grip:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--wp-border-focus); }
|
package/src/TagInput.vue
CHANGED
|
@@ -263,7 +263,7 @@ function setOpen(v: boolean): void {
|
|
|
263
263
|
color: var(--wp-text); font-size: var(--wp-text-xs); line-height: 1;
|
|
264
264
|
}
|
|
265
265
|
.wp-tag-input[data-size="sm"] .wp-tag-input__chip { height: 16px; padding-left: 5px; font-size: 10.5px; }
|
|
266
|
-
.wp-tag-input__chip-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
266
|
+
.wp-tag-input__chip-text { min-width: 0; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
267
267
|
/* Plain ✕: no background zone, the chip keeps its height; the hit area is 20 px. */
|
|
268
268
|
.wp-tag-input__remove {
|
|
269
269
|
display: inline-grid; place-items: center; width: 16px; height: 16px; margin: -2px 0; padding: 0;
|
package/src/Timeline.vue
CHANGED
|
@@ -71,13 +71,13 @@ withDefaults(defineProps<{
|
|
|
71
71
|
}
|
|
72
72
|
.wp-timeline__dot {
|
|
73
73
|
position: relative; display: grid; place-items: center; flex: none; box-sizing: border-box;
|
|
74
|
-
width: var(--_dot); height: var(--_dot); margin-top: 1px; border-radius: 50
|
|
74
|
+
width: var(--_dot); height: var(--_dot); margin-top: 1px; border-radius: min(50%, var(--wp-radius-cap, 999px));
|
|
75
75
|
border: 2px solid var(--_tone); background: var(--wp-bg-1); color: var(--_tone);
|
|
76
76
|
}
|
|
77
77
|
.wp-timeline__item:not([data-icon]) .wp-timeline__dot { transform: scale(0.6); background: var(--_tone); }
|
|
78
78
|
.wp-timeline__dot .pi { font-size: calc(var(--_dot) * 0.45); }
|
|
79
79
|
.wp-timeline__item[data-pending] .wp-timeline__dot::after {
|
|
80
|
-
content: ""; position: absolute; inset: -4px; border-radius: 50
|
|
80
|
+
content: ""; position: absolute; inset: -4px; border-radius: min(50%, var(--wp-radius-cap, 999px)); border: 2px solid var(--_tone);
|
|
81
81
|
animation: wp-timeline-pulse 1.6s ease-out infinite;
|
|
82
82
|
}
|
|
83
83
|
@keyframes wp-timeline-pulse { from { opacity: 0.7; transform: scale(0.8); } to { opacity: 0; transform: scale(1.4); } }
|