@cloudron/pankow 4.4.1 → 4.4.2

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.
@@ -2,6 +2,11 @@
2
2
  import { ref, computed, watch, onMounted, onUnmounted, useTemplateRef } from 'vue';
3
3
 
4
4
  const props = defineProps({
5
+ orientation: {
6
+ type: String,
7
+ default: 'horizontal'
8
+ },
9
+ // horizontal mode props
5
10
  leftWidth: {
6
11
  type: Number,
7
12
  default: 50
@@ -13,40 +18,88 @@ const props = defineProps({
13
18
  minRightWidth: {
14
19
  type: Number,
15
20
  default: 20
21
+ },
22
+ // vertical mode props
23
+ topHeight: {
24
+ type: Number,
25
+ default: 50
26
+ },
27
+ minTopHeight: {
28
+ type: Number,
29
+ default: 20
30
+ },
31
+ minBottomHeight: {
32
+ type: Number,
33
+ default: 20
34
+ },
35
+ opaque: {
36
+ type: Boolean,
37
+ default: false
16
38
  }
17
39
  });
18
40
 
19
- const emit = defineEmits(['update:leftWidth']);
41
+ const emit = defineEmits(['update:leftWidth', 'update:topHeight']);
42
+
43
+ const isHorizontal = computed(() => props.orientation === 'horizontal');
20
44
 
21
45
  const containerRef = useTemplateRef('container');
22
46
  const isDragging = ref(false);
23
- const dragStartX = ref(0);
24
- const dragStartWidth = ref(0);
25
- const currentLeftWidth = ref(props.leftWidth);
47
+ const dragStartCoord = ref(0);
48
+ const dragStartSize = ref(0);
49
+
50
+ const currentFirstSize = ref(
51
+ isHorizontal.value ? props.leftWidth : props.topHeight
52
+ );
26
53
 
27
54
  watch(() => props.leftWidth, (val) => {
55
+ if (!isDragging.value && isHorizontal.value) {
56
+ currentFirstSize.value = val;
57
+ }
58
+ });
59
+
60
+ watch(() => props.topHeight, (val) => {
61
+ if (!isDragging.value && !isHorizontal.value) {
62
+ currentFirstSize.value = val;
63
+ }
64
+ });
65
+
66
+ watch(() => props.orientation, () => {
28
67
  if (!isDragging.value) {
29
- currentLeftWidth.value = val;
68
+ currentFirstSize.value = isHorizontal.value ? props.leftWidth : props.topHeight;
30
69
  }
31
70
  });
32
71
 
72
+ const minFirst = computed(() =>
73
+ isHorizontal.value ? props.minLeftWidth : props.minTopHeight
74
+ );
75
+
76
+ const minSecond = computed(() =>
77
+ isHorizontal.value ? props.minRightWidth : props.minBottomHeight
78
+ );
79
+
33
80
  function startDrag(e) {
34
81
  isDragging.value = true;
35
- dragStartX.value = e.clientX ?? e.touches?.[0]?.clientX ?? 0;
36
- dragStartWidth.value = currentLeftWidth.value;
37
- document.body.style.cursor = 'col-resize';
82
+ dragStartCoord.value = isHorizontal.value
83
+ ? (e.clientX ?? e.touches?.[0]?.clientX ?? 0)
84
+ : (e.clientY ?? e.touches?.[0]?.clientY ?? 0);
85
+ dragStartSize.value = currentFirstSize.value;
86
+ document.body.style.cursor = isHorizontal.value ? 'col-resize' : 'row-resize';
38
87
  document.body.style.userSelect = 'none';
39
88
  e.preventDefault();
40
89
  }
41
90
 
42
91
  function onDrag(e) {
43
92
  if (!isDragging.value || !containerRef.value) return;
44
- const clientX = e.clientX ?? e.touches?.[0]?.clientX ?? 0;
45
- const containerWidth = containerRef.value.getBoundingClientRect().width;
46
- if (containerWidth === 0) return;
47
- const delta = ((clientX - dragStartX.value) / containerWidth) * 100;
48
- const newWidth = dragStartWidth.value + delta;
49
- currentLeftWidth.value = Math.max(props.minLeftWidth, Math.min(100 - props.minRightWidth, newWidth));
93
+ const coord = isHorizontal.value
94
+ ? (e.clientX ?? e.touches?.[0]?.clientX ?? 0)
95
+ : (e.clientY ?? e.touches?.[0]?.clientY ?? 0);
96
+ const containerSize = isHorizontal.value
97
+ ? containerRef.value.getBoundingClientRect().width
98
+ : containerRef.value.getBoundingClientRect().height;
99
+ if (containerSize === 0) return;
100
+ const delta = ((coord - dragStartCoord.value) / containerSize) * 100;
101
+ const newSize = dragStartSize.value + delta;
102
+ currentFirstSize.value = Math.max(minFirst.value, Math.min(100 - minSecond.value, newSize));
50
103
  }
51
104
 
52
105
  function stopDrag() {
@@ -54,7 +107,11 @@ function stopDrag() {
54
107
  isDragging.value = false;
55
108
  document.body.style.cursor = '';
56
109
  document.body.style.userSelect = '';
57
- emit('update:leftWidth', Math.round(currentLeftWidth.value));
110
+ if (isHorizontal.value) {
111
+ emit('update:leftWidth', Math.round(currentFirstSize.value));
112
+ } else {
113
+ emit('update:topHeight', Math.round(currentFirstSize.value));
114
+ }
58
115
  }
59
116
 
60
117
  onMounted(() => {
@@ -71,21 +128,35 @@ onUnmounted(() => {
71
128
  document.removeEventListener('touchend', stopDrag);
72
129
  });
73
130
 
74
- const leftStyle = computed(() => ({
75
- flex: `0 0 ${currentLeftWidth.value}%`,
76
- maxWidth: `${currentLeftWidth.value}%`
77
- }));
131
+ const firstStyle = computed(() => {
132
+ const size = currentFirstSize.value;
133
+ return isHorizontal.value
134
+ ? { flex: `0 0 ${size}%`, maxWidth: `${size}%` }
135
+ : { flex: `0 0 ${size}%`, maxHeight: `${size}%` };
136
+ });
78
137
  </script>
79
138
 
80
139
  <template>
81
- <div ref="container" class="pankow-split-layout" :class="{ 'pankow-split-layout-dragging': isDragging }">
82
- <div class="pankow-split-layout-left" :style="leftStyle">
140
+ <div
141
+ ref="container"
142
+ class="pankow-split-layout"
143
+ :class="{
144
+ 'pankow-split-layout-dragging': isDragging,
145
+ 'pankow-split-layout-vertical': !isHorizontal,
146
+ 'pankow-split-layout-divider-opaque': opaque
147
+ }"
148
+ >
149
+ <div class="pankow-split-layout-first" :style="firstStyle">
83
150
  <slot name="left" />
84
151
  </div>
85
- <div class="pankow-split-layout-divider" @mousedown="startDrag" @touchstart.prevent="startDrag">
152
+ <div
153
+ class="pankow-split-layout-divider"
154
+ @mousedown="startDrag"
155
+ @touchstart.prevent="startDrag"
156
+ >
86
157
  <div class="pankow-split-layout-handle"><span></span><span></span></div>
87
158
  </div>
88
- <div class="pankow-split-layout-right">
159
+ <div class="pankow-split-layout-second">
89
160
  <slot name="right" />
90
161
  </div>
91
162
  </div>
@@ -100,15 +171,22 @@ const leftStyle = computed(() => ({
100
171
  overflow: hidden;
101
172
  }
102
173
 
103
- .pankow-split-layout-left {
104
- height: 100%;
174
+ .pankow-split-layout-vertical {
175
+ flex-direction: column;
176
+ }
177
+
178
+ .pankow-split-layout-first {
105
179
  min-width: 0;
106
180
  overflow: hidden;
107
181
  }
108
182
 
183
+ .pankow-split-layout-vertical .pankow-split-layout-first {
184
+ height: auto;
185
+ min-height: 0;
186
+ min-width: 0;
187
+ }
188
+
109
189
  .pankow-split-layout-divider {
110
- width: 6px;
111
- cursor: col-resize;
112
190
  background: transparent;
113
191
  position: relative;
114
192
  flex-shrink: 0;
@@ -117,6 +195,20 @@ const leftStyle = computed(() => ({
117
195
  justify-content: center;
118
196
  }
119
197
 
198
+ .pankow-split-layout:not(.pankow-split-layout-vertical) .pankow-split-layout-divider {
199
+ width: 6px;
200
+ cursor: col-resize;
201
+ }
202
+
203
+ .pankow-split-layout-vertical .pankow-split-layout-divider {
204
+ height: 6px;
205
+ cursor: row-resize;
206
+ }
207
+
208
+ .pankow-split-layout-divider-opaque .pankow-split-layout-divider {
209
+ background: var(--pankow-color-background);
210
+ }
211
+
120
212
  .pankow-split-layout-divider:hover,
121
213
  .pankow-split-layout-dragging .pankow-split-layout-divider {
122
214
  background: var(--pankow-input-border-color);
@@ -128,13 +220,20 @@ const leftStyle = computed(() => ({
128
220
  left: 50%;
129
221
  transform: translate(-50%, -50%);
130
222
  display: flex;
131
- flex-direction: column;
132
223
  gap: 2px;
133
224
  opacity: 0;
134
225
  transition: opacity 0.15s;
135
226
  pointer-events: none;
136
227
  }
137
228
 
229
+ .pankow-split-layout:not(.pankow-split-layout-vertical) .pankow-split-layout-handle {
230
+ flex-direction: column;
231
+ }
232
+
233
+ .pankow-split-layout-vertical .pankow-split-layout-handle {
234
+ flex-direction: row;
235
+ }
236
+
138
237
  .pankow-split-layout-divider:hover .pankow-split-layout-handle,
139
238
  .pankow-split-layout-dragging .pankow-split-layout-handle {
140
239
  opacity: 0.5;
@@ -142,21 +241,34 @@ const leftStyle = computed(() => ({
142
241
 
143
242
  .pankow-split-layout-handle span {
144
243
  display: block;
145
- width: 2px;
146
- height: 16px;
147
244
  border-radius: 1px;
148
245
  background: var(--pankow-color-text);
149
246
  }
150
247
 
151
- .pankow-split-layout-right {
248
+ .pankow-split-layout:not(.pankow-split-layout-vertical) .pankow-split-layout-handle span {
249
+ width: 2px;
250
+ height: 16px;
251
+ }
252
+
253
+ .pankow-split-layout-vertical .pankow-split-layout-handle span {
254
+ width: 16px;
255
+ height: 2px;
256
+ }
257
+
258
+ .pankow-split-layout-second {
152
259
  flex: 1;
153
- height: 100%;
154
260
  min-width: 0;
155
261
  overflow: hidden;
156
262
  }
157
263
 
158
- .pankow-split-layout-dragging .pankow-split-layout-left,
159
- .pankow-split-layout-dragging .pankow-split-layout-right {
264
+ .pankow-split-layout-vertical .pankow-split-layout-second {
265
+ height: auto;
266
+ min-height: 0;
267
+ min-width: 0;
268
+ }
269
+
270
+ .pankow-split-layout-dragging .pankow-split-layout-first,
271
+ .pankow-split-layout-dragging .pankow-split-layout-second {
160
272
  pointer-events: none;
161
273
  }
162
274
  </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudron/pankow",
3
3
  "private": false,
4
- "version": "4.4.1",
4
+ "version": "4.4.2",
5
5
  "description": "Vue 3 UI component library for Cloudron apps",
6
6
  "main": "index.js",
7
7
  "types": "types/index.d.ts",