hamzus-ui 0.0.207 → 0.0.208
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,308 +1,307 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
2
|
+
import { onMount, onDestroy } from 'svelte';
|
|
3
|
+
import { browser } from '$app/environment';
|
|
4
|
+
|
|
5
|
+
export let element = null;
|
|
6
|
+
export let thickness = 15;
|
|
7
|
+
export let padding = 1;
|
|
8
|
+
|
|
9
|
+
let thumbHeight = 0;
|
|
10
|
+
let thumbTop = 0;
|
|
11
|
+
let hasScrollY = false;
|
|
12
|
+
|
|
13
|
+
let thumbWidth = 0;
|
|
14
|
+
let thumbLeft = 0;
|
|
15
|
+
let hasScrollX = false;
|
|
16
|
+
|
|
17
|
+
// ── Mesure ──────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
function measure(el) {
|
|
20
|
+
const { clientHeight, scrollHeight, scrollTop, clientWidth, scrollWidth, scrollLeft } = el;
|
|
21
|
+
|
|
22
|
+
hasScrollY = scrollHeight > clientHeight;
|
|
23
|
+
thumbHeight = hasScrollY ? (clientHeight / scrollHeight) * clientHeight : clientHeight;
|
|
24
|
+
thumbTop = hasScrollY
|
|
25
|
+
? (scrollTop / (scrollHeight - clientHeight)) * (clientHeight - thumbHeight)
|
|
26
|
+
: 0;
|
|
27
|
+
|
|
28
|
+
hasScrollX = scrollWidth > clientWidth;
|
|
29
|
+
thumbWidth = hasScrollX ? (clientWidth / scrollWidth) * clientWidth : clientWidth;
|
|
30
|
+
thumbLeft = hasScrollX
|
|
31
|
+
? (scrollLeft / (scrollWidth - clientWidth)) * (clientWidth - thumbWidth)
|
|
32
|
+
: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Press & hold sur la track ───────────────────────────────
|
|
36
|
+
|
|
37
|
+
let trackPressInterval = null;
|
|
38
|
+
|
|
39
|
+
function stopTrackPress() {
|
|
40
|
+
if (trackPressInterval) {
|
|
41
|
+
clearInterval(trackPressInterval);
|
|
42
|
+
trackPressInterval = null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function onTrackYMouseDown(e) {
|
|
47
|
+
if (!element || e.target !== e.currentTarget) return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
const target = e.currentTarget;
|
|
50
|
+
|
|
51
|
+
function step() {
|
|
52
|
+
if (!element) return;
|
|
53
|
+
const rect = target.getBoundingClientRect();
|
|
54
|
+
const clickY = e.clientY - rect.top;
|
|
55
|
+
const direction = clickY < thumbTop ? -1 : 1;
|
|
56
|
+
element.scrollTop += direction * element.clientHeight * 0.8;
|
|
57
|
+
measure(element);
|
|
58
|
+
if (direction === -1 && thumbTop <= clickY) stopTrackPress();
|
|
59
|
+
if (direction === 1 && thumbTop + thumbHeight >= clickY) stopTrackPress();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
step();
|
|
63
|
+
trackPressInterval = setInterval(step, 120);
|
|
64
|
+
window.addEventListener('mouseup', stopTrackPress, { once: true });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function onTrackXMouseDown(e) {
|
|
68
|
+
if (!element || e.target !== e.currentTarget) return;
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
const target = e.currentTarget;
|
|
71
|
+
|
|
72
|
+
function step() {
|
|
73
|
+
if (!element) return;
|
|
74
|
+
const rect = target.getBoundingClientRect();
|
|
75
|
+
const clickX = e.clientX - rect.left;
|
|
76
|
+
const direction = clickX < thumbLeft ? -1 : 1;
|
|
77
|
+
element.scrollLeft += direction * element.clientWidth * 0.8;
|
|
78
|
+
measure(element);
|
|
79
|
+
if (direction === -1 && thumbLeft <= clickX) stopTrackPress();
|
|
80
|
+
if (direction === 1 && thumbLeft + thumbWidth >= clickX) stopTrackPress();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
step();
|
|
84
|
+
trackPressInterval = setInterval(step, 120);
|
|
85
|
+
window.addEventListener('mouseup', stopTrackPress, { once: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── Drag vertical ───────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
let draggingY = false;
|
|
91
|
+
let dragStartY = 0;
|
|
92
|
+
let dragStartScrollTop = 0;
|
|
93
|
+
|
|
94
|
+
function onThumbYMouseDown(e) {
|
|
95
|
+
if (!element) return;
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
draggingY = true;
|
|
98
|
+
dragStartY = e.clientY;
|
|
99
|
+
dragStartScrollTop = element.scrollTop;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function onMouseMoveY(e) {
|
|
103
|
+
if (!draggingY || !element) return;
|
|
104
|
+
const { clientHeight, scrollHeight } = element;
|
|
105
|
+
const thumbH = (clientHeight / scrollHeight) * clientHeight;
|
|
106
|
+
const ratio = (scrollHeight - clientHeight) / (clientHeight - thumbH);
|
|
107
|
+
element.scrollTop = dragStartScrollTop + (e.clientY - dragStartY) * ratio;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function onMouseUpY() {
|
|
111
|
+
draggingY = false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── Drag horizontal ─────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
let draggingX = false;
|
|
117
|
+
let dragStartX = 0;
|
|
118
|
+
let dragStartScrollLeft = 0;
|
|
119
|
+
|
|
120
|
+
function onThumbXMouseDown(e) {
|
|
121
|
+
if (!element) return;
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
draggingX = true;
|
|
124
|
+
dragStartX = e.clientX;
|
|
125
|
+
dragStartScrollLeft = element.scrollLeft;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function onMouseMoveX(e) {
|
|
129
|
+
if (!draggingX || !element) return;
|
|
130
|
+
const { clientWidth, scrollWidth } = element;
|
|
131
|
+
const thumbW = (clientWidth / scrollWidth) * clientWidth;
|
|
132
|
+
const ratio = (scrollWidth - clientWidth) / (clientWidth - thumbW);
|
|
133
|
+
element.scrollLeft = dragStartScrollLeft + (e.clientX - dragStartX) * ratio;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function onMouseUpX() {
|
|
137
|
+
draggingX = false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Listeners globaux (window) ──────────────────────────────
|
|
141
|
+
|
|
142
|
+
function onWindowMouseMove(e) {
|
|
143
|
+
onMouseMoveY(e);
|
|
144
|
+
onMouseMoveX(e);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function onWindowMouseUp() {
|
|
148
|
+
onMouseUpY();
|
|
149
|
+
onMouseUpX();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function addWindowListeners() {
|
|
153
|
+
window.addEventListener('mousemove', onWindowMouseMove);
|
|
154
|
+
window.addEventListener('mouseup', onWindowMouseUp);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function removeWindowListeners() {
|
|
158
|
+
window.removeEventListener('mousemove', onWindowMouseMove);
|
|
159
|
+
window.removeEventListener('mouseup', onWindowMouseUp);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ── Observer setup ──────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
let resizeObserver = null;
|
|
165
|
+
|
|
166
|
+
function handleScroll() {
|
|
167
|
+
if (element) measure(element);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function setupObserver(el) {
|
|
171
|
+
cleanupObserver();
|
|
172
|
+
measure(el);
|
|
173
|
+
|
|
174
|
+
resizeObserver = new ResizeObserver(() => measure(el));
|
|
175
|
+
resizeObserver.observe(el);
|
|
176
|
+
for (const child of Array.from(el.children)) {
|
|
177
|
+
resizeObserver.observe(child);
|
|
178
|
+
}
|
|
179
|
+
el.addEventListener('scroll', handleScroll);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function cleanupObserver() {
|
|
183
|
+
if (element) element.removeEventListener('scroll', handleScroll);
|
|
184
|
+
resizeObserver?.disconnect();
|
|
185
|
+
resizeObserver = null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// $: réactif à `element` — mais uniquement côté client
|
|
189
|
+
$: if (browser && element) {
|
|
190
|
+
setupObserver(element);
|
|
191
|
+
} else if (browser && !element) {
|
|
192
|
+
cleanupObserver();
|
|
193
|
+
stopTrackPress();
|
|
194
|
+
thumbHeight = 0;
|
|
195
|
+
thumbTop = 0;
|
|
196
|
+
hasScrollY = false;
|
|
197
|
+
thumbWidth = 0;
|
|
198
|
+
thumbLeft = 0;
|
|
199
|
+
hasScrollX = false;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Les listeners window uniquement après le montage (côté client)
|
|
203
|
+
onMount(() => {
|
|
204
|
+
addWindowListeners();
|
|
205
|
+
return () => {
|
|
206
|
+
removeWindowListeners();
|
|
207
|
+
cleanupObserver();
|
|
208
|
+
stopTrackPress();
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
onDestroy(() => {
|
|
213
|
+
// onDestroy peut être appelé côté serveur — ne rien faire si pas browser
|
|
214
|
+
if (!browser) return;
|
|
215
|
+
removeWindowListeners();
|
|
216
|
+
cleanupObserver();
|
|
217
|
+
stopTrackPress();
|
|
218
|
+
});
|
|
212
219
|
</script>
|
|
213
220
|
|
|
214
221
|
<div
|
|
215
|
-
|
|
216
|
-
|
|
222
|
+
class="scroll-provider"
|
|
223
|
+
style="--track-padding:{padding}px;--track-thickness:{thickness}px;--thumb-width:{thumbWidth}px;--thumb-height:{thumbHeight}px;--thumb-left:{thumbLeft}px;--thumb-top:{thumbTop}px;"
|
|
217
224
|
>
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<div class="track-v" on:mousedown={onTrackYMouseDown}>
|
|
230
|
-
<span
|
|
231
|
-
class="thumb"
|
|
232
|
-
class:dragging={draggingY}
|
|
233
|
-
on:mousedown={onThumbYMouseDown}
|
|
234
|
-
/>
|
|
235
|
-
</div>
|
|
236
|
-
{/if}
|
|
225
|
+
{#if hasScrollX}
|
|
226
|
+
<div class="track-h" on:mousedown={onTrackXMouseDown}>
|
|
227
|
+
<span class="thumb" class:dragging={draggingX} on:mousedown={onThumbXMouseDown} />
|
|
228
|
+
</div>
|
|
229
|
+
{/if}
|
|
230
|
+
|
|
231
|
+
{#if hasScrollY}
|
|
232
|
+
<div class="track-v" on:mousedown={onTrackYMouseDown}>
|
|
233
|
+
<span class="thumb" class:dragging={draggingY} on:mousedown={onThumbYMouseDown} />
|
|
234
|
+
</div>
|
|
235
|
+
{/if}
|
|
237
236
|
</div>
|
|
238
237
|
|
|
239
238
|
<style>
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
</style>
|
|
239
|
+
.scroll-provider {
|
|
240
|
+
position: absolute;
|
|
241
|
+
top: 0px;
|
|
242
|
+
left: 0px;
|
|
243
|
+
width: 100%;
|
|
244
|
+
height: 100%;
|
|
245
|
+
pointer-events: none;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.track-h,
|
|
249
|
+
.track-v {
|
|
250
|
+
pointer-events: all;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.thumb {
|
|
254
|
+
position: absolute;
|
|
255
|
+
display: flex;
|
|
256
|
+
background-color: var(--bg-blur);
|
|
257
|
+
cursor: grab;
|
|
258
|
+
transition: background-color 0.15s;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.thumb:hover,
|
|
262
|
+
.thumb.dragging {
|
|
263
|
+
background-color: var(--accent-b);
|
|
264
|
+
cursor: grabbing;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.track-h {
|
|
268
|
+
position: absolute;
|
|
269
|
+
bottom: 0px;
|
|
270
|
+
left: 0px;
|
|
271
|
+
width: 100%;
|
|
272
|
+
height: var(--track-thickness);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.track-h .thumb {
|
|
276
|
+
width: calc(var(--thumb-width) - var(--track-padding) * 2);
|
|
277
|
+
height: calc(100% - var(--track-padding) * 2);
|
|
278
|
+
left: calc(var(--thumb-left) + var(--track-padding));
|
|
279
|
+
top: calc(0px + var(--track-padding));
|
|
280
|
+
border-radius: var(--radius-s);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.track-v {
|
|
284
|
+
position: absolute;
|
|
285
|
+
top: 0px;
|
|
286
|
+
right: 0px;
|
|
287
|
+
height: 100%;
|
|
288
|
+
width: var(--track-thickness);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.track-v .thumb {
|
|
292
|
+
height: calc(var(--thumb-height) - var(--track-padding) * 2);
|
|
293
|
+
width: calc(100% - var(--track-padding) * 2);
|
|
294
|
+
top: calc(var(--thumb-top) + 1px);
|
|
295
|
+
left: calc(0px + 1px);
|
|
296
|
+
border-radius: var(--radius-s);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
@media (max-width: 750px) {
|
|
300
|
+
.track-h {
|
|
301
|
+
height: 5px;
|
|
302
|
+
}
|
|
303
|
+
.track-v {
|
|
304
|
+
width: 5px;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
</style>
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
>
|
|
216
216
|
<DropdownMenu.Trigger slot="trigger">
|
|
217
217
|
<Button style="width:100%;" avoidRipple={!column.isSearchable} variant="ghost">
|
|
218
|
-
<
|
|
218
|
+
<h5>{column.label}</h5>
|
|
219
219
|
<h4>
|
|
220
220
|
{$table.sort &&
|
|
221
221
|
$table.sort.columnName === column.name &&
|