impact-ui 4.0.12 → 4.0.13

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.
Files changed (45) hide show
  1. package/dist/_virtual/index13.js +2 -2
  2. package/dist/_virtual/index14.js +2 -2
  3. package/dist/_virtual/index15.js +2 -2
  4. package/dist/_virtual/index16.js +2 -2
  5. package/dist/_virtual/index3.js +2 -4
  6. package/dist/_virtual/index4.js +3 -3
  7. package/dist/_virtual/index5.js +4 -2
  8. package/dist/components/Chatbot/Chatbot.types.d.ts +12 -1
  9. package/dist/components/Chatbot/Chatbot.types.d.ts.map +1 -1
  10. package/dist/components/Chatbot/chatInput.d.ts.map +1 -1
  11. package/dist/components/Chatbot/chatInput.js +22 -4
  12. package/dist/components/Chatbot/chatbotModuleMenu.d.ts +1 -1
  13. package/dist/components/Chatbot/chatbotModuleMenu.d.ts.map +1 -1
  14. package/dist/components/Chatbot/chatbotModuleMenu.js +162 -186
  15. package/dist/components/Chatbot/conversationScreen.d.ts +1 -1
  16. package/dist/components/Chatbot/conversationScreen.d.ts.map +1 -1
  17. package/dist/components/Chatbot/conversationScreen.js +7 -3
  18. package/dist/components/Chatbot/customScreen.d.ts +1 -1
  19. package/dist/components/Chatbot/customScreen.d.ts.map +1 -1
  20. package/dist/components/Chatbot/customScreen.js +26 -25
  21. package/dist/components/Chatbot/index.d.ts.map +1 -1
  22. package/dist/components/Chatbot/index.js +330 -240
  23. package/dist/components/Chatbot/newChatComponent.d.ts +1 -1
  24. package/dist/components/Chatbot/newChatComponent.d.ts.map +1 -1
  25. package/dist/components/Chatbot/newChatComponent.js +5 -2
  26. package/dist/components/Table/index.js +1 -1
  27. package/dist/components/TableOld/index.js +1 -1
  28. package/dist/hooks/useDraggableResizable.d.ts +104 -0
  29. package/dist/hooks/useDraggableResizable.d.ts.map +1 -0
  30. package/dist/hooks/useDraggableResizable.js +323 -0
  31. package/dist/hooks/useMediaQuery.d.ts +9 -0
  32. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  33. package/dist/mcp-component-registry.json +1 -1
  34. package/dist/node_modules/@mui/system/colorManipulator.js +2 -2
  35. package/dist/node_modules/call-bind/index.js +1 -1
  36. package/dist/node_modules/hoist-non-react-statics/node_modules/react-is/index.js +1 -1
  37. package/dist/node_modules/is-symbol/index.js +1 -1
  38. package/dist/node_modules/react-is/index.js +1 -1
  39. package/dist/node_modules/react-with-styles-interface-css/dist/index.js +1 -1
  40. package/dist/utils/index.d.ts +1 -0
  41. package/dist/utils/index.d.ts.map +1 -1
  42. package/dist/utils/onResize.d.ts +24 -0
  43. package/dist/utils/onResize.d.ts.map +1 -0
  44. package/dist/utils/onResize.js +28 -0
  45. package/package.json +1 -1
