@adaptabletools/adaptable 23.0.9 → 23.0.11
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/index.css +56 -8
- package/package.json +1 -1
- package/src/View/Components/AdaptableDateInput/index.d.ts +1 -0
- package/src/View/Components/AdaptableDateInput/index.js +2 -1
- package/src/View/Components/ColumnFilter/FloatingFilter.js +13 -13
- package/src/View/Components/ColumnFilter/components/ColumnFilterInput.d.ts +3 -0
- package/src/View/Components/ColumnFilter/components/ColumnFilterInput.js +6 -5
- package/src/View/Components/ColumnFilter/components/FloatingFilterInputList.js +33 -21
- package/src/components/Combobox/index.js +5 -1
- package/src/components/Datepicker/index.d.ts +1 -0
- package/src/components/Datepicker/index.js +2 -2
- package/src/components/WindowModal/WindowModal.d.ts +6 -0
- package/src/components/WindowModal/WindowModal.js +232 -31
- package/src/components/ui/combobox.js +1 -1
- package/src/components/utils/useDraggable.d.ts +3 -1
- package/src/components/utils/useDraggable.js +67 -44
- package/src/env.js +2 -2
- package/tsconfig.esm.tsbuildinfo +1 -1
|
@@ -5,6 +5,7 @@ import useDraggable from '../utils/useDraggable';
|
|
|
5
5
|
import { isBrowserDocumentAvailable } from '../../View/UIHelper';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { useStacking } from './useStacking';
|
|
8
|
+
import { clamp } from '../../Utilities/Extensions/NumberExtensions';
|
|
8
9
|
let portalElement;
|
|
9
10
|
const ensurePortalElement = () => {
|
|
10
11
|
if (!isBrowserDocumentAvailable()) {
|
|
@@ -17,7 +18,55 @@ const ensurePortalElement = () => {
|
|
|
17
18
|
portalElement.classList.add('ab-cmp-modal-window');
|
|
18
19
|
document.body.appendChild(portalElement);
|
|
19
20
|
};
|
|
20
|
-
const normalizeTopLeft = (position) =>
|
|
21
|
+
const normalizeTopLeft = (position, edgeOffset) => position < edgeOffset ? edgeOffset : position;
|
|
22
|
+
export const WINDOW_MODAL_VIEWPORT_EDGE_OFFSET = 10;
|
|
23
|
+
const getViewportSize = () => {
|
|
24
|
+
if (!isBrowserDocumentAvailable()) {
|
|
25
|
+
return { width: Infinity, height: Infinity };
|
|
26
|
+
}
|
|
27
|
+
return { width: window.innerWidth, height: window.innerHeight };
|
|
28
|
+
};
|
|
29
|
+
const parsePxConstraint = (value) => {
|
|
30
|
+
if (!value) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const match = /^(-?\d+(?:\.\d+)?)px$/.exec(value.trim());
|
|
34
|
+
if (!match) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const parsed = Number(match[1]);
|
|
38
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;
|
|
39
|
+
};
|
|
40
|
+
const readDomSizeConstraints = (element) => {
|
|
41
|
+
if (!element || !isBrowserDocumentAvailable()) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
const computed = window.getComputedStyle(element);
|
|
45
|
+
return {
|
|
46
|
+
minWidth: parsePxConstraint(computed.minWidth),
|
|
47
|
+
minHeight: parsePxConstraint(computed.minHeight),
|
|
48
|
+
maxWidth: parsePxConstraint(computed.maxWidth),
|
|
49
|
+
maxHeight: parsePxConstraint(computed.maxHeight),
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export const clampWindowModalToViewport = (position, size, minWidth = 0, minHeight = 0, edgeOffset = WINDOW_MODAL_VIEWPORT_EDGE_OFFSET) => {
|
|
53
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportSize();
|
|
54
|
+
const width = clamp(size.width, minWidth, Math.max(minWidth, viewportWidth - 2 * edgeOffset));
|
|
55
|
+
const height = clamp(size.height, minHeight, Math.max(minHeight, viewportHeight - 2 * edgeOffset));
|
|
56
|
+
const x = clamp(position.x, edgeOffset, Math.max(edgeOffset, viewportWidth - edgeOffset - width));
|
|
57
|
+
const y = clamp(position.y, edgeOffset, Math.max(edgeOffset, viewportHeight - edgeOffset - height));
|
|
58
|
+
return {
|
|
59
|
+
position: { x, y },
|
|
60
|
+
size: { width, height },
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export const clampWindowModalPositionToViewport = (position, size, edgeOffset = WINDOW_MODAL_VIEWPORT_EDGE_OFFSET) => {
|
|
64
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportSize();
|
|
65
|
+
return {
|
|
66
|
+
x: clamp(position.x, edgeOffset, Math.max(edgeOffset, viewportWidth - edgeOffset - size.width)),
|
|
67
|
+
y: clamp(position.y, edgeOffset, Math.max(edgeOffset, viewportHeight - edgeOffset - size.height)),
|
|
68
|
+
};
|
|
69
|
+
};
|
|
21
70
|
const getResizePositionDelta = (direction, delta) => {
|
|
22
71
|
const positionDelta = { x: 0, y: 0 };
|
|
23
72
|
const left = -delta.width;
|
|
@@ -38,16 +87,126 @@ const getResizePositionDelta = (direction, delta) => {
|
|
|
38
87
|
}
|
|
39
88
|
return null;
|
|
40
89
|
};
|
|
90
|
+
const resizeDirectionAffects = (direction) => ({
|
|
91
|
+
left: ['left', 'topLeft', 'bottomLeft'].includes(direction),
|
|
92
|
+
top: ['top', 'topLeft', 'topRight'].includes(direction),
|
|
93
|
+
right: ['right', 'topRight', 'bottomRight'].includes(direction),
|
|
94
|
+
bottom: ['bottom', 'bottomLeft', 'bottomRight'].includes(direction),
|
|
95
|
+
});
|
|
96
|
+
const getClampedResizeState = (direction, delta, basePosition, baseSize, minWidth, minHeight, maxWidth, maxHeight, edgeOffset = WINDOW_MODAL_VIEWPORT_EDGE_OFFSET) => {
|
|
97
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportSize();
|
|
98
|
+
const affects = resizeDirectionAffects(direction);
|
|
99
|
+
let deltaWidth = delta.width;
|
|
100
|
+
let deltaHeight = delta.height;
|
|
101
|
+
if (affects.left) {
|
|
102
|
+
deltaWidth = Math.min(deltaWidth, Math.max(0, basePosition.x - edgeOffset));
|
|
103
|
+
}
|
|
104
|
+
if (affects.top) {
|
|
105
|
+
deltaHeight = Math.min(deltaHeight, Math.max(0, basePosition.y - edgeOffset));
|
|
106
|
+
}
|
|
107
|
+
if (affects.right) {
|
|
108
|
+
deltaWidth = Math.min(deltaWidth, viewportWidth - edgeOffset - basePosition.x - baseSize.width);
|
|
109
|
+
}
|
|
110
|
+
if (affects.bottom) {
|
|
111
|
+
deltaHeight = Math.min(deltaHeight, viewportHeight - edgeOffset - basePosition.y - baseSize.height);
|
|
112
|
+
}
|
|
113
|
+
if (affects.left || affects.right) {
|
|
114
|
+
const maxDeltaWidth = maxWidth != null ? maxWidth - baseSize.width : Infinity;
|
|
115
|
+
const minDeltaWidth = minWidth - baseSize.width;
|
|
116
|
+
if (minDeltaWidth <= maxDeltaWidth) {
|
|
117
|
+
deltaWidth = clamp(deltaWidth, minDeltaWidth, maxDeltaWidth);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (affects.top || affects.bottom) {
|
|
121
|
+
const maxDeltaHeight = maxHeight != null ? maxHeight - baseSize.height : Infinity;
|
|
122
|
+
const minDeltaHeight = minHeight - baseSize.height;
|
|
123
|
+
if (minDeltaHeight <= maxDeltaHeight) {
|
|
124
|
+
deltaHeight = clamp(deltaHeight, minDeltaHeight, maxDeltaHeight);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const adjustedDelta = { width: deltaWidth, height: deltaHeight };
|
|
128
|
+
const positionDelta = getResizePositionDelta(direction, adjustedDelta);
|
|
129
|
+
const newPosition = {
|
|
130
|
+
x: basePosition.x + (positionDelta?.x ?? 0),
|
|
131
|
+
y: basePosition.y + (positionDelta?.y ?? 0),
|
|
132
|
+
};
|
|
133
|
+
const newSize = {
|
|
134
|
+
width: baseSize.width + deltaWidth,
|
|
135
|
+
height: baseSize.height + deltaHeight,
|
|
136
|
+
};
|
|
137
|
+
const clamped = clampWindowModalToViewport(newPosition, newSize, minWidth, minHeight, edgeOffset);
|
|
138
|
+
return {
|
|
139
|
+
...clamped,
|
|
140
|
+
positionDelta: positionDelta
|
|
141
|
+
? {
|
|
142
|
+
x: clamped.position.x - basePosition.x,
|
|
143
|
+
y: clamped.position.y - basePosition.y,
|
|
144
|
+
}
|
|
145
|
+
: null,
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
const RESIZE_HANDLE_CLASS_PREFIX = 'ab-WindowModal__resize-handle';
|
|
149
|
+
const RESIZE_EDGE_HANDLES = ['left', 'right', 'top', 'bottom'];
|
|
150
|
+
const RESIZE_HANDLE_CLASSES = {
|
|
151
|
+
left: `${RESIZE_HANDLE_CLASS_PREFIX}--left`,
|
|
152
|
+
right: `${RESIZE_HANDLE_CLASS_PREFIX}--right`,
|
|
153
|
+
top: `${RESIZE_HANDLE_CLASS_PREFIX}--top`,
|
|
154
|
+
bottom: `${RESIZE_HANDLE_CLASS_PREFIX}--bottom`,
|
|
155
|
+
};
|
|
156
|
+
const AT_CONSTRAINT_EPSILON = 0.5;
|
|
157
|
+
const GROW_CURSOR = {
|
|
158
|
+
left: 'w-resize',
|
|
159
|
+
right: 'e-resize',
|
|
160
|
+
top: 'n-resize',
|
|
161
|
+
bottom: 's-resize',
|
|
162
|
+
};
|
|
163
|
+
const SHRINK_CURSOR = {
|
|
164
|
+
left: 'e-resize',
|
|
165
|
+
right: 'w-resize',
|
|
166
|
+
top: 's-resize',
|
|
167
|
+
bottom: 'n-resize',
|
|
168
|
+
};
|
|
169
|
+
const getEdgeResizeCursor = (edge, size, constraints) => {
|
|
170
|
+
const isHorizontal = edge === 'left' || edge === 'right';
|
|
171
|
+
const value = isHorizontal ? size.width : size.height;
|
|
172
|
+
const min = isHorizontal ? constraints.minWidth : constraints.minHeight;
|
|
173
|
+
const max = isHorizontal ? constraints.maxWidth : constraints.maxHeight;
|
|
174
|
+
const atMax = max != null && value >= max - AT_CONSTRAINT_EPSILON;
|
|
175
|
+
const atMin = value <= min + AT_CONSTRAINT_EPSILON;
|
|
176
|
+
if (atMax && !atMin) {
|
|
177
|
+
return SHRINK_CURSOR[edge];
|
|
178
|
+
}
|
|
179
|
+
if (atMin && !atMax) {
|
|
180
|
+
return GROW_CURSOR[edge];
|
|
181
|
+
}
|
|
182
|
+
return isHorizontal ? 'ew-resize' : 'ns-resize';
|
|
183
|
+
};
|
|
184
|
+
const updateResizeHandleCursors = (container, size, constraints) => {
|
|
185
|
+
if (!container) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
RESIZE_EDGE_HANDLES.forEach((edge) => {
|
|
189
|
+
const handle = container.querySelector(`.${RESIZE_HANDLE_CLASSES[edge]}`);
|
|
190
|
+
if (handle) {
|
|
191
|
+
handle.style.cursor = getEdgeResizeCursor(edge, size, constraints);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
};
|
|
41
195
|
export const WindowModal = (props) => {
|
|
42
196
|
ensurePortalElement();
|
|
43
197
|
const positionDeltaRef = React.useRef(null);
|
|
198
|
+
const lastClampedRef = React.useRef(null);
|
|
44
199
|
const normalizedPosition = {
|
|
45
|
-
x: normalizeTopLeft(props.position?.x),
|
|
46
|
-
y: normalizeTopLeft(props.position?.y),
|
|
200
|
+
x: normalizeTopLeft(props.position?.x ?? 0, WINDOW_MODAL_VIEWPORT_EDGE_OFFSET),
|
|
201
|
+
y: normalizeTopLeft(props.position?.y ?? 0, WINDOW_MODAL_VIEWPORT_EDGE_OFFSET),
|
|
47
202
|
};
|
|
48
203
|
const positionRef = React.useRef(normalizedPosition);
|
|
204
|
+
const sizeRef = React.useRef(props.size);
|
|
49
205
|
const stacking = useStacking();
|
|
50
206
|
positionRef.current = normalizedPosition;
|
|
207
|
+
sizeRef.current = props.size;
|
|
208
|
+
const minWidth = props.minWidth ?? 0;
|
|
209
|
+
const minHeight = props.minHeight ?? 0;
|
|
51
210
|
const style = {
|
|
52
211
|
zIndex: stacking.zIndex,
|
|
53
212
|
position: 'absolute',
|
|
@@ -59,41 +218,83 @@ export const WindowModal = (props) => {
|
|
|
59
218
|
x: positionRef.current.x + dx,
|
|
60
219
|
y: positionRef.current.y + dy,
|
|
61
220
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
221
|
+
const size = sizeRef.current;
|
|
222
|
+
const position = clampWindowModalPositionToViewport(newPosition, size, WINDOW_MODAL_VIEWPORT_EDGE_OFFSET);
|
|
223
|
+
props.onChange({ position, size });
|
|
66
224
|
};
|
|
67
225
|
const { targetRef, applyTransform } = useDraggable({
|
|
68
226
|
handleSelector: props.handleSelector,
|
|
69
227
|
onDrop: handleDrop,
|
|
228
|
+
edgeOffset: WINDOW_MODAL_VIEWPORT_EDGE_OFFSET,
|
|
70
229
|
});
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
height: props.size.height + delta.height,
|
|
230
|
+
const constraintsRef = React.useRef({ minWidth, minHeight });
|
|
231
|
+
const getContentElement = () => {
|
|
232
|
+
const resizableEl = targetRef.current?.firstElementChild;
|
|
233
|
+
return resizableEl?.firstElementChild ?? null;
|
|
234
|
+
};
|
|
235
|
+
const computeEffectiveConstraints = () => {
|
|
236
|
+
const dom = readDomSizeConstraints(getContentElement());
|
|
237
|
+
return {
|
|
238
|
+
minWidth: Math.max(minWidth, dom.minWidth ?? 0),
|
|
239
|
+
minHeight: Math.max(minHeight, dom.minHeight ?? 0),
|
|
240
|
+
maxWidth: dom.maxWidth,
|
|
241
|
+
maxHeight: dom.maxHeight,
|
|
84
242
|
};
|
|
85
|
-
props.onChange({
|
|
86
|
-
position: newPosition,
|
|
87
|
-
size: newSize,
|
|
88
|
-
});
|
|
89
243
|
};
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
244
|
+
const handleResizeStart = () => {
|
|
245
|
+
constraintsRef.current = computeEffectiveConstraints();
|
|
246
|
+
updateResizeHandleCursors(targetRef.current, sizeRef.current, constraintsRef.current);
|
|
247
|
+
};
|
|
248
|
+
const handleResize = (_event, direction, elementRef, delta) => {
|
|
249
|
+
const constraints = constraintsRef.current;
|
|
250
|
+
const clamped = getClampedResizeState(direction, delta, positionRef.current, sizeRef.current, constraints.minWidth, constraints.minHeight, constraints.maxWidth, constraints.maxHeight);
|
|
251
|
+
lastClampedRef.current = clamped;
|
|
252
|
+
if (clamped.positionDelta) {
|
|
253
|
+
positionDeltaRef.current = clamped.positionDelta;
|
|
254
|
+
applyTransform(clamped.positionDelta.x, clamped.positionDelta.y);
|
|
255
|
+
}
|
|
256
|
+
elementRef.style.width = `${clamped.size.width}px`;
|
|
257
|
+
elementRef.style.height = `${clamped.size.height}px`;
|
|
258
|
+
updateResizeHandleCursors(targetRef.current, clamped.size, constraints);
|
|
259
|
+
if (isBrowserDocumentAvailable() &&
|
|
260
|
+
RESIZE_EDGE_HANDLES.includes(direction)) {
|
|
261
|
+
document.body.style.cursor = getEdgeResizeCursor(direction, clamped.size, constraints);
|
|
95
262
|
}
|
|
96
|
-
}
|
|
263
|
+
};
|
|
264
|
+
React.useEffect(() => {
|
|
265
|
+
updateResizeHandleCursors(targetRef.current, sizeRef.current, computeEffectiveConstraints());
|
|
266
|
+
}, [props.size.width, props.size.height, minWidth, minHeight]);
|
|
267
|
+
const handleResizeStop = () => {
|
|
268
|
+
applyTransform(0, 0);
|
|
269
|
+
positionDeltaRef.current = null;
|
|
270
|
+
if (isBrowserDocumentAvailable()) {
|
|
271
|
+
document.body.style.cursor = '';
|
|
272
|
+
}
|
|
273
|
+
const clamped = lastClampedRef.current ??
|
|
274
|
+
clampWindowModalToViewport(positionRef.current, sizeRef.current, minWidth, minHeight, WINDOW_MODAL_VIEWPORT_EDGE_OFFSET);
|
|
275
|
+
lastClampedRef.current = null;
|
|
276
|
+
props.onChange(clamped);
|
|
277
|
+
};
|
|
278
|
+
const onChangeRef = React.useRef(props.onChange);
|
|
279
|
+
onChangeRef.current = props.onChange;
|
|
280
|
+
React.useEffect(() => {
|
|
281
|
+
if (!isBrowserDocumentAvailable()) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const handleViewportResize = () => {
|
|
285
|
+
const current = positionRef.current;
|
|
286
|
+
const currentSize = sizeRef.current;
|
|
287
|
+
const clamped = clampWindowModalToViewport(current, currentSize, minWidth, minHeight, WINDOW_MODAL_VIEWPORT_EDGE_OFFSET);
|
|
288
|
+
if (clamped.position.x !== current.x ||
|
|
289
|
+
clamped.position.y !== current.y ||
|
|
290
|
+
clamped.size.width !== currentSize.width ||
|
|
291
|
+
clamped.size.height !== currentSize.height) {
|
|
292
|
+
onChangeRef.current(clamped);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
window.addEventListener('resize', handleViewportResize);
|
|
296
|
+
return () => window.removeEventListener('resize', handleViewportResize);
|
|
297
|
+
}, [minWidth, minHeight]);
|
|
97
298
|
const ResizableCmp = Resizable;
|
|
98
299
|
const handleMouseDown = (event) => {
|
|
99
300
|
const node = targetRef.current;
|
|
@@ -102,7 +303,7 @@ export const WindowModal = (props) => {
|
|
|
102
303
|
}
|
|
103
304
|
stacking.bringInFront();
|
|
104
305
|
};
|
|
105
|
-
return createPortal(_jsx("div", { style: style, ref: targetRef, onMouseDown: handleMouseDown, children: _jsx(ResizableCmp, { minWidth:
|
|
306
|
+
return createPortal(_jsx("div", { style: style, ref: targetRef, onMouseDown: handleMouseDown, children: _jsx(ResizableCmp, { minWidth: minWidth, minHeight: minHeight, onResizeStart: handleResizeStart, onResizeStop: handleResizeStop, onResize: handleResize, handleClasses: RESIZE_HANDLE_CLASSES, size: {
|
|
106
307
|
width: props.size.width,
|
|
107
308
|
height: props.size.height,
|
|
108
309
|
}, children: props.children }) }), portalElement);
|
|
@@ -47,7 +47,7 @@ function ComboboxContent({ className, side = 'bottom', sideOffset = 6, align = '
|
|
|
47
47
|
const resizableStyle = resizable
|
|
48
48
|
? { resize: 'both' }
|
|
49
49
|
: undefined;
|
|
50
|
-
return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: `twa:isolate ${POPUP_Z_INDEX}`, children: _jsx(ComboboxPrimitive.Popup, { ref: popupRef, "data-slot": "combobox-content", "data-chips": !!anchor, "data-resizable": resizable || undefined, style: { ...resizableStyle, ...style }, className: cn('twa:group/combobox-content twa:relative twa:origin-(--transform-origin) twa:overflow-hidden twa:rounded-input twa:bg-popover twa:text-popover-foreground twa:shadow-md twa:ring-1 twa:ring-foreground/10 twa:duration-100 twa:data-[side=bottom]:slide-in-from-top-2 twa:data-[side=inline-end]:slide-in-from-left-2 twa:data-[side=inline-start]:slide-in-from-right-2 twa:data-[side=left]:slide-in-from-right-2 twa:data-[side=right]:slide-in-from-left-2 twa:data-[side=top]:slide-in-from-bottom-2 twa:*:data-[slot=input-group]:m-1 twa:*:data-[slot=input-group]:mb-0 twa:*:data-[slot=input-group]:h-8 twa:*:data-[slot=input-group]:border-input/30 twa:*:data-[slot=input-group]:bg-input/30 twa:*:data-[slot=input-group]:shadow-none twa:data-open:animate-in twa:data-open:fade-in-0 twa:data-open:zoom-in-95 twa:data-closed:animate-out twa:data-closed:fade-out-0 twa:data-closed:zoom-out-95', 'twa:max-h-[min(var(--available-height),80vh)]', 'twa:max-w-[min(var(--available-width),80vw)]', 'twa:min-w-[min(calc(var(--anchor-width)+--spacing(7)),var(--available-width),80vw)]', resizable ? 'twa:flex twa:flex-col twa:min-h-24' : 'twa:w-(--anchor-width)', className), ...props }) }) }));
|
|
50
|
+
return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: `twa:isolate ${POPUP_Z_INDEX}`, children: _jsx(ComboboxPrimitive.Popup, { ref: popupRef, "data-slot": "combobox-content", "data-chips": !!anchor, "data-resizable": resizable || undefined, style: { ...resizableStyle, ...style }, className: cn('twa:group/combobox-content twa:relative twa:origin-(--transform-origin) twa:overflow-hidden twa:rounded-input twa:bg-popover twa:text-popover-foreground twa:shadow-md twa:ring-1 twa:ring-foreground/10 twa:duration-100 twa:data-[side=bottom]:slide-in-from-top-2 twa:data-[side=inline-end]:slide-in-from-left-2 twa:data-[side=inline-start]:slide-in-from-right-2 twa:data-[side=left]:slide-in-from-right-2 twa:data-[side=right]:slide-in-from-left-2 twa:data-[side=top]:slide-in-from-bottom-2 twa:*:data-[slot=input-group]:m-1 twa:*:data-[slot=input-group]:mb-0 twa:*:data-[slot=input-group]:h-8 twa:*:data-[slot=input-group]:border-input/30 twa:*:data-[slot=input-group]:bg-input/30 twa:*:data-[slot=input-group]:shadow-none twa:data-open:animate-in twa:data-open:fade-in-0 twa:data-open:zoom-in-95 twa:data-closed:animate-out twa:data-closed:fade-out-0 twa:data-closed:zoom-out-95', 'twa:max-h-[min(var(--available-height,80vh),80vh)]', 'twa:max-w-[min(var(--available-width,80vw),80vw)]', 'twa:min-w-[min(calc(var(--anchor-width)+--spacing(7)),var(--available-width),80vw)]', resizable ? 'twa:flex twa:flex-col twa:min-h-24' : 'twa:w-(--anchor-width)', className), ...props }) }) }));
|
|
51
51
|
}
|
|
52
52
|
const ComboboxList = React.forwardRef(function ComboboxList({ className, ...props }, ref) {
|
|
53
53
|
return (_jsx(ComboboxPrimitive.List, { "data-slot": "combobox-list", className: cn('twa:no-scrollbar twa:max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] twa:scroll-py-1 twa:overflow-y-auto twa:overscroll-contain twa:p-1 twa:data-empty:p-0', RESIZABLE_LIST_CLASS, className), ref: ref, ...props }));
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export default function useDraggable({ onMove, onDrop, getBoundingRect, handleSelector, }: {
|
|
1
|
+
export default function useDraggable({ onMove, onDrop, getBoundingRect, handleSelector, edgeOffset, }: {
|
|
2
2
|
onMove?: (event: MouseEvent) => void;
|
|
3
3
|
onDrop?: (dx: number, dy: number) => void;
|
|
4
4
|
getBoundingRect?: () => DOMRect;
|
|
5
5
|
handleSelector?: string;
|
|
6
|
+
/** Minimum distance to keep from the constrain region edges while dragging. */
|
|
7
|
+
edgeOffset?: number;
|
|
6
8
|
}): {
|
|
7
9
|
handleRef: (newNode: HTMLElement) => void;
|
|
8
10
|
targetRef: import("react").RefObject<HTMLElement>;
|
|
@@ -2,29 +2,34 @@ import { useRef, useCallback, useEffect } from 'react';
|
|
|
2
2
|
function clamp(num, min, max) {
|
|
3
3
|
return num <= min ? min : num >= max ? max : num;
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
const getTranslationBounds = (targetRect, boundingRect) => {
|
|
6
|
+
const left = boundingRect.x - targetRect.x;
|
|
7
|
+
const right = left + boundingRect.width - targetRect.width;
|
|
8
|
+
const top = boundingRect.y - targetRect.y;
|
|
9
|
+
const bottom = top + boundingRect.height - targetRect.height;
|
|
10
|
+
return { left, right, top, bottom };
|
|
11
|
+
};
|
|
12
|
+
const applyEdgeOffsetToBoundingRect = (boundingRect, edgeOffset) => {
|
|
13
|
+
if (!edgeOffset) {
|
|
14
|
+
return boundingRect;
|
|
15
|
+
}
|
|
16
|
+
return new DOMRect(boundingRect.x + edgeOffset, boundingRect.y + edgeOffset, boundingRect.width - 2 * edgeOffset, boundingRect.height - 2 * edgeOffset);
|
|
17
|
+
};
|
|
18
|
+
export default function useDraggable({ onMove, onDrop, getBoundingRect = () => document.body.getBoundingClientRect(), handleSelector, edgeOffset = 0, }) {
|
|
6
19
|
const startRef = useRef(null);
|
|
7
20
|
const handleRef = useRef(null);
|
|
8
21
|
const targetRef = useRef(null);
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (handleSelector) {
|
|
22
|
-
setTimeout(() => {
|
|
23
|
-
const node = targetRef?.current?.querySelector(handleSelector);
|
|
24
|
-
node && handleRefCallback(node);
|
|
25
|
-
}, 16);
|
|
26
|
-
}
|
|
27
|
-
}, [handleSelector]);
|
|
22
|
+
const onMoveRef = useRef(onMove);
|
|
23
|
+
const onDropRef = useRef(onDrop);
|
|
24
|
+
const getBoundingRectRef = useRef(getBoundingRect);
|
|
25
|
+
const edgeOffsetRef = useRef(edgeOffset);
|
|
26
|
+
onMoveRef.current = onMove;
|
|
27
|
+
onDropRef.current = onDrop;
|
|
28
|
+
getBoundingRectRef.current = getBoundingRect;
|
|
29
|
+
edgeOffsetRef.current = edgeOffset;
|
|
30
|
+
const getEffectiveBoundingRect = () => {
|
|
31
|
+
return applyEdgeOffsetToBoundingRect(getBoundingRectRef.current(), edgeOffsetRef.current);
|
|
32
|
+
};
|
|
28
33
|
const applyTransform = (dx, dy) => {
|
|
29
34
|
if (!targetRef.current)
|
|
30
35
|
return;
|
|
@@ -39,12 +44,19 @@ export default function useDraggable({ onMove, onDrop, getBoundingRect = () => d
|
|
|
39
44
|
dy: clamp(event.pageY - pageY, bounds.top, bounds.bottom),
|
|
40
45
|
};
|
|
41
46
|
};
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
47
|
+
const handleMouseUp = (event) => {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
50
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
51
|
+
const { dx, dy } = getTranslation(event);
|
|
52
|
+
applyTransform(0, 0);
|
|
53
|
+
onDropRef.current?.(dx, dy);
|
|
54
|
+
};
|
|
55
|
+
const handleMouseMove = (event) => {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
const { dx, dy } = getTranslation(event);
|
|
58
|
+
applyTransform(dx, dy);
|
|
59
|
+
onMoveRef.current?.(event);
|
|
48
60
|
};
|
|
49
61
|
const handleMouseDown = (event) => {
|
|
50
62
|
if (!targetRef.current)
|
|
@@ -53,37 +65,48 @@ export default function useDraggable({ onMove, onDrop, getBoundingRect = () => d
|
|
|
53
65
|
document.addEventListener('mouseup', handleMouseUp);
|
|
54
66
|
document.addEventListener('mousemove', handleMouseMove);
|
|
55
67
|
const targetRect = targetRef.current.getBoundingClientRect();
|
|
56
|
-
const boundingRect =
|
|
68
|
+
const boundingRect = getEffectiveBoundingRect();
|
|
57
69
|
startRef.current = {
|
|
58
70
|
pageX: event.pageX,
|
|
59
71
|
pageY: event.pageY,
|
|
60
72
|
bounds: getTranslationBounds(targetRect, boundingRect),
|
|
61
73
|
};
|
|
62
74
|
};
|
|
63
|
-
const handleMouseUp = (event) => {
|
|
64
|
-
event.preventDefault();
|
|
65
|
-
document.removeEventListener('mouseup', handleMouseUp);
|
|
66
|
-
document.removeEventListener('mousemove', handleMouseMove);
|
|
67
|
-
const { dx, dy } = getTranslation(event);
|
|
68
|
-
applyTransform(0, 0);
|
|
69
|
-
onDrop && onDrop(dx, dy);
|
|
70
|
-
};
|
|
71
|
-
const handleMouseMove = (event) => {
|
|
72
|
-
event.preventDefault();
|
|
73
|
-
const { dx, dy } = getTranslation(event);
|
|
74
|
-
applyTransform(dx, dy);
|
|
75
|
-
onMove && onMove(event);
|
|
76
|
-
};
|
|
77
75
|
const boundInitialPosition = () => {
|
|
78
76
|
if (!targetRef.current)
|
|
79
77
|
return;
|
|
80
78
|
const targetRect = targetRef.current.getBoundingClientRect();
|
|
81
|
-
const boundingRect =
|
|
79
|
+
const boundingRect = getEffectiveBoundingRect();
|
|
82
80
|
const bounds = getTranslationBounds(targetRect, boundingRect);
|
|
83
81
|
const dx = clamp(0, bounds.left, bounds.right);
|
|
84
82
|
const dy = clamp(0, bounds.top, bounds.bottom);
|
|
85
|
-
if (
|
|
86
|
-
|
|
83
|
+
if (onDropRef.current && (dx !== 0 || dy !== 0)) {
|
|
84
|
+
onDropRef.current(dx, dy);
|
|
85
|
+
}
|
|
87
86
|
};
|
|
87
|
+
const handleMouseDownRef = useRef(handleMouseDown);
|
|
88
|
+
handleMouseDownRef.current = handleMouseDown;
|
|
89
|
+
const stableHandleMouseDown = useCallback((event) => {
|
|
90
|
+
handleMouseDownRef.current(event);
|
|
91
|
+
}, []);
|
|
92
|
+
const handleRefCallback = useCallback((newNode) => {
|
|
93
|
+
const oldNode = handleRef.current;
|
|
94
|
+
if (oldNode) {
|
|
95
|
+
oldNode.removeEventListener('mousedown', stableHandleMouseDown);
|
|
96
|
+
}
|
|
97
|
+
if (newNode) {
|
|
98
|
+
newNode.addEventListener('mousedown', stableHandleMouseDown);
|
|
99
|
+
boundInitialPosition();
|
|
100
|
+
}
|
|
101
|
+
handleRef.current = newNode;
|
|
102
|
+
}, [stableHandleMouseDown]);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (handleSelector) {
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
const node = targetRef?.current?.querySelector(handleSelector);
|
|
107
|
+
node && handleRefCallback(node);
|
|
108
|
+
}, 16);
|
|
109
|
+
}
|
|
110
|
+
}, [handleSelector, handleRefCallback]);
|
|
88
111
|
return { handleRef: handleRefCallback, targetRef, applyTransform };
|
|
89
112
|
}
|
package/src/env.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
|
|
3
|
-
PUBLISH_TIMESTAMP:
|
|
4
|
-
VERSION: "23.0.
|
|
3
|
+
PUBLISH_TIMESTAMP: 1784037600986 || Date.now(),
|
|
4
|
+
VERSION: "23.0.11" || '--current-version--',
|
|
5
5
|
};
|