@redseed/redseed-ui-vue3 8.44.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redseed/redseed-ui-vue3",
3
- "version": "8.44.0",
3
+ "version": "8.45.0",
4
4
  "description": "RedSeed UI Vue 3 components",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/redseedtraining/redseed-ui",
@@ -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"