@@ -0,0 +1,104 @@
1
+ import { KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';
2
+
3
+ export interface Rect {
4
+ x: number;
5
+ y: number;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export type ResizeDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
10
+ export declare const BOTTOM_VIEWPORT_MARGIN = 24;
11
+ export interface ViewportMargin {
12
+ top: number;
13
+ right: number;
14
+ bottom: number;
15
+ left: number;
16
+ }
17
+ /** Accepts a single number (all sides) or per-side overrides. */
18
+ export type ViewportMarginInput = number | Partial<ViewportMargin>;
19
+ export interface UseDraggableResizableOptions {
20
+ /** Starting position/size. Only read once on mount (use `setRect`/`collapseTo` to change later). */
21
+ initialRect: Rect;
22
+ minWidth?: number;
23
+ minHeight?: number;
24
+ maxWidth?: number;
25
+ maxHeight?: number;
26
+ /**
27
+ * Gap kept clear between the panel and the viewport edges while dragging/resizing, so it
28
+ * stops short of the edge instead of touching it. Pass a number for a uniform margin, or
29
+ * per-side values (e.g. `{ top: 56, bottom: 24 }` to also clear a fixed app header).
30
+ * Pass `0` for docked panels that should sit flush with the viewport.
31
+ * @default 0
32
+ */
33
+ viewportMargin?: ViewportMarginInput;
34
+ /** Disables both dragging and resizing (e.g. while in a "full width" mode). */
35
+ disabled?: boolean;
36
+ onChange?: (rect: Rect) => void;
37
+ onDragEnd?: (rect: Rect) => void;
38
+ onResizeEnd?: (rect: Rect) => void;
39
+ }
40
+ export interface HandleProps {
41
+ onPointerDown: (e: ReactPointerEvent) => void;
42
+ onKeyDown: (e: ReactKeyboardEvent) => void;
43
+ }
44
+ /** Viewport corner the collapsed panel is pinned to. */
45
+ export type CollapseAnchor = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
46
+ export interface CollapseOptions {
47
+ /** @default 'bottom-right' */
48
+ anchor?: CollapseAnchor;
49
+ /**
50
+ * Margin to inset the collapsed panel from the viewport edges. Pass this when the margin
51
+ * changes in the same event that triggers the collapse - the `viewportMargin` *prop* is
52
+ * still the pre-update value at that point (React batches state), so relying on it would
53
+ * anchor against the wrong gap.
54
+ */
55
+ viewportMargin?: ViewportMarginInput;
56
+ }
57
+ export interface UseDraggableResizableResult {
58
+ rect: Rect;
59
+ isDragging: boolean;
60
+ isResizing: boolean;
61
+ isCollapsed: boolean;
62
+ setRect: (updater: Rect | ((prev: Rect) => Rect)) => void;
63
+ /** Spread onto the element that should act as the "title bar" drag handle. */
64
+ dragHandleProps: HandleProps;
65
+ /** Spread onto one of the 8 resize handle elements. */
66
+ getResizeHandleProps: (direction: ResizeDirection) => HandleProps & {
67
+ role: 'separator';
68
+ tabIndex: 0;
69
+ 'aria-orientation': 'horizontal' | 'vertical';
70
+ };
71
+ /**
72
+ * Shrink to a fixed compact size pinned to a viewport corner (default: bottom-right),
73
+ * remembering the current rect so `restore()` can bring it back.
74
+ */
75
+ collapseTo: (size: {
76
+ width: number;
77
+ height: number;
78
+ }, options?: CollapseOptions) => void;
79
+ /** Restore the rect that was active before the last `collapseTo` call. */
80
+ restore: () => void;
81
+ }
82
+ /**
83
+ * Headless drag + 8-direction resize behavior for a floating panel (think: Google Meet's
84
+ * pop-out mini window). Framework-agnostic logic lives here so any component (chatbot,
85
+ * modal, side panel, etc.) can opt in just by spreading `dragHandleProps` /
86
+ * `getResizeHandleProps(direction)` onto its own markup.
87
+ *
88
+ * Implementation notes (see chat discussion for rationale):
89
+ * - Uses Pointer Events + `setPointerCapture` (works for mouse, touch, and pen) instead of
90
+ * plain `mousedown`/`mousemove`, and keeps receiving events on the same element even if the
91
+ * pointer moves faster than layout, so there is no need for `document`-level listeners.
92
+ * - Batches state updates via `requestAnimationFrame` so dragging/resizing doesn't trigger a
93
+ * React re-render on every single pixel of pointer movement.
94
+ * - Clamps the rect to the viewport (recomputed on every move, not just drag-start) so the
95
+ * panel can never be dragged/resized off-screen on any edge, and always keeps a small margin
96
+ * clear at the bottom of the viewport.
97
+ * - Toggles a `no-select`/`col-resize`-style class on `<body>` while interacting, and always
98
+ * cleans up listeners + that class on `pointerup`/`pointercancel` and on unmount, even if the
99
+ * consumer unmounts mid-drag.
100
+ * - Resize handles expose `role="separator"` + keyboard nudging (arrow keys, Shift for a
101
+ * larger step) for accessibility.
102
+ */
103
+ export declare function useDraggableResizable({ initialRect, minWidth, minHeight, maxWidth, maxHeight, viewportMargin, disabled, onChange, onDragEnd, onResizeEnd, }: UseDraggableResizableOptions): UseDraggableResizableResult;
104
+ //# sourceMappingURL=useDraggableResizable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDraggableResizable.d.ts","sourceRoot":"","sources":["../../src/hooks/useDraggableResizable.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,323 @@
1
+ import { useState, useRef, useCallback, useEffect } from "react";
2
+ const RESIZE_STEP = 8;
3
+ const RESIZE_STEP_LARGE = 32;
4
+ const BOTTOM_VIEWPORT_MARGIN = 24;
5
+ function resolveViewportMargin(input) {
6
+ if (typeof input === "number") {
7
+ return { top: input, right: input, bottom: input, left: input };
8
+ }
9
+ return {
10
+ top: (input == null ? void 0 : input.top) ?? 0,
11
+ right: (input == null ? void 0 : input.right) ?? 0,
12
+ bottom: (input == null ? void 0 : input.bottom) ?? 0,
13
+ left: (input == null ? void 0 : input.left) ?? 0
14
+ };
15
+ }
16
+ function clampNumber(value, min, max) {
17
+ return Math.min(Math.max(value, min), Math.max(min, max));
18
+ }
19
+ function safeCapturePointer(target, pointerId) {
20
+ if (typeof target.setPointerCapture !== "function") return;
21
+ try {
22
+ target.setPointerCapture(pointerId);
23
+ } catch {
24
+ }
25
+ }
26
+ function safeReleasePointer(target, pointerId) {
27
+ if (typeof target.releasePointerCapture !== "function") return;
28
+ try {
29
+ target.releasePointerCapture(pointerId);
30
+ } catch {
31
+ }
32
+ }
33
+ function clampRect(rect, opts) {
34
+ const viewportWidth = typeof window !== "undefined" ? window.innerWidth : Infinity;
35
+ const viewportHeight = typeof window !== "undefined" ? window.innerHeight : Infinity;
36
+ const { margin } = opts;
37
+ const boundsWidth = viewportWidth - margin.left - margin.right;
38
+ const boundsHeight = viewportHeight - margin.top - margin.bottom;
39
+ const width = clampNumber(rect.width, opts.minWidth, Math.min(opts.maxWidth, boundsWidth));
40
+ const height = clampNumber(rect.height, opts.minHeight, Math.min(opts.maxHeight, boundsHeight));
41
+ const x = clampNumber(
42
+ rect.x,
43
+ margin.left,
44
+ Math.max(margin.left, viewportWidth - margin.right - width)
45
+ );
46
+ const y = clampNumber(
47
+ rect.y,
48
+ margin.top,
49
+ Math.max(margin.top, viewportHeight - margin.bottom - height)
50
+ );
51
+ return { x, y, width, height };
52
+ }
53
+ function useDraggableResizable({
54
+ initialRect,
55
+ minWidth = 320,
56
+ minHeight = 320,
57
+ maxWidth = Infinity,
58
+ maxHeight = Infinity,
59
+ viewportMargin,
60
+ disabled = false,
61
+ onChange,
62
+ onDragEnd,
63
+ onResizeEnd
64
+ }) {
65
+ const [rect, setRectState] = useState(initialRect);
66
+ const [isDragging, setIsDragging] = useState(false);
67
+ const [isResizing, setIsResizing] = useState(false);
68
+ const [isCollapsed, setIsCollapsed] = useState(false);
69
+ const rectRef = useRef(rect);
70
+ rectRef.current = rect;
71
+ const savedRectRef = useRef(null);
72
+ const rafRef = useRef(null);
73
+ const pendingRectRef = useRef(null);
74
+ const cleanupRef = useRef(null);
75
+ const margin = resolveViewportMargin(viewportMargin);
76
+ const limits = { minWidth, minHeight, maxWidth, maxHeight, margin };
77
+ const { top: marginTop, right: marginRight, bottom: marginBottom, left: marginLeft } = margin;
78
+ const commitRect = useCallback(
79
+ (next) => {
80
+ const clamped = clampRect(next, limits);
81
+ pendingRectRef.current = clamped;
82
+ if (rafRef.current == null) {
83
+ rafRef.current = requestAnimationFrame(() => {
84
+ rafRef.current = null;
85
+ if (pendingRectRef.current) {
86
+ setRectState(pendingRectRef.current);
87
+ onChange == null ? void 0 : onChange(pendingRectRef.current);
88
+ }
89
+ });
90
+ }
91
+ },
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ [
94
+ minWidth,
95
+ minHeight,
96
+ maxWidth,
97
+ maxHeight,
98
+ marginTop,
99
+ marginRight,
100
+ marginBottom,
101
+ marginLeft,
102
+ onChange
103
+ ]
104
+ );
105
+ const setRect = useCallback(
106
+ (updater) => {
107
+ const next = typeof updater === "function" ? updater(rectRef.current) : updater;
108
+ const clamped = clampRect(next, limits);
109
+ rectRef.current = clamped;
110
+ setRectState(clamped);
111
+ onChange == null ? void 0 : onChange(clamped);
112
+ },
113
+ // eslint-disable-next-line react-hooks/exhaustive-deps
114
+ [
115
+ minWidth,
116
+ minHeight,
117
+ maxWidth,
118
+ maxHeight,
119
+ marginTop,
120
+ marginRight,
121
+ marginBottom,
122
+ marginLeft,
123
+ onChange
124
+ ]
125
+ );
126
+ const endInteraction = useCallback(() => {
127
+ document.body.classList.remove("no-select");
128
+ const cleanup = cleanupRef.current;
129
+ cleanupRef.current = null;
130
+ cleanup == null ? void 0 : cleanup();
131
+ if (rafRef.current != null) {
132
+ cancelAnimationFrame(rafRef.current);
133
+ rafRef.current = null;
134
+ }
135
+ if (pendingRectRef.current) {
136
+ setRectState(pendingRectRef.current);
137
+ onChange == null ? void 0 : onChange(pendingRectRef.current);
138
+ }
139
+ }, [onChange]);
140
+ useEffect(
141
+ () => () => {
142
+ var _a;
143
+ document.body.classList.remove("no-select");
144
+ (_a = cleanupRef.current) == null ? void 0 : _a.call(cleanupRef);
145
+ if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
146
+ },
147
+ []
148
+ );
149
+ const startDrag = useCallback(
150
+ (e) => {
151
+ if (disabled) return;
152
+ const target = e.currentTarget;
153
+ const pointerId = e.pointerId;
154
+ const startX = e.clientX;
155
+ const startY = e.clientY;
156
+ const startRect = rectRef.current;
157
+ safeCapturePointer(target, pointerId);
158
+ document.body.classList.add("no-select");
159
+ setIsDragging(true);
160
+ const onMove = (ev) => {
161
+ const dx = ev.clientX - startX;
162
+ const dy = ev.clientY - startY;
163
+ commitRect({ ...startRect, x: startRect.x - 24 + dx, y: startRect.y - 24 + dy });
164
+ };
165
+ const onUp = () => {
166
+ safeReleasePointer(target, pointerId);
167
+ target.removeEventListener("pointermove", onMove);
168
+ target.removeEventListener("pointerup", onUp);
169
+ target.removeEventListener("pointercancel", onUp);
170
+ setIsDragging(false);
171
+ endInteraction();
172
+ onDragEnd == null ? void 0 : onDragEnd(rectRef.current);
173
+ };
174
+ target.addEventListener("pointermove", onMove);
175
+ target.addEventListener("pointerup", onUp);
176
+ target.addEventListener("pointercancel", onUp);
177
+ cleanupRef.current = onUp;
178
+ },
179
+ [disabled, commitRect, endInteraction, onDragEnd]
180
+ );
181
+ const startResize = useCallback(
182
+ (direction) => (e) => {
183
+ if (disabled) return;
184
+ e.stopPropagation();
185
+ const target = e.currentTarget;
186
+ const pointerId = e.pointerId;
187
+ const startX = e.clientX;
188
+ const startY = e.clientY;
189
+ const startRect = rectRef.current;
190
+ safeCapturePointer(target, pointerId);
191
+ document.body.classList.add("no-select");
192
+ setIsResizing(true);
193
+ const onMove = (ev) => {
194
+ const dx = ev.clientX - startX;
195
+ const dy = ev.clientY - startY;
196
+ let { x, y, width, height } = startRect;
197
+ if (direction.includes("e")) width = startRect.width + dx;
198
+ if (direction.includes("s")) height = startRect.height + dy;
199
+ if (direction.includes("w")) {
200
+ width = startRect.width - dx;
201
+ x = startRect.x + dx;
202
+ }
203
+ if (direction.includes("n")) {
204
+ height = startRect.height - dy;
205
+ y = startRect.y + dy;
206
+ }
207
+ commitRect({ x, y, width, height });
208
+ };
209
+ const onUp = () => {
210
+ safeReleasePointer(target, pointerId);
211
+ target.removeEventListener("pointermove", onMove);
212
+ target.removeEventListener("pointerup", onUp);
213
+ target.removeEventListener("pointercancel", onUp);
214
+ setIsResizing(false);
215
+ endInteraction();
216
+ onResizeEnd == null ? void 0 : onResizeEnd(rectRef.current);
217
+ };
218
+ target.addEventListener("pointermove", onMove);
219
+ target.addEventListener("pointerup", onUp);
220
+ target.addEventListener("pointercancel", onUp);
221
+ cleanupRef.current = onUp;
222
+ },
223
+ [disabled, commitRect, endInteraction, onResizeEnd]
224
+ );
225
+ const handleResizeKeyDown = useCallback(
226
+ (direction) => (e) => {
227
+ if (disabled) return;
228
+ const step = e.shiftKey ? RESIZE_STEP_LARGE : RESIZE_STEP;
229
+ let dx = 0;
230
+ let dy = 0;
231
+ if (e.key === "ArrowLeft") dx = -step;
232
+ else if (e.key === "ArrowRight") dx = step;
233
+ else if (e.key === "ArrowUp") dy = -step;
234
+ else if (e.key === "ArrowDown") dy = step;
235
+ else return;
236
+ e.preventDefault();
237
+ const startRect = rectRef.current;
238
+ let { x, y, width, height } = startRect;
239
+ if (direction.includes("e")) width += dx;
240
+ if (direction.includes("s")) height += dy;
241
+ if (direction.includes("w")) {
242
+ width -= dx;
243
+ x += dx;
244
+ }
245
+ if (direction.includes("n")) {
246
+ height -= dy;
247
+ y += dy;
248
+ }
249
+ setRect({ x, y, width, height });
250
+ onResizeEnd == null ? void 0 : onResizeEnd(rectRef.current);
251
+ },
252
+ [disabled, setRect, onResizeEnd]
253
+ );
254
+ const dragHandleProps = {
255
+ onPointerDown: startDrag,
256
+ onKeyDown: (e) => {
257
+ if (disabled) return;
258
+ const step = e.shiftKey ? RESIZE_STEP_LARGE : RESIZE_STEP;
259
+ let dx = 0;
260
+ let dy = 0;
261
+ if (e.key === "ArrowLeft") dx = -step;
262
+ else if (e.key === "ArrowRight") dx = step;
263
+ else if (e.key === "ArrowUp") dy = -step;
264
+ else if (e.key === "ArrowDown") dy = step;
265
+ else return;
266
+ e.preventDefault();
267
+ setRect((prev) => ({ ...prev, x: prev.x + dx, y: prev.y + dy }));
268
+ }
269
+ };
270
+ const getResizeHandleProps = useCallback(
271
+ (direction) => ({
272
+ onPointerDown: startResize(direction),
273
+ onKeyDown: handleResizeKeyDown(direction),
274
+ role: "separator",
275
+ tabIndex: 0,
276
+ "aria-orientation": direction === "n" || direction === "s" ? "horizontal" : "vertical"
277
+ }),
278
+ [startResize, handleResizeKeyDown]
279
+ );
280
+ const collapseTo = useCallback(
281
+ (size, options) => {
282
+ savedRectRef.current = rectRef.current;
283
+ setIsCollapsed(true);
284
+ const m = (options == null ? void 0 : options.viewportMargin) === void 0 ? { top: marginTop, right: marginRight, bottom: marginBottom, left: marginLeft } : resolveViewportMargin(options.viewportMargin);
285
+ const viewportWidth = typeof window !== "undefined" ? window.innerWidth : size.width;
286
+ const viewportHeight = typeof window !== "undefined" ? window.innerHeight : size.height;
287
+ const anchor = (options == null ? void 0 : options.anchor) ?? "bottom-right";
288
+ const x = anchor.endsWith("right") ? viewportWidth - size.width - m.right : m.left;
289
+ const y = anchor.startsWith("bottom") ? viewportHeight - size.height - m.bottom : m.top;
290
+ const clamped = clampRect(
291
+ { x, y, width: size.width, height: size.height },
292
+ { minWidth: size.width, minHeight: size.height, maxWidth, maxHeight, margin: m }
293
+ );
294
+ rectRef.current = clamped;
295
+ setRectState(clamped);
296
+ onChange == null ? void 0 : onChange(clamped);
297
+ },
298
+ // eslint-disable-next-line react-hooks/exhaustive-deps
299
+ [maxWidth, maxHeight, marginTop, marginRight, marginBottom, marginLeft, onChange]
300
+ );
301
+ const restore = useCallback(() => {
302
+ if (savedRectRef.current) {
303
+ setRect(savedRectRef.current);
304
+ savedRectRef.current = null;
305
+ }
306
+ setIsCollapsed(false);
307
+ }, [setRect]);
308
+ return {
309
+ rect,
310
+ isDragging,
311
+ isResizing,
312
+ isCollapsed,
313
+ setRect,
314
+ dragHandleProps,
315
+ getResizeHandleProps,
316
+ collapseTo,
317
+ restore
318
+ };
319
+ }
320
+ export {
321
+ BOTTOM_VIEWPORT_MARGIN,
322
+ useDraggableResizable
323
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Subscribes to a CSS media query via `window.matchMedia` and returns whether it currently
3
+ * matches. Re-renders when the match state changes (e.g. the viewport crosses the threshold).
4
+ *
5
+ * @param query - A valid CSS media query string, e.g. `'(max-width: 768px)'`.
6
+ * @param defaultMatches - Value returned during SSR / before `window` is available. Defaults to `false`.
7
+ */
8
+ export declare function useMediaQuery(query: string, defaultMatches?: boolean): boolean;
9
+ //# sourceMappingURL=useMediaQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMediaQuery.d.ts","sourceRoot":"","sources":["../../src/hooks/useMediaQuery.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,UAAQ,GAAG,OAAO,CA+B5E"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generatedAt": "2026-09-07T14:26:01.055Z",
3
+ "generatedAt": "2026-09-08T12:21:32.564Z",
4
4
  "components": {
5
5
  "Menu": {
6
6
  "title": "Components/Menu",
@@ -1,7 +1,7 @@
1
1
  import { __exports as colorManipulator } from "../../../_virtual/colorManipulator.js";
2
2
  import require$$0 from "@babel/runtime/helpers/interopRequireDefault";
3
- import require$$1 from "../../../_virtual/index3.js";
4
- import require$$2 from "../../../_virtual/index4.js";
3
+ import require$$1 from "../../../_virtual/index4.js";
4
+ import require$$2 from "../../../_virtual/index5.js";
5
5
  var _interopRequireDefault = require$$0;
6
6
  Object.defineProperty(colorManipulator, "__esModule", {
7
7
  value: true
@@ -1,4 +1,4 @@
1
- import { __module as callBind } from "../../_virtual/index14.js";
1
+ import { __module as callBind } from "../../_virtual/index15.js";
2
2
  import { __require as requireSetFunctionLength } from "../set-function-length/index.js";
3
3
  import { __require as requireEsDefineProperty } from "../es-define-property/index.js";
4
4
  import { __require as requireCallBindApplyHelpers } from "../call-bind-apply-helpers/index.js";
@@ -1,4 +1,4 @@
1
- import { __module as reactIs } from "../../../../_virtual/index16.js";
1
+ import { __module as reactIs } from "../../../../_virtual/index13.js";
2
2
  import { __require as requireReactIs_production_min } from "./cjs/react-is.production.min.js";
3
3
  import { __require as requireReactIs_development } from "./cjs/react-is.development.js";
4
4
  if (process.env.NODE_ENV === "production") {
@@ -1,4 +1,4 @@
1
- import { __module as isSymbol } from "../../_virtual/index15.js";
1
+ import { __module as isSymbol } from "../../_virtual/index16.js";
2
2
  import { __require as requireCallBound } from "../call-bound/index.js";
3
3
  import { __require as requireHasSymbols } from "../has-symbols/index.js";
4
4
  import { __require as requireSafeRegexTest } from "../safe-regex-test/index.js";
@@ -1,4 +1,4 @@
1
- import { __module as reactIs } from "../../_virtual/index5.js";
1
+ import { __module as reactIs } from "../../_virtual/index3.js";
2
2
  import { __require as requireReactIs_production } from "./cjs/react-is.production.js";
3
3
  import { __require as requireReactIs_development } from "./cjs/react-is.development.js";
4
4
  if (process.env.NODE_ENV === "production") {
@@ -1,4 +1,4 @@
1
- import { __exports as dist } from "../../../_virtual/index13.js";
1
+ import { __exports as dist } from "../../../_virtual/index14.js";
2
2
  import require$$0 from "@babel/runtime/helpers/interopRequireDefault";
3
3
  import { __require as requireArray_prototype_flat } from "../../array.prototype.flat/index.js";
4
4
  import { __require as requireGlobalCache } from "../../global-cache/index.js";
@@ -10,6 +10,7 @@
10
10
  */
11
11
  export { getUserAvatarColor, DEFAULT_AVATAR_COLORS } from './avatarColor';
12
12
  export { debounce } from './debounce';
13
+ export { getSize, onResize, type ElementSize } from './onResize';
13
14
  export { toInnerHTML, type InnerHTML } from './html';
14
15
  export { TEXT_FILTER_OPTIONS, NON_TEXT_FILTER_OPTIONS, DATE_FILTER_OPTIONS, getTextFilterOptions, getNonTextFilterOptions, getDateFilterOptions, convertToOptions, getAllowedColumns, hasDuplicateColumns, isColumnSelectionDuplicate, isViewNameUnique, toSentenceCase, type FilterOption, type ColumnOption, type ColumnDefinition, type FormFilter, type FormValues, type FilterField, type SavedView, } from './helper';
15
16
  export { useTextOverflow } from './useTextOverflow';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,EAChB,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,GACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAGjE,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,EAChB,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,GACf,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Thin ResizeObserver helper for watching an element's size.
3
+ * Prefer this over viewport breakpoints when the thing that changes
4
+ * size is a specific div (e.g. the resizable chatbot panel).
5
+ */
6
+ export interface ElementSize {
7
+ width: number;
8
+ height: number;
9
+ }
10
+ /** Current width/height of an element. */
11
+ export declare function getSize(el: Element): ElementSize;
12
+ /**
13
+ * Watch an element with ResizeObserver.
14
+ * Fires immediately with the current size, then on every resize.
15
+ * Returns an unsubscribe function.
16
+ *
17
+ * @example
18
+ * const stop = onResize(panelEl, ({ width, height }) => {
19
+ * console.log(width, height);
20
+ * });
21
+ * // later: stop();
22
+ */
23
+ export declare function onResize(el: Element, callback: (size: ElementSize) => void): () => void;
24
+ //# sourceMappingURL=onResize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onResize.d.ts","sourceRoot":"","sources":["../../src/utils/onResize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0CAA0C;AAC1C,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,WAAW,CAGhD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAyBvF"}
@@ -0,0 +1,28 @@
1
+ function getSize(el) {
2
+ const { width, height } = el.getBoundingClientRect();
3
+ return { width, height };
4
+ }
5
+ function onResize(el, callback) {
6
+ if (typeof ResizeObserver === "undefined") {
7
+ callback(getSize(el));
8
+ return () => {
9
+ };
10
+ }
11
+ const observer = new ResizeObserver((entries) => {
12
+ const entry = entries[0];
13
+ if (!entry) return;
14
+ const box = entry.borderBoxSize[0];
15
+ callback(
16
+ box ? { width: box.inlineSize, height: box.blockSize } : { width: entry.contentRect.width, height: entry.contentRect.height }
17
+ );
18
+ });
19
+ observer.observe(el);
20
+ callback(getSize(el));
21
+ return () => {
22
+ observer.disconnect();
23
+ };
24
+ }
25
+ export {
26
+ getSize,
27
+ onResize
28
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impact-ui",
3
- "version": "4.0.12",
3
+ "version": "4.0.13",
4
4
  "description": "Impact Analytics UI library",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",