cx 26.8.0 → 26.9.1
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/build/charts/Legend.d.ts +8 -1
- package/build/charts/Legend.d.ts.map +1 -1
- package/build/charts/Legend.js +8 -4
- package/build/data/index.d.ts +1 -0
- package/build/data/index.d.ts.map +1 -1
- package/build/data/index.js +1 -0
- package/build/jsx-dev-runtime.d.ts +2 -1
- package/build/jsx-dev-runtime.d.ts.map +1 -1
- package/build/svg/Svg.d.ts +9 -0
- package/build/svg/Svg.d.ts.map +1 -1
- package/build/svg/Svg.js +9 -1
- package/build/ui/index.d.ts +3 -2
- package/build/ui/index.d.ts.map +1 -1
- package/build/ui/index.js +1 -1
- package/build/util/DOM.d.ts.map +1 -1
- package/build/util/DOM.js +16 -4
- package/build/util/getActiveElement.d.ts +1 -1
- package/build/util/getActiveElement.d.ts.map +1 -1
- package/build/util/getActiveElement.js +14 -2
- package/build/widgets/form/TextArea.d.ts +4 -0
- package/build/widgets/form/TextArea.d.ts.map +1 -1
- package/build/widgets/form/TextArea.js +7 -1
- package/build/widgets/grid/Grid.d.ts +3 -2
- package/build/widgets/grid/Grid.d.ts.map +1 -1
- package/build/widgets/nav/MenuItem.js +2 -2
- package/build/widgets/overlay/Dropdown.d.ts +4 -4
- package/build/widgets/overlay/Dropdown.d.ts.map +1 -1
- package/build/widgets/overlay/Dropdown.js +82 -38
- package/build/widgets/overlay/Overlay.d.ts.map +1 -1
- package/build/widgets/overlay/Overlay.js +7 -3
- package/build/widgets/overlay/Window.d.ts.map +1 -1
- package/build/widgets/overlay/Window.js +2 -1
- package/dist/charts.js +10 -3
- package/dist/data.js +1 -0
- package/dist/manifest.js +869 -869
- package/dist/svg.js +13 -0
- package/dist/util.js +31 -9
- package/dist/widgets.js +139 -47
- package/package.json +1 -1
- package/src/charts/Legend.tsx +22 -2
- package/src/data/index.ts +31 -30
- package/src/jsx-dev-runtime.ts +2 -1
- package/src/svg/Svg.tsx +24 -1
- package/src/ui/index.ts +3 -6
- package/src/util/DOM.ts +15 -4
- package/src/util/getActiveElement.ts +16 -2
- package/src/widgets/form/TextArea.tsx +10 -1
- package/src/widgets/grid/Grid.tsx +3 -2
- package/src/widgets/nav/MenuItem.tsx +2 -2
- package/src/widgets/overlay/Dropdown.tsx +87 -27
- package/src/widgets/overlay/Overlay.tsx +5 -3
- package/src/widgets/overlay/Window.tsx +2 -1
package/src/svg/Svg.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
|
+
import { StringProp } from "../ui/Prop";
|
|
2
3
|
import { RenderingContext } from "../ui/RenderingContext";
|
|
3
4
|
import { ResizeManager } from "../ui/ResizeManager";
|
|
4
5
|
import { VDOM, Widget } from "../ui/Widget";
|
|
@@ -18,6 +19,15 @@ interface SvgInstance extends BoundedObjectInstance {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface SvgConfig extends BoundedObjectConfig {
|
|
22
|
+
/** ARIA role for the `svg` element. Defaults to `img` when `ariaLabel` is set. */
|
|
23
|
+
role?: StringProp;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Accessible name for the `svg` element. Setting it announces the drawing as a single graphic
|
|
27
|
+
* instead of as its individual shapes, which is also how a tagged PDF export tags it.
|
|
28
|
+
*/
|
|
29
|
+
ariaLabel?: StringProp;
|
|
30
|
+
|
|
21
31
|
/** Set to `true` to automatically calculate width based on the measured height and `aspectRatio`. */
|
|
22
32
|
autoWidth?: boolean;
|
|
23
33
|
|
|
@@ -53,6 +63,16 @@ export class Svg extends BoundedObject<SvgConfig, SvgInstance> {
|
|
|
53
63
|
super(config);
|
|
54
64
|
}
|
|
55
65
|
|
|
66
|
+
declareData(...args: any[]) {
|
|
67
|
+
return super.declareData(
|
|
68
|
+
{
|
|
69
|
+
role: undefined,
|
|
70
|
+
ariaLabel: undefined,
|
|
71
|
+
},
|
|
72
|
+
...args,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
56
76
|
initState(context: RenderingContext, instance: SvgInstance) {
|
|
57
77
|
const size = {
|
|
58
78
|
width: 0,
|
|
@@ -147,6 +167,9 @@ class SvgComponent extends VDOM.Component<SvgComponentProps> {
|
|
|
147
167
|
const { instance, data, size, children, eventHandlers } = this.props;
|
|
148
168
|
const { widget } = instance;
|
|
149
169
|
|
|
170
|
+
// An unnamed drawing is left alone: `role="img"` would hide its text and put nothing in its place.
|
|
171
|
+
const role = data.role ?? (data.ariaLabel ? "img" : undefined);
|
|
172
|
+
|
|
150
173
|
const defs: any[] = [];
|
|
151
174
|
for (const k in (instance as any).clipRects) {
|
|
152
175
|
let cr = (instance as any).clipRects[k];
|
|
@@ -181,7 +204,7 @@ class SvgComponent extends VDOM.Component<SvgComponentProps> {
|
|
|
181
204
|
{...eventHandlers}
|
|
182
205
|
>
|
|
183
206
|
{size.width > 0 && size.height > 0 && (
|
|
184
|
-
<svg>
|
|
207
|
+
<svg role={role} aria-label={data.ariaLabel}>
|
|
185
208
|
<defs>{defs}</defs>
|
|
186
209
|
{children}
|
|
187
210
|
</svg>
|
package/src/ui/index.ts
CHANGED
|
@@ -43,9 +43,6 @@ export * from "./exprHelpers";
|
|
|
43
43
|
|
|
44
44
|
//re-export computable here
|
|
45
45
|
import { computable } from "../data/computable";
|
|
46
|
-
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
AccessorChain,
|
|
50
|
-
} from "../data/createAccessorModelProxy";
|
|
51
|
-
export { computable, createAccessorModelProxy, createModel, AccessorChain };
|
|
46
|
+
import { createAccessorModelProxy, createModel } from "../data/createAccessorModelProxy";
|
|
47
|
+
export { computable, createAccessorModelProxy, createModel };
|
|
48
|
+
export type { AccessorChain } from "../data/createAccessorModelProxy";
|
package/src/util/DOM.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isNumber } from "../util/isNumber";
|
|
2
|
+
import { getActiveElement } from "./getActiveElement";
|
|
2
3
|
|
|
3
4
|
type ElementFilter = (el: Element, condition: (el: Element) => boolean) => Element | null;
|
|
4
5
|
|
|
@@ -51,11 +52,11 @@ export function closestParent(el: Element, condition: (el: any) => boolean): HTM
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export function isFocused(el: Element): boolean {
|
|
54
|
-
return
|
|
55
|
+
return getActiveElement() == el;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function isFocusedDeep(el: Element): boolean {
|
|
58
|
-
return
|
|
59
|
+
return isSelfOrDescendant(el, getActiveElement());
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
const focusableWithoutTabIndex = ["INPUT", "SELECT", "TEXTAREA", "A", "BUTTON"];
|
|
@@ -76,13 +77,23 @@ export function isFocusable(el: Element): el is HTMLElement {
|
|
|
76
77
|
* @returns {Element}
|
|
77
78
|
*/
|
|
78
79
|
export function getFocusedElement(): Element | null {
|
|
79
|
-
return
|
|
80
|
+
return getActiveElement();
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
export function isDescendant(el: Element, descEl: Element): boolean {
|
|
83
84
|
return el.contains(descEl);
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
//`descEl` may live in a different document than `el` (e.g. focus is inside a same-origin
|
|
88
|
+
//iframe) - Node.contains never crosses document boundaries, so walk out through each
|
|
89
|
+
//frame's <iframe> element in its parent document until we either cross into el's document
|
|
90
|
+
//or run out of ancestor frames.
|
|
86
91
|
export function isSelfOrDescendant(el: Element, descEl: Element): boolean {
|
|
87
|
-
|
|
92
|
+
let node: Element | null | undefined = descEl;
|
|
93
|
+
while (node) {
|
|
94
|
+
if (el == node || el.contains(node)) return true;
|
|
95
|
+
let win: Window | null = node.ownerDocument?.defaultView;
|
|
96
|
+
node = win?.frameElement;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
88
99
|
}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
//IE sometimes returns null while other browsers always return document.body.
|
|
2
|
-
export function getActiveElement(): Element {
|
|
3
|
-
|
|
2
|
+
export function getActiveElement(doc: Document = document): Element {
|
|
3
|
+
let active = doc.activeElement ?? doc.body;
|
|
4
|
+
|
|
5
|
+
//when focus is inside a same-origin iframe, `doc.activeElement` only reports the
|
|
6
|
+
//<iframe> element itself - drill into its own document to find the element that's
|
|
7
|
+
//actually focused there (recursively, in case of nested iframes)
|
|
8
|
+
if (active && active.tagName === "IFRAME") {
|
|
9
|
+
const iframe = active as HTMLIFrameElement;
|
|
10
|
+
let frameDoc = iframe.contentDocument;
|
|
11
|
+
if (frameDoc) {
|
|
12
|
+
const inner = getActiveElement(frameDoc);
|
|
13
|
+
return inner ?? active;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return active;
|
|
4
18
|
}
|
|
@@ -16,8 +16,13 @@ import { stopPropagation } from "../../util/eventCallbacks";
|
|
|
16
16
|
import { KeyCode } from "../../util/KeyCode";
|
|
17
17
|
import { autoFocus } from "../autoFocus";
|
|
18
18
|
import { getActiveElement } from "../../util/getActiveElement";
|
|
19
|
+
import { isString } from "../../util/isString";
|
|
19
20
|
import { NumberProp } from "../../ui/Prop";
|
|
20
21
|
|
|
22
|
+
/**
|
|
23
|
+
* `trim` applies to the commit that ends the edit, not to intermediate `input` commits. Whitespace
|
|
24
|
+
* inside the text is never touched.
|
|
25
|
+
*/
|
|
21
26
|
export interface TextAreaConfig extends TextFieldConfig {
|
|
22
27
|
/** Specifies the number of visible lines. */
|
|
23
28
|
rows?: NumberProp;
|
|
@@ -199,8 +204,12 @@ class Input extends VDOM.Component<InputProps, InputState> {
|
|
|
199
204
|
}
|
|
200
205
|
|
|
201
206
|
if (instance.widget.reactOn.indexOf(change) != -1) {
|
|
202
|
-
|
|
207
|
+
// Trimming on `input` would strip whitespace the user is still typing, so a trailing
|
|
208
|
+
// newline could never be entered.
|
|
209
|
+
let text = change != "input" && data.trim && isString(inputValue) ? inputValue.trim() : inputValue;
|
|
210
|
+
let value = text || widget.emptyValue;
|
|
203
211
|
instance.set("value", value);
|
|
212
|
+
if (this.input && text != inputValue) this.input.value = text;
|
|
204
213
|
}
|
|
205
214
|
}
|
|
206
215
|
|
|
@@ -72,10 +72,11 @@ import DropDownIcon from "../icons/sort-asc";
|
|
|
72
72
|
import { captureMouse2, getCursorPos } from "../overlay/captureMouse";
|
|
73
73
|
import { tooltipMouseLeave, tooltipMouseMove } from "../overlay/tooltip-ops";
|
|
74
74
|
import { createGridCellEditor } from "./createGridCellEditor";
|
|
75
|
-
import { GridRow, GridRowComponent,
|
|
75
|
+
import { GridRow, GridRowComponent, GridRowInstance } from "./GridRow";
|
|
76
|
+
import type { GridRowConfig } from "./GridRow";
|
|
76
77
|
import { Create, CreateConfig } from "../../util";
|
|
77
78
|
import type { TreeAdapter } from "../../ui/adapter/TreeAdapter";
|
|
78
|
-
export { GridRowConfig };
|
|
79
|
+
export type { GridRowConfig };
|
|
79
80
|
|
|
80
81
|
export type GridFetchRecordsResult<T> = T[] | { records: T[]; lastPage?: boolean; totalRecordCount?: number };
|
|
81
82
|
|
|
@@ -385,7 +385,7 @@ class MenuItemComponent extends VDOM.Component<MenuItemComponentProps, MenuItemC
|
|
|
385
385
|
debug(menuFlag, "MenuItem", "mouseLeave", this.el);
|
|
386
386
|
this.clearAutoFocusTimer();
|
|
387
387
|
|
|
388
|
-
if (widget.hoverToOpen &&
|
|
388
|
+
if (widget.hoverToOpen && getActiveElement() == this.el) unfocusElement(this.el!);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
tooltipMouseLeave(e, this.props.instance, widget.tooltip);
|
|
@@ -486,7 +486,7 @@ class MenuItemComponent extends VDOM.Component<MenuItemComponentProps, MenuItemC
|
|
|
486
486
|
let { widget } = this.props.instance;
|
|
487
487
|
if (widget.dropdown) {
|
|
488
488
|
oneFocusOut(this, this.el!, this.onFocusOut.bind(this));
|
|
489
|
-
debug(menuFlag, "MenuItem", "focus", this.el,
|
|
489
|
+
debug(menuFlag, "MenuItem", "focus", this.el, getActiveElement());
|
|
490
490
|
this.clearAutoFocusTimer();
|
|
491
491
|
if (widget.openOnFocus) this.openDropdown();
|
|
492
492
|
}
|
|
@@ -5,6 +5,7 @@ import { Widget, VDOM } from "../../ui/Widget";
|
|
|
5
5
|
import { calculateNaturalElementHeight } from "../../util/calculateNaturalElementHeight";
|
|
6
6
|
import { closestParent, findFirst, isFocusable } from "../../util/DOM";
|
|
7
7
|
import { getTopLevelBoundingClientRect } from "../../util/getTopLevelBoundingClientRect";
|
|
8
|
+
import { getParentFrameBoundingClientRect } from "../../util/getParentFrameBoundingClientRect";
|
|
8
9
|
import { isTouchDevice } from "../../util/isTouchDevice";
|
|
9
10
|
import {
|
|
10
11
|
ConfigureOverlayContainerContext,
|
|
@@ -224,6 +225,23 @@ export class DropdownBase<
|
|
|
224
225
|
component.updateDropdownPosition,
|
|
225
226
|
);
|
|
226
227
|
|
|
228
|
+
//if the related element lives in a different document (e.g. inside a same-origin
|
|
229
|
+
//iframe), that document/window has its own scroll position and its own resize event
|
|
230
|
+
//(which also fires when the <iframe> element itself is resized) - neither is observed
|
|
231
|
+
//by the top-level `window` above or by the relatedElement's parentElement chain, so
|
|
232
|
+
//track every frame window between the related element's document and the top document.
|
|
233
|
+
var frameWindows: Window[] = (component.frameWindows = []);
|
|
234
|
+
var frameWin: Window | null | undefined =
|
|
235
|
+
instance.relatedElement?.ownerDocument?.defaultView;
|
|
236
|
+
while (frameWin && frameWin !== window) {
|
|
237
|
+
frameWindows.push(frameWin);
|
|
238
|
+
frameWin = frameWin.frameElement?.ownerDocument?.defaultView;
|
|
239
|
+
}
|
|
240
|
+
frameWindows.forEach((w) => {
|
|
241
|
+
w.addEventListener("scroll", component.updateDropdownPosition);
|
|
242
|
+
w.addEventListener("resize", component.updateDropdownPosition);
|
|
243
|
+
});
|
|
244
|
+
|
|
227
245
|
if (this.onDropdownDidMount)
|
|
228
246
|
instance.invoke("onDropdownDidMount", instance, component);
|
|
229
247
|
|
|
@@ -246,14 +264,21 @@ export class DropdownBase<
|
|
|
246
264
|
}
|
|
247
265
|
|
|
248
266
|
overlayWillUnmount(instance: InstanceType, component: any): void {
|
|
249
|
-
var { scrollableParents } = component;
|
|
267
|
+
var { scrollableParents, frameWindows } = component;
|
|
250
268
|
if (scrollableParents) {
|
|
251
269
|
scrollableParents.forEach((el: Element) => {
|
|
252
270
|
el.removeEventListener("scroll", component.updateDropdownPosition);
|
|
253
271
|
});
|
|
254
272
|
delete component.scrollableParents;
|
|
255
|
-
delete component.updateDropdownPosition;
|
|
256
273
|
}
|
|
274
|
+
if (frameWindows) {
|
|
275
|
+
frameWindows.forEach((w: Window) => {
|
|
276
|
+
w.removeEventListener("scroll", component.updateDropdownPosition);
|
|
277
|
+
w.removeEventListener("resize", component.updateDropdownPosition);
|
|
278
|
+
});
|
|
279
|
+
delete component.frameWindows;
|
|
280
|
+
}
|
|
281
|
+
delete component.updateDropdownPosition;
|
|
257
282
|
if (component.offResize) component.offResize();
|
|
258
283
|
|
|
259
284
|
if (this.pipeValidateDropdownPosition)
|
|
@@ -278,7 +303,17 @@ export class DropdownBase<
|
|
|
278
303
|
updateDropdownPosition(instance: InstanceType, component: any): void {
|
|
279
304
|
var { el, initialScreenPosition } = component;
|
|
280
305
|
var { data, relatedElement } = instance;
|
|
281
|
-
var
|
|
306
|
+
var elDocument: Document = el.ownerDocument || document;
|
|
307
|
+
|
|
308
|
+
//if the dropdown renders in the same document as its related element (e.g. not
|
|
309
|
+
//portaled to the top-level body, such as an inline dropdown living inside an
|
|
310
|
+
//iframe together with its field), no cross-document offset should be applied -
|
|
311
|
+
//getBoundingClientRect() is already relative to that shared document/viewport.
|
|
312
|
+
var isSameDocument =
|
|
313
|
+
el && relatedElement && el.ownerDocument === relatedElement.ownerDocument;
|
|
314
|
+
var parentBounds = isSameDocument
|
|
315
|
+
? relatedElement!.getBoundingClientRect()
|
|
316
|
+
: getTopLevelBoundingClientRect(relatedElement!);
|
|
282
317
|
|
|
283
318
|
//getBoundingClientRect() will return an empty rect if the element is hidden or removed
|
|
284
319
|
if (
|
|
@@ -291,19 +326,33 @@ export class DropdownBase<
|
|
|
291
326
|
parentBounds = component.parentBounds;
|
|
292
327
|
} else component.parentBounds = parentBounds;
|
|
293
328
|
|
|
294
|
-
|
|
329
|
+
//instance.mousePosition (set from getCursorPos) is always expressed in top-document
|
|
330
|
+
//coordinates. When the dropdown and its related element share a document that isn't
|
|
331
|
+
//the top document (e.g. both live inside the same iframe), parentBounds above is in
|
|
332
|
+
//that document's own coordinate space, so the mouse position must be translated into
|
|
333
|
+
//the same space before it can replace part of parentBounds.
|
|
334
|
+
var mousePosition = instance.mousePosition;
|
|
335
|
+
if (mousePosition && isSameDocument && elDocument !== document) {
|
|
336
|
+
const frameOffset = getParentFrameBoundingClientRect(relatedElement!);
|
|
337
|
+
mousePosition = {
|
|
338
|
+
x: mousePosition.x - frameOffset.left,
|
|
339
|
+
y: mousePosition.y - frameOffset.top,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (this.trackMouseX && mousePosition) {
|
|
295
344
|
parentBounds = new DOMRect(
|
|
296
|
-
|
|
345
|
+
mousePosition.x,
|
|
297
346
|
parentBounds.top,
|
|
298
347
|
0,
|
|
299
348
|
parentBounds.bottom - parentBounds.top,
|
|
300
349
|
);
|
|
301
350
|
}
|
|
302
351
|
|
|
303
|
-
if (this.trackMouseY &&
|
|
352
|
+
if (this.trackMouseY && mousePosition) {
|
|
304
353
|
parentBounds = new DOMRect(
|
|
305
354
|
parentBounds.left,
|
|
306
|
-
|
|
355
|
+
mousePosition.y,
|
|
307
356
|
parentBounds.right - parentBounds.left,
|
|
308
357
|
0,
|
|
309
358
|
);
|
|
@@ -334,6 +383,7 @@ export class DropdownBase<
|
|
|
334
383
|
parentBounds,
|
|
335
384
|
data.placement,
|
|
336
385
|
component.lastPlacement,
|
|
386
|
+
elDocument,
|
|
337
387
|
);
|
|
338
388
|
|
|
339
389
|
var arrowAdjust = this.getArrowAdjust(component);
|
|
@@ -346,6 +396,7 @@ export class DropdownBase<
|
|
|
346
396
|
el,
|
|
347
397
|
false,
|
|
348
398
|
arrowAdjust,
|
|
399
|
+
elDocument,
|
|
349
400
|
);
|
|
350
401
|
component.setCustomStyle(style);
|
|
351
402
|
this.setDirectionClass(component, placement);
|
|
@@ -366,6 +417,7 @@ export class DropdownBase<
|
|
|
366
417
|
el,
|
|
367
418
|
true,
|
|
368
419
|
arrowAdjust,
|
|
420
|
+
elDocument,
|
|
369
421
|
);
|
|
370
422
|
component.setCustomStyle(newStyle);
|
|
371
423
|
}
|
|
@@ -412,8 +464,9 @@ export class DropdownBase<
|
|
|
412
464
|
el: HTMLElement,
|
|
413
465
|
noAuto: boolean,
|
|
414
466
|
arrowAdjust: number = 0,
|
|
467
|
+
elDocument: Document,
|
|
415
468
|
): void {
|
|
416
|
-
let viewport = getViewportRect(this.screenPadding);
|
|
469
|
+
let viewport = getViewportRect(this.screenPadding, elDocument);
|
|
417
470
|
style.position = "fixed";
|
|
418
471
|
|
|
419
472
|
if (placement.startsWith("down")) {
|
|
@@ -431,7 +484,7 @@ export class DropdownBase<
|
|
|
431
484
|
? Math.max(this.screenPadding, top) + "px"
|
|
432
485
|
: "auto";
|
|
433
486
|
style.bottom =
|
|
434
|
-
|
|
487
|
+
elDocument.documentElement.clientHeight -
|
|
435
488
|
(this.cover ? rel.bottom : rel.top) +
|
|
436
489
|
this.offset +
|
|
437
490
|
"px";
|
|
@@ -450,7 +503,7 @@ export class DropdownBase<
|
|
|
450
503
|
break;
|
|
451
504
|
|
|
452
505
|
case "down-left":
|
|
453
|
-
style.right = `${
|
|
506
|
+
style.right = `${elDocument.documentElement.clientWidth - rel.right - arrowAdjust}px`;
|
|
454
507
|
style.left = "auto";
|
|
455
508
|
break;
|
|
456
509
|
|
|
@@ -466,7 +519,7 @@ export class DropdownBase<
|
|
|
466
519
|
break;
|
|
467
520
|
|
|
468
521
|
case "up-left":
|
|
469
|
-
style.right = `${
|
|
522
|
+
style.right = `${elDocument.documentElement.clientWidth - rel.right - arrowAdjust}px`;
|
|
470
523
|
style.left = "auto";
|
|
471
524
|
break;
|
|
472
525
|
|
|
@@ -488,45 +541,45 @@ export class DropdownBase<
|
|
|
488
541
|
case "right-up":
|
|
489
542
|
style.top = "auto";
|
|
490
543
|
style.right = "auto";
|
|
491
|
-
style.bottom = `${
|
|
544
|
+
style.bottom = `${elDocument.documentElement.clientHeight - rel.bottom - arrowAdjust}px`;
|
|
492
545
|
style.left = `${rel.right + this.offset}px`;
|
|
493
546
|
break;
|
|
494
547
|
|
|
495
548
|
case "left":
|
|
496
549
|
case "left-center":
|
|
497
550
|
style.top = `${Math.round((rel.top + rel.bottom - el.offsetHeight) / 2)}px`;
|
|
498
|
-
style.right = `${
|
|
551
|
+
style.right = `${elDocument.documentElement.clientWidth - rel.left + this.offset}px`;
|
|
499
552
|
style.bottom = "auto";
|
|
500
553
|
style.left = "auto";
|
|
501
554
|
break;
|
|
502
555
|
|
|
503
556
|
case "left-down":
|
|
504
557
|
style.top = `${rel.top - arrowAdjust}px`;
|
|
505
|
-
style.right = `${
|
|
558
|
+
style.right = `${elDocument.documentElement.clientWidth - rel.left + this.offset}px`;
|
|
506
559
|
style.bottom = "auto";
|
|
507
560
|
style.left = "auto";
|
|
508
561
|
break;
|
|
509
562
|
|
|
510
563
|
case "left-up":
|
|
511
564
|
style.top = "auto";
|
|
512
|
-
style.right = `${
|
|
513
|
-
style.bottom = `${
|
|
565
|
+
style.right = `${elDocument.documentElement.clientWidth - rel.left + this.offset}px`;
|
|
566
|
+
style.bottom = `${elDocument.documentElement.clientHeight - rel.bottom - arrowAdjust}px`;
|
|
514
567
|
style.left = "auto";
|
|
515
568
|
break;
|
|
516
569
|
|
|
517
570
|
case "screen-center":
|
|
518
571
|
let w = Math.min(
|
|
519
572
|
contentSize.width,
|
|
520
|
-
|
|
573
|
+
elDocument.documentElement.clientWidth - 2 * this.screenPadding,
|
|
521
574
|
);
|
|
522
575
|
let h = Math.min(
|
|
523
576
|
contentSize.height,
|
|
524
|
-
|
|
577
|
+
elDocument.documentElement.clientHeight - 2 * this.screenPadding,
|
|
525
578
|
);
|
|
526
|
-
style.top = `${Math.round((
|
|
527
|
-
style.right = `${Math.round((
|
|
528
|
-
style.bottom = `${Math.round((
|
|
529
|
-
style.left = `${Math.round((
|
|
579
|
+
style.top = `${Math.round((elDocument.documentElement.clientHeight - h) / 2)}px`;
|
|
580
|
+
style.right = `${Math.round((elDocument.documentElement.clientWidth - w) / 2)}px`;
|
|
581
|
+
style.bottom = `${Math.round((elDocument.documentElement.clientHeight - h) / 2)}px`;
|
|
582
|
+
style.left = `${Math.round((elDocument.documentElement.clientWidth - w) / 2)}px`;
|
|
530
583
|
break;
|
|
531
584
|
}
|
|
532
585
|
}
|
|
@@ -539,8 +592,9 @@ export class DropdownBase<
|
|
|
539
592
|
el: HTMLElement,
|
|
540
593
|
noAuto: boolean,
|
|
541
594
|
arrowAdjust: number = 0,
|
|
595
|
+
elDocument: Document,
|
|
542
596
|
): void {
|
|
543
|
-
var viewport = getViewportRect(this.screenPadding);
|
|
597
|
+
var viewport = getViewportRect(this.screenPadding, elDocument);
|
|
544
598
|
|
|
545
599
|
style.position = "absolute";
|
|
546
600
|
|
|
@@ -647,6 +701,7 @@ export class DropdownBase<
|
|
|
647
701
|
el: HTMLElement,
|
|
648
702
|
noAuto: boolean,
|
|
649
703
|
arrowAdjust: number = 0,
|
|
704
|
+
elDocument: Document,
|
|
650
705
|
): void {
|
|
651
706
|
switch (this.positioning) {
|
|
652
707
|
case "absolute":
|
|
@@ -658,6 +713,7 @@ export class DropdownBase<
|
|
|
658
713
|
el,
|
|
659
714
|
noAuto,
|
|
660
715
|
arrowAdjust,
|
|
716
|
+
elDocument,
|
|
661
717
|
);
|
|
662
718
|
break;
|
|
663
719
|
|
|
@@ -671,6 +727,7 @@ export class DropdownBase<
|
|
|
671
727
|
el,
|
|
672
728
|
noAuto,
|
|
673
729
|
arrowAdjust,
|
|
730
|
+
elDocument,
|
|
674
731
|
);
|
|
675
732
|
else
|
|
676
733
|
this.applyFixedPositioningPlacementStyles(
|
|
@@ -681,6 +738,7 @@ export class DropdownBase<
|
|
|
681
738
|
el,
|
|
682
739
|
noAuto,
|
|
683
740
|
arrowAdjust,
|
|
741
|
+
elDocument,
|
|
684
742
|
);
|
|
685
743
|
break;
|
|
686
744
|
|
|
@@ -693,6 +751,7 @@ export class DropdownBase<
|
|
|
693
751
|
el,
|
|
694
752
|
noAuto,
|
|
695
753
|
arrowAdjust,
|
|
754
|
+
elDocument,
|
|
696
755
|
);
|
|
697
756
|
break;
|
|
698
757
|
}
|
|
@@ -749,13 +808,14 @@ export class DropdownBase<
|
|
|
749
808
|
target: any,
|
|
750
809
|
placement: string,
|
|
751
810
|
lastPlacement: any,
|
|
811
|
+
elDocument: Document,
|
|
752
812
|
): any {
|
|
753
813
|
var placementOrder = this.placementOrder.split(" ");
|
|
754
814
|
var best = lastPlacement || placement;
|
|
755
815
|
var first;
|
|
756
816
|
|
|
757
817
|
var score: Record<string, number> = {};
|
|
758
|
-
var viewport = getViewportRect();
|
|
818
|
+
var viewport = getViewportRect(0, elDocument);
|
|
759
819
|
|
|
760
820
|
for (var i = 0; i < placementOrder.length; i++) {
|
|
761
821
|
var p = placementOrder[i];
|
|
@@ -970,11 +1030,11 @@ export class Dropdown extends DropdownBase<DropdownConfig, DropdownInstance> {}
|
|
|
970
1030
|
Widget.alias("dropdown", Dropdown);
|
|
971
1031
|
Localization.registerPrototype("cx/widgets/Dropdown", Dropdown);
|
|
972
1032
|
|
|
973
|
-
function getViewportRect(padding = 0) {
|
|
1033
|
+
function getViewportRect(padding = 0, elDocument: Document = document) {
|
|
974
1034
|
return {
|
|
975
1035
|
left: padding,
|
|
976
1036
|
top: padding,
|
|
977
|
-
right:
|
|
978
|
-
bottom:
|
|
1037
|
+
right: elDocument.documentElement.clientWidth - padding,
|
|
1038
|
+
bottom: elDocument.documentElement.clientHeight - padding,
|
|
979
1039
|
};
|
|
980
1040
|
}
|
|
@@ -765,9 +765,11 @@ export class OverlayComponent<
|
|
|
765
765
|
widget.handleResize(e, instance, this);
|
|
766
766
|
} else {
|
|
767
767
|
let prefix = this.getResizePrefix(e);
|
|
768
|
-
this.setCustomStyle({
|
|
769
|
-
|
|
770
|
-
|
|
768
|
+
if (prefix) this.setCustomStyle({ cursor: `${prefix}-resize` });
|
|
769
|
+
else if (this.customStyle.cursor) {
|
|
770
|
+
delete this.customStyle.cursor;
|
|
771
|
+
if (this.el) this.el.style.cursor = data.style?.cursor ?? "";
|
|
772
|
+
}
|
|
771
773
|
}
|
|
772
774
|
}
|
|
773
775
|
|
|
@@ -21,6 +21,7 @@ import { isDefined } from "../../util/isDefined";
|
|
|
21
21
|
import { isString } from "../../util/isString";
|
|
22
22
|
import { BooleanProp, StringProp, StyleProp, ClassProp } from "../../ui/Prop";
|
|
23
23
|
import { RenderingContext } from "../../ui/RenderingContext";
|
|
24
|
+
import { getActiveElement } from "../../util/getActiveElement";
|
|
24
25
|
|
|
25
26
|
export interface WindowConfig extends OverlayConfig {
|
|
26
27
|
/** Text to be displayed in the header. */
|
|
@@ -292,7 +293,7 @@ class WindowComponent extends OverlayComponent<WindowComponentProps, WindowCompo
|
|
|
292
293
|
onFocusIn() {
|
|
293
294
|
super.onFocusIn();
|
|
294
295
|
if (!this.state.active) {
|
|
295
|
-
if (this.containerEl?.contains(
|
|
296
|
+
if (this.containerEl?.contains(getActiveElement())) this.setZIndex(ZIndexManager.next());
|
|
296
297
|
this.setState({ active: true });
|
|
297
298
|
}
|
|
298
299
|
}
|