@redseed/redseed-ui-vue3 8.43.0 → 8.45.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/package.json
CHANGED
|
@@ -56,8 +56,69 @@ const props = defineProps({
|
|
|
56
56
|
type: Boolean,
|
|
57
57
|
default: false,
|
|
58
58
|
},
|
|
59
|
+
resizable: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
default: false,
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// User-set panel width (px) when resizable; null falls back to the size-class width.
|
|
66
|
+
const panelWidth = ref(null)
|
|
67
|
+
const isResizing = ref(false)
|
|
68
|
+
|
|
69
|
+
const panelStyle = computed(() => {
|
|
70
|
+
if (!props.resizable || panelWidth.value === null) return {}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
width: `${panelWidth.value}px`,
|
|
74
|
+
maxWidth: 'none',
|
|
75
|
+
}
|
|
59
76
|
})
|
|
60
77
|
|
|
78
|
+
const MIN_WIDTH = 320
|
|
79
|
+
|
|
80
|
+
function clampWidth(width) {
|
|
81
|
+
const max = window.innerWidth * 0.95
|
|
82
|
+
|
|
83
|
+
return Math.min(max, Math.max(MIN_WIDTH, width))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function startResize(event) {
|
|
87
|
+
const startX = event.clientX
|
|
88
|
+
const startWidth = drawerPanelRef.value.getBoundingClientRect().width
|
|
89
|
+
isResizing.value = true
|
|
90
|
+
document.body.style.userSelect = 'none'
|
|
91
|
+
|
|
92
|
+
function onMove(moveEvent) {
|
|
93
|
+
const dx = moveEvent.clientX - startX
|
|
94
|
+
// Right-anchored grows by dragging left; left-anchored grows by dragging right.
|
|
95
|
+
const delta = props.left ? dx : -dx
|
|
96
|
+
panelWidth.value = clampWidth(startWidth + delta)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function onUp() {
|
|
100
|
+
isResizing.value = false
|
|
101
|
+
document.body.style.userSelect = ''
|
|
102
|
+
document.removeEventListener('pointermove', onMove)
|
|
103
|
+
document.removeEventListener('pointerup', onUp)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
document.addEventListener('pointermove', onMove)
|
|
107
|
+
document.addEventListener('pointerup', onUp)
|
|
108
|
+
event.preventDefault()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function onHandleKeydown(event) {
|
|
112
|
+
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return
|
|
113
|
+
|
|
114
|
+
const step = 16
|
|
115
|
+
const current = panelWidth.value ?? drawerPanelRef.value?.getBoundingClientRect().width ?? MIN_WIDTH
|
|
116
|
+
const growsLeft = !props.left
|
|
117
|
+
const grow = event.key === (growsLeft ? 'ArrowLeft' : 'ArrowRight')
|
|
118
|
+
panelWidth.value = clampWidth(current + (grow ? step : -step))
|
|
119
|
+
event.preventDefault()
|
|
120
|
+
}
|
|
121
|
+
|
|
61
122
|
const defaultWidth = computed(() => !props.sm && !props.md && !props.lg)
|
|
62
123
|
|
|
63
124
|
const drawerPanelClass = computed(() => [
|
|
@@ -160,12 +221,23 @@ function handlePanelAfterLeave() {
|
|
|
160
221
|
>
|
|
161
222
|
<div v-if="isPanelVisible"
|
|
162
223
|
ref="drawerPanelRef"
|
|
163
|
-
:class="drawerPanelClass"
|
|
224
|
+
:class="[drawerPanelClass, { 'rsui-drawer__panel--resizing': isResizing }]"
|
|
225
|
+
:style="panelStyle"
|
|
164
226
|
role="dialog"
|
|
165
227
|
:aria-modal="!nonModal"
|
|
166
228
|
:aria-labelledby="$slots.header ? drawerHeaderId : undefined"
|
|
167
229
|
tabindex="-1"
|
|
168
230
|
>
|
|
231
|
+
<div v-if="resizable"
|
|
232
|
+
class="rsui-drawer__resize-handle"
|
|
233
|
+
role="separator"
|
|
234
|
+
aria-orientation="vertical"
|
|
235
|
+
aria-label="Resize drawer"
|
|
236
|
+
tabindex="0"
|
|
237
|
+
@pointerdown="startResize"
|
|
238
|
+
@keydown="onHandleKeydown"
|
|
239
|
+
></div>
|
|
240
|
+
|
|
169
241
|
<button v-if="closeIcon"
|
|
170
242
|
type="button"
|
|
171
243
|
class="rsui-drawer__close-icon"
|
|
@@ -26,6 +26,10 @@ const props = defineProps({
|
|
|
26
26
|
type: Boolean,
|
|
27
27
|
default: true,
|
|
28
28
|
},
|
|
29
|
+
noClamp: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
29
33
|
/**
|
|
30
34
|
* Heading level (1-6) for the title. When set, the title renders as a real
|
|
31
35
|
* <h1>-<h6> so consuming pages get a correct document outline (WCAG 1.3.1,
|
|
@@ -80,9 +84,9 @@ const titleTag = computed(() => props.headingLevel ? `h${props.headingLevel}` :
|
|
|
80
84
|
>
|
|
81
85
|
<div class="rsui-section-header__header">
|
|
82
86
|
|
|
83
|
-
<!-- Icon slot, optional -->
|
|
87
|
+
<!-- Icon slot, optional — hidden on narrow sections -->
|
|
84
88
|
<div class="rsui-section-header__icon"
|
|
85
|
-
v-if="$slots.icon"
|
|
89
|
+
v-if="$slots.icon && responsiveWidth.specific"
|
|
86
90
|
>
|
|
87
91
|
<slot name="icon"></slot>
|
|
88
92
|
</div>
|
|
@@ -93,8 +97,16 @@ const titleTag = computed(() => props.headingLevel ? `h${props.headingLevel}` :
|
|
|
93
97
|
}">
|
|
94
98
|
|
|
95
99
|
<!-- Title slot, default slot -->
|
|
96
|
-
<div class="
|
|
97
|
-
|
|
100
|
+
<div :class="[
|
|
101
|
+
'rsui-section-header__title',
|
|
102
|
+
{ 'rsui-section-header__title--stacked': !responsiveWidth.specific },
|
|
103
|
+
]">
|
|
104
|
+
<component :is="titleTag"
|
|
105
|
+
:class="[
|
|
106
|
+
'rsui-section-header__title-text',
|
|
107
|
+
{ 'rsui-section-header__title-text--no-clamp': noClamp },
|
|
108
|
+
]"
|
|
109
|
+
>
|
|
98
110
|
<slot></slot>
|
|
99
111
|
</component>
|
|
100
112
|
<div v-if="$slots.badge" class="rsui-section-header__badge">
|