@reshaped/utilities 3.9.1-canary.2 → 3.10.0-canary.4
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/dist/a11y/Chain.d.ts +20 -0
- package/dist/a11y/Chain.js +60 -0
- package/dist/a11y/TrapFocus.d.ts +28 -0
- package/dist/a11y/TrapFocus.js +162 -0
- package/dist/a11y/TrapScreenReader.d.ts +15 -0
- package/dist/a11y/TrapScreenReader.js +42 -0
- package/dist/a11y/focus.d.ts +38 -0
- package/dist/a11y/focus.js +101 -0
- package/dist/a11y/index.d.ts +4 -0
- package/dist/a11y/index.js +3 -0
- package/dist/a11y/keyboardMode.d.ts +4 -0
- package/dist/a11y/keyboardMode.js +10 -0
- package/dist/a11y/tests/Chain.test.js +88 -0
- package/dist/a11y/tests/TrapFocus.test.d.ts +1 -0
- package/dist/a11y/tests/TrapFocus.test.js +313 -0
- package/dist/a11y/tests/TrapScreenReader.test.d.ts +1 -0
- package/dist/a11y/tests/TrapScreenReader.test.js +126 -0
- package/dist/a11y/tests/focus.test.d.ts +1 -0
- package/dist/a11y/tests/focus.test.js +278 -0
- package/dist/a11y/tests/keyboardMode.test.d.ts +1 -0
- package/dist/a11y/tests/keyboardMode.test.js +27 -0
- package/dist/a11y/types.d.ts +24 -0
- package/dist/a11y/types.js +1 -0
- package/dist/constants/keys.d.ts +11 -0
- package/dist/constants/keys.js +11 -0
- package/dist/css/StyleCache.d.ts +7 -0
- package/dist/css/StyleCache.js +19 -0
- package/dist/css/classNames.d.ts +7 -0
- package/dist/css/classNames.js +19 -0
- package/dist/css/index.d.ts +2 -0
- package/dist/css/index.js +4 -0
- package/dist/css/tests/StyleCache.test.d.ts +1 -0
- package/dist/css/tests/StyleCache.test.js +45 -0
- package/dist/css/tests/classNames.test.d.ts +1 -0
- package/dist/css/tests/classNames.test.js +63 -0
- package/dist/dom/findClosestScrollableContainer.d.ts +5 -0
- package/dist/dom/findClosestScrollableContainer.js +12 -0
- package/dist/dom/findParent.d.ts +2 -0
- package/dist/dom/findParent.js +10 -0
- package/dist/dom/index.d.ts +3 -0
- package/dist/dom/index.js +4 -0
- package/dist/dom/tests/findClosestScrollableContainer.test.d.ts +1 -0
- package/dist/dom/tests/findClosestScrollableContainer.test.js +61 -0
- package/dist/dom/tests/findParent.test.d.ts +1 -0
- package/dist/dom/tests/findParent.test.js +45 -0
- package/dist/flyout/Flyout.js +11 -9
- package/dist/flyout/constants.d.ts +1 -1
- package/dist/flyout/constants.js +1 -1
- package/dist/flyout/index.d.ts +1 -1
- package/dist/flyout/index.js +1 -1
- package/dist/flyout/tests/Flyout.test.js +1 -1
- package/dist/flyout/types.d.ts +1 -1
- package/dist/flyout/utilities/applyPosition.js +46 -26
- package/dist/flyout/utilities/calculateLayoutAdjustment.d.ts +19 -0
- package/dist/flyout/utilities/calculateLayoutAdjustment.js +73 -0
- package/dist/flyout/utilities/calculatePosition.d.ts +7 -20
- package/dist/flyout/utilities/calculatePosition.js +11 -87
- package/dist/flyout/utilities/isFullyVisible.d.ts +2 -4
- package/dist/flyout/utilities/isFullyVisible.js +11 -14
- package/dist/flyout/utilities/tests/applyPosition.test.js +1 -1
- package/dist/flyout/utilities/tests/calculateLayoutAdjustment.test.d.ts +1 -0
- package/dist/flyout/utilities/tests/calculateLayoutAdjustment.test.js +384 -0
- package/dist/flyout/utilities/tests/calculatePosition.test.js +244 -293
- package/dist/flyout/utilities/tests/centerBySize.test.js +1 -1
- package/dist/flyout/utilities/tests/getPositionFallbacks.test.js +1 -1
- package/dist/flyout/utilities/tests/getRTLPosition.test.js +1 -1
- package/dist/flyout/utilities/tests/isFullyVisible.test.js +28 -52
- package/dist/helpers/classNames.d.ts +7 -0
- package/dist/helpers/classNames.js +19 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/tests/classNames.test.d.ts +1 -0
- package/dist/helpers/tests/classNames.test.js +63 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +2 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/internal.d.ts +11 -0
- package/dist/internal.js +10 -0
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.js +16 -0
- package/dist/scroll/disable.d.ts +7 -0
- package/dist/scroll/disable.js +15 -0
- package/dist/scroll/helpers.d.ts +1 -0
- package/dist/scroll/helpers.js +17 -0
- package/dist/scroll/index.d.ts +2 -0
- package/dist/scroll/index.js +4 -0
- package/dist/scroll/lock.d.ts +7 -0
- package/dist/scroll/lock.js +26 -0
- package/dist/scroll/lockSafari.d.ts +2 -0
- package/dist/scroll/lockSafari.js +20 -0
- package/dist/scroll/lockStandard.d.ts +4 -0
- package/dist/scroll/lockStandard.js +15 -0
- package/dist/scroll/tests/lock.test.d.ts +1 -0
- package/dist/scroll/tests/lock.test.js +81 -0
- package/package.json +6 -1
- package/dist/flyout/utilities/findClosestFixedContainer.d.ts +0 -5
- package/dist/flyout/utilities/findClosestFixedContainer.js +0 -18
- package/dist/flyout/utilities/tests/findClosestFixedContainer.test.js +0 -46
- /package/dist/{flyout/utilities/tests/findClosestFixedContainer.test.d.ts → a11y/tests/Chain.test.d.ts} +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { expect, test, describe, vi } from "vitest";
|
|
2
|
-
import
|
|
3
|
-
import calculatePosition from "../calculatePosition.js";
|
|
1
|
+
import { expect, test, describe, vi, beforeEach } from "vitest";
|
|
2
|
+
import calculatePosition from "flyout/utilities/calculatePosition";
|
|
4
3
|
describe("flyout/calculatePosition", () => {
|
|
5
4
|
const createBounds = (left, top, width, height) => {
|
|
6
5
|
return {
|
|
@@ -15,522 +14,474 @@ describe("flyout/calculatePosition", () => {
|
|
|
15
14
|
toJSON: vi.fn(),
|
|
16
15
|
};
|
|
17
16
|
};
|
|
18
|
-
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
// Set consistent viewport dimensions for tests
|
|
19
|
+
Object.defineProperty(window, "innerWidth", { value: 1000, writable: true });
|
|
20
|
+
Object.defineProperty(window, "innerHeight", { value: 800, writable: true });
|
|
21
|
+
});
|
|
22
|
+
test("calculates position for 'top'", () => {
|
|
19
23
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
20
24
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
21
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
22
25
|
const result = calculatePosition({
|
|
23
26
|
triggerBounds,
|
|
24
27
|
flyoutBounds,
|
|
25
|
-
containerBounds,
|
|
26
28
|
position: "top",
|
|
27
29
|
rtl: false,
|
|
28
30
|
contentGap: 0,
|
|
29
31
|
contentShift: 0,
|
|
30
32
|
});
|
|
31
|
-
// top
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
expect(result.
|
|
36
|
-
|
|
37
|
-
expect(result.styles.
|
|
38
|
-
expect(result.styles.bottom).toBe(
|
|
39
|
-
expect(result.styles.left).toBe("0px");
|
|
33
|
+
// top: relativeTop - flyoutHeight - contentGap = 200 - 60 - 0 = 140
|
|
34
|
+
// left: relativeLeft + centerBySize(triggerWidth, flyoutWidth) = 100 + (50/2 - 40/2) = 105
|
|
35
|
+
// bottom: relativeBottom + triggerHeight + contentGap = (800 - 230) + 30 + 0 = 600
|
|
36
|
+
// right: null
|
|
37
|
+
expect(result.position).toBe("top");
|
|
38
|
+
expect(result.styles.top).toBe(140);
|
|
39
|
+
expect(result.styles.left).toBe(105);
|
|
40
|
+
expect(result.styles.bottom).toBe(600);
|
|
40
41
|
expect(result.styles.right).toBe(null);
|
|
41
42
|
});
|
|
42
|
-
test("calculates position for bottom
|
|
43
|
+
test("calculates position for 'bottom'", () => {
|
|
43
44
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
44
45
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
45
|
-
const
|
|
46
|
-
const bottom = calculatePosition({
|
|
46
|
+
const result = calculatePosition({
|
|
47
47
|
triggerBounds,
|
|
48
48
|
flyoutBounds,
|
|
49
|
-
containerBounds,
|
|
50
49
|
position: "bottom",
|
|
51
50
|
rtl: false,
|
|
52
51
|
contentGap: 0,
|
|
53
52
|
contentShift: 0,
|
|
54
53
|
});
|
|
55
|
-
// relativeTop
|
|
56
|
-
// relativeLeft
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
// top: relativeTop + triggerHeight + contentGap = 200 + 30 + 0 = 230
|
|
55
|
+
// left: relativeLeft + centerBySize(triggerWidth, flyoutWidth) = 100 + 5 = 105
|
|
56
|
+
// bottom: null
|
|
57
|
+
// right: null
|
|
58
|
+
expect(result.position).toBe("bottom");
|
|
59
|
+
expect(result.styles.top).toBe(230);
|
|
60
|
+
expect(result.styles.left).toBe(105);
|
|
61
|
+
expect(result.styles.bottom).toBe(null);
|
|
62
|
+
expect(result.styles.right).toBe(null);
|
|
63
|
+
});
|
|
64
|
+
test("calculates position for 'start'", () => {
|
|
65
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
66
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
67
|
+
const result = calculatePosition({
|
|
60
68
|
triggerBounds,
|
|
61
69
|
flyoutBounds,
|
|
62
|
-
containerBounds,
|
|
63
70
|
position: "start",
|
|
64
71
|
rtl: false,
|
|
65
72
|
contentGap: 0,
|
|
66
73
|
contentShift: 0,
|
|
67
74
|
});
|
|
68
|
-
// relativeLeft
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
// left: relativeLeft - flyoutWidth - contentGap = 100 - 40 - 0 = 60
|
|
76
|
+
// right: relativeRight + triggerWidth + contentGap = (1000 - 150) + 50 + 0 = 900
|
|
77
|
+
// top: relativeTop + centerBySize(triggerHeight, flyoutHeight) = 200 + (30/2 - 60/2) = 185
|
|
78
|
+
// bottom: null
|
|
79
|
+
expect(result.position).toBe("start");
|
|
80
|
+
expect(result.styles.left).toBe(60);
|
|
81
|
+
expect(result.styles.right).toBe(900);
|
|
82
|
+
expect(result.styles.top).toBe(185);
|
|
83
|
+
expect(result.styles.bottom).toBe(null);
|
|
84
|
+
});
|
|
85
|
+
test("calculates position for 'end'", () => {
|
|
86
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
87
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
88
|
+
const result = calculatePosition({
|
|
73
89
|
triggerBounds,
|
|
74
90
|
flyoutBounds,
|
|
75
|
-
containerBounds,
|
|
76
91
|
position: "end",
|
|
77
92
|
rtl: false,
|
|
78
93
|
contentGap: 0,
|
|
79
94
|
contentShift: 0,
|
|
80
95
|
});
|
|
81
|
-
// relativeLeft
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
96
|
+
// left: relativeLeft + triggerWidth + contentGap = 100 + 50 + 0 = 150
|
|
97
|
+
// right: null
|
|
98
|
+
// top: relativeTop + centerBySize(triggerHeight, flyoutHeight) = 200 + (30/2 - 60/2) = 185
|
|
99
|
+
// bottom: null
|
|
100
|
+
expect(result.position).toBe("end");
|
|
101
|
+
expect(result.styles.left).toBe(150);
|
|
102
|
+
expect(result.styles.right).toBe(null);
|
|
103
|
+
expect(result.styles.top).toBe(185);
|
|
104
|
+
expect(result.styles.bottom).toBe(null);
|
|
85
105
|
});
|
|
86
|
-
test("calculates position for top-start
|
|
106
|
+
test("calculates position for 'top-start'", () => {
|
|
87
107
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
88
108
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
89
|
-
const
|
|
90
|
-
const topStart = calculatePosition({
|
|
109
|
+
const result = calculatePosition({
|
|
91
110
|
triggerBounds,
|
|
92
111
|
flyoutBounds,
|
|
93
|
-
containerBounds,
|
|
94
112
|
position: "top-start",
|
|
95
113
|
rtl: false,
|
|
96
114
|
contentGap: 0,
|
|
97
115
|
contentShift: 0,
|
|
98
116
|
});
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
117
|
+
// left: relativeLeft + contentShift = 100 + 0 = 100
|
|
118
|
+
// top: relativeTop - flyoutHeight - contentGap = 200 - 60 - 0 = 140
|
|
119
|
+
// bottom: relativeBottom + triggerHeight + contentGap = 570 + 30 + 0 = 600
|
|
120
|
+
// right: null
|
|
121
|
+
expect(result.position).toBe("top-start");
|
|
122
|
+
expect(result.styles.left).toBe(100);
|
|
123
|
+
expect(result.styles.top).toBe(140);
|
|
124
|
+
expect(result.styles.bottom).toBe(600);
|
|
125
|
+
expect(result.styles.right).toBe(null);
|
|
126
|
+
});
|
|
127
|
+
test("calculates position for 'top-end'", () => {
|
|
128
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
129
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
130
|
+
const result = calculatePosition({
|
|
104
131
|
triggerBounds,
|
|
105
132
|
flyoutBounds,
|
|
106
|
-
containerBounds,
|
|
107
133
|
position: "top-end",
|
|
108
134
|
rtl: false,
|
|
109
135
|
contentGap: 0,
|
|
110
136
|
contentShift: 0,
|
|
111
137
|
});
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
expect(
|
|
117
|
-
|
|
138
|
+
// left: relativeLeft + triggerWidth - flyoutWidth + contentShift = 100 + 50 - 40 + 0 = 110
|
|
139
|
+
// right: relativeRight - contentShift = 850 - 0 = 850
|
|
140
|
+
// top: relativeTop - flyoutHeight - contentGap = 200 - 60 - 0 = 140
|
|
141
|
+
// bottom: relativeBottom + triggerHeight + contentGap = 570 + 30 + 0 = 600
|
|
142
|
+
expect(result.position).toBe("top-end");
|
|
143
|
+
expect(result.styles.left).toBe(110);
|
|
144
|
+
expect(result.styles.right).toBe(850);
|
|
145
|
+
expect(result.styles.top).toBe(140);
|
|
146
|
+
expect(result.styles.bottom).toBe(600);
|
|
147
|
+
});
|
|
148
|
+
test("calculates position for 'bottom-start'", () => {
|
|
149
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
150
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
151
|
+
const result = calculatePosition({
|
|
118
152
|
triggerBounds,
|
|
119
153
|
flyoutBounds,
|
|
120
|
-
containerBounds,
|
|
121
154
|
position: "bottom-start",
|
|
122
155
|
rtl: false,
|
|
123
156
|
contentGap: 0,
|
|
124
157
|
contentShift: 0,
|
|
125
158
|
});
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
159
|
+
// left: relativeLeft + contentShift = 100 + 0 = 100
|
|
160
|
+
// top: relativeTop + triggerHeight + contentGap = 200 + 30 + 0 = 230
|
|
161
|
+
// bottom: null
|
|
162
|
+
// right: null
|
|
163
|
+
expect(result.position).toBe("bottom-start");
|
|
164
|
+
expect(result.styles.left).toBe(100);
|
|
165
|
+
expect(result.styles.top).toBe(230);
|
|
166
|
+
expect(result.styles.bottom).toBe(null);
|
|
167
|
+
expect(result.styles.right).toBe(null);
|
|
168
|
+
});
|
|
169
|
+
test("calculates position for 'bottom-end'", () => {
|
|
170
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
171
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
172
|
+
const result = calculatePosition({
|
|
131
173
|
triggerBounds,
|
|
132
174
|
flyoutBounds,
|
|
133
|
-
containerBounds,
|
|
134
175
|
position: "bottom-end",
|
|
135
176
|
rtl: false,
|
|
136
177
|
contentGap: 0,
|
|
137
178
|
contentShift: 0,
|
|
138
179
|
});
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
180
|
+
// left: relativeLeft + triggerWidth - flyoutWidth + contentShift = 100 + 50 - 40 + 0 = 110
|
|
181
|
+
// right: relativeRight - contentShift = 850 - 0 = 850
|
|
182
|
+
// top: relativeTop + triggerHeight + contentGap = 200 + 30 + 0 = 230
|
|
183
|
+
// bottom: null
|
|
184
|
+
expect(result.position).toBe("bottom-end");
|
|
185
|
+
expect(result.styles.left).toBe(110);
|
|
186
|
+
expect(result.styles.right).toBe(850);
|
|
187
|
+
expect(result.styles.top).toBe(230);
|
|
188
|
+
expect(result.styles.bottom).toBe(null);
|
|
143
189
|
});
|
|
144
|
-
test("calculates position for start-top
|
|
190
|
+
test("calculates position for 'start-top'", () => {
|
|
145
191
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
146
192
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
147
|
-
const
|
|
148
|
-
const startTop = calculatePosition({
|
|
193
|
+
const result = calculatePosition({
|
|
149
194
|
triggerBounds,
|
|
150
195
|
flyoutBounds,
|
|
151
|
-
containerBounds,
|
|
152
196
|
position: "start-top",
|
|
153
197
|
rtl: false,
|
|
154
198
|
contentGap: 0,
|
|
155
199
|
contentShift: 0,
|
|
156
200
|
});
|
|
157
|
-
// relativeLeft
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
201
|
+
// left: relativeLeft - flyoutWidth - contentGap = 100 - 40 - 0 = 60
|
|
202
|
+
// right: relativeRight + triggerWidth + contentGap = 850 + 50 + 0 = 900
|
|
203
|
+
// top: relativeTop + contentShift = 200 + 0 = 200
|
|
204
|
+
// bottom: null
|
|
205
|
+
expect(result.position).toBe("start-top");
|
|
206
|
+
expect(result.styles.left).toBe(60);
|
|
207
|
+
expect(result.styles.right).toBe(900);
|
|
208
|
+
expect(result.styles.top).toBe(200);
|
|
209
|
+
expect(result.styles.bottom).toBe(null);
|
|
210
|
+
});
|
|
211
|
+
test("calculates position for 'start-bottom'", () => {
|
|
212
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
213
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
214
|
+
const result = calculatePosition({
|
|
162
215
|
triggerBounds,
|
|
163
216
|
flyoutBounds,
|
|
164
|
-
containerBounds,
|
|
165
217
|
position: "start-bottom",
|
|
166
218
|
rtl: false,
|
|
167
219
|
contentGap: 0,
|
|
168
220
|
contentShift: 0,
|
|
169
221
|
});
|
|
170
|
-
// relativeLeft
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
expect(
|
|
175
|
-
|
|
222
|
+
// left: relativeLeft - flyoutWidth - contentGap = 100 - 40 - 0 = 60
|
|
223
|
+
// right: relativeRight + triggerWidth + contentGap = 850 + 50 + 0 = 900
|
|
224
|
+
// top: relativeTop + triggerHeight - flyoutHeight + contentShift = 200 + 30 - 60 + 0 = 170
|
|
225
|
+
// bottom: relativeBottom - contentShift = 570 - 0 = 570
|
|
226
|
+
expect(result.position).toBe("start-bottom");
|
|
227
|
+
expect(result.styles.left).toBe(60);
|
|
228
|
+
expect(result.styles.right).toBe(900);
|
|
229
|
+
expect(result.styles.top).toBe(170);
|
|
230
|
+
expect(result.styles.bottom).toBe(570);
|
|
231
|
+
});
|
|
232
|
+
test("calculates position for 'end-top'", () => {
|
|
233
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
234
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
235
|
+
const result = calculatePosition({
|
|
176
236
|
triggerBounds,
|
|
177
237
|
flyoutBounds,
|
|
178
|
-
containerBounds,
|
|
179
238
|
position: "end-top",
|
|
180
239
|
rtl: false,
|
|
181
240
|
contentGap: 0,
|
|
182
241
|
contentShift: 0,
|
|
183
242
|
});
|
|
184
|
-
// relativeLeft
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
243
|
+
// left: relativeLeft + triggerWidth + contentGap = 100 + 50 + 0 = 150
|
|
244
|
+
// right: null
|
|
245
|
+
// top: relativeTop + contentShift = 200 + 0 = 200
|
|
246
|
+
// bottom: null
|
|
247
|
+
expect(result.position).toBe("end-top");
|
|
248
|
+
expect(result.styles.left).toBe(150);
|
|
249
|
+
expect(result.styles.right).toBe(null);
|
|
250
|
+
expect(result.styles.top).toBe(200);
|
|
251
|
+
expect(result.styles.bottom).toBe(null);
|
|
252
|
+
});
|
|
253
|
+
test("calculates position for 'end-bottom'", () => {
|
|
254
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
255
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
256
|
+
const result = calculatePosition({
|
|
189
257
|
triggerBounds,
|
|
190
258
|
flyoutBounds,
|
|
191
|
-
containerBounds,
|
|
192
259
|
position: "end-bottom",
|
|
193
260
|
rtl: false,
|
|
194
261
|
contentGap: 0,
|
|
195
262
|
contentShift: 0,
|
|
196
263
|
});
|
|
197
|
-
// relativeLeft
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
264
|
+
// left: relativeLeft + triggerWidth + contentGap = 100 + 50 + 0 = 150
|
|
265
|
+
// right: null
|
|
266
|
+
// top: relativeTop + triggerHeight - flyoutHeight + contentShift = 200 + 30 - 60 + 0 = 170
|
|
267
|
+
// bottom: relativeBottom - contentShift = 570 - 0 = 570
|
|
268
|
+
expect(result.position).toBe("end-bottom");
|
|
269
|
+
expect(result.styles.left).toBe(150);
|
|
270
|
+
expect(result.styles.right).toBe(null);
|
|
271
|
+
expect(result.styles.top).toBe(170);
|
|
272
|
+
expect(result.styles.bottom).toBe(570);
|
|
201
273
|
});
|
|
202
|
-
test("applies contentGap
|
|
274
|
+
test("applies contentGap for vertical positions", () => {
|
|
203
275
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
204
276
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
205
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
206
277
|
const top = calculatePosition({
|
|
207
278
|
triggerBounds,
|
|
208
279
|
flyoutBounds,
|
|
209
|
-
containerBounds,
|
|
210
280
|
position: "top",
|
|
211
281
|
rtl: false,
|
|
212
282
|
contentGap: 10,
|
|
213
283
|
contentShift: 0,
|
|
214
284
|
});
|
|
215
|
-
// relativeTop
|
|
216
|
-
|
|
285
|
+
// top: relativeTop - flyoutHeight - contentGap = 200 - 60 - 10 = 130
|
|
286
|
+
// bottom: relativeBottom + triggerHeight + contentGap = 570 + 30 + 10 = 610
|
|
287
|
+
expect(top.styles.top).toBe(130);
|
|
288
|
+
expect(top.styles.bottom).toBe(610);
|
|
217
289
|
const bottom = calculatePosition({
|
|
218
290
|
triggerBounds,
|
|
219
291
|
flyoutBounds,
|
|
220
|
-
containerBounds,
|
|
221
292
|
position: "bottom",
|
|
222
293
|
rtl: false,
|
|
223
294
|
contentGap: 10,
|
|
224
295
|
contentShift: 0,
|
|
225
296
|
});
|
|
226
|
-
// relativeTop
|
|
227
|
-
expect(bottom.
|
|
297
|
+
// top: relativeTop + triggerHeight + contentGap = 200 + 30 + 10 = 240
|
|
298
|
+
expect(bottom.styles.top).toBe(240);
|
|
299
|
+
});
|
|
300
|
+
test("applies contentGap for horizontal positions", () => {
|
|
301
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
302
|
+
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
228
303
|
const start = calculatePosition({
|
|
229
304
|
triggerBounds,
|
|
230
305
|
flyoutBounds,
|
|
231
|
-
containerBounds,
|
|
232
306
|
position: "start",
|
|
233
307
|
rtl: false,
|
|
234
308
|
contentGap: 10,
|
|
235
309
|
contentShift: 0,
|
|
236
310
|
});
|
|
237
|
-
// relativeLeft
|
|
238
|
-
// relativeRight
|
|
239
|
-
expect(start.
|
|
311
|
+
// left: relativeLeft - flyoutWidth - contentGap = 100 - 40 - 10 = 50
|
|
312
|
+
// right: relativeRight + triggerWidth + contentGap = 850 + 50 + 10 = 910
|
|
313
|
+
expect(start.styles.left).toBe(50);
|
|
314
|
+
expect(start.styles.right).toBe(910);
|
|
240
315
|
const end = calculatePosition({
|
|
241
316
|
triggerBounds,
|
|
242
317
|
flyoutBounds,
|
|
243
|
-
containerBounds,
|
|
244
318
|
position: "end",
|
|
245
319
|
rtl: false,
|
|
246
320
|
contentGap: 10,
|
|
247
321
|
contentShift: 0,
|
|
248
322
|
});
|
|
249
|
-
// relativeLeft
|
|
250
|
-
expect(end.
|
|
323
|
+
// left: relativeLeft + triggerWidth + contentGap = 100 + 50 + 10 = 160
|
|
324
|
+
expect(end.styles.left).toBe(160);
|
|
251
325
|
});
|
|
252
|
-
test("applies contentShift
|
|
326
|
+
test("applies contentShift for centered positions", () => {
|
|
253
327
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
254
328
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
255
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
256
329
|
const top = calculatePosition({
|
|
257
330
|
triggerBounds,
|
|
258
331
|
flyoutBounds,
|
|
259
|
-
containerBounds,
|
|
260
332
|
position: "top",
|
|
261
333
|
rtl: false,
|
|
262
334
|
contentGap: 0,
|
|
263
|
-
contentShift:
|
|
335
|
+
contentShift: 10,
|
|
264
336
|
});
|
|
265
|
-
//
|
|
266
|
-
expect(top.
|
|
267
|
-
const topStart = calculatePosition({
|
|
268
|
-
triggerBounds,
|
|
269
|
-
flyoutBounds,
|
|
270
|
-
containerBounds,
|
|
271
|
-
position: "top-start",
|
|
272
|
-
rtl: false,
|
|
273
|
-
contentGap: 0,
|
|
274
|
-
contentShift: 5,
|
|
275
|
-
});
|
|
276
|
-
// relativeLeft = 100, left = 100 + 5 = 105
|
|
277
|
-
expect(topStart.boundaries.left).toBe(105);
|
|
337
|
+
// left: relativeLeft + centerBySize(50, 40) + contentShift = 100 + 5 + 10 = 115
|
|
338
|
+
expect(top.styles.left).toBe(115);
|
|
278
339
|
const start = calculatePosition({
|
|
279
340
|
triggerBounds,
|
|
280
341
|
flyoutBounds,
|
|
281
|
-
containerBounds,
|
|
282
342
|
position: "start",
|
|
283
343
|
rtl: false,
|
|
284
344
|
contentGap: 0,
|
|
285
|
-
contentShift:
|
|
345
|
+
contentShift: 10,
|
|
286
346
|
});
|
|
287
|
-
//
|
|
288
|
-
expect(start.
|
|
347
|
+
// top: relativeTop + centerBySize(30, 60) + contentShift = 200 + (-15) + 10 = 195
|
|
348
|
+
expect(start.styles.top).toBe(195);
|
|
289
349
|
});
|
|
290
|
-
test("
|
|
350
|
+
test("applies contentShift for aligned positions", () => {
|
|
291
351
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
292
352
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
293
|
-
const
|
|
294
|
-
// In RTL, "start" should behave like "end" in LTR
|
|
295
|
-
const startRTL = calculatePosition({
|
|
296
|
-
triggerBounds,
|
|
297
|
-
flyoutBounds,
|
|
298
|
-
containerBounds,
|
|
299
|
-
position: "start",
|
|
300
|
-
rtl: true,
|
|
301
|
-
contentGap: 0,
|
|
302
|
-
contentShift: 0,
|
|
303
|
-
});
|
|
304
|
-
const endLTR = calculatePosition({
|
|
305
|
-
triggerBounds,
|
|
306
|
-
flyoutBounds,
|
|
307
|
-
containerBounds,
|
|
308
|
-
position: "end",
|
|
309
|
-
rtl: false,
|
|
310
|
-
contentGap: 0,
|
|
311
|
-
contentShift: 0,
|
|
312
|
-
});
|
|
313
|
-
expect(startRTL.boundaries.left).toBe(endLTR.boundaries.left);
|
|
314
|
-
expect(startRTL.position).toBe("end");
|
|
315
|
-
// In RTL, "top-start" should behave like "top-end" in LTR
|
|
316
|
-
const topStartRTL = calculatePosition({
|
|
353
|
+
const topStart = calculatePosition({
|
|
317
354
|
triggerBounds,
|
|
318
355
|
flyoutBounds,
|
|
319
|
-
containerBounds,
|
|
320
356
|
position: "top-start",
|
|
321
|
-
rtl:
|
|
357
|
+
rtl: false,
|
|
322
358
|
contentGap: 0,
|
|
323
|
-
contentShift:
|
|
359
|
+
contentShift: 5,
|
|
324
360
|
});
|
|
325
|
-
|
|
361
|
+
// left: relativeLeft + contentShift = 100 + 5 = 105
|
|
362
|
+
expect(topStart.styles.left).toBe(105);
|
|
363
|
+
const topEnd = calculatePosition({
|
|
326
364
|
triggerBounds,
|
|
327
365
|
flyoutBounds,
|
|
328
|
-
containerBounds,
|
|
329
366
|
position: "top-end",
|
|
330
367
|
rtl: false,
|
|
331
368
|
contentGap: 0,
|
|
332
|
-
contentShift:
|
|
369
|
+
contentShift: 5,
|
|
333
370
|
});
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const
|
|
339
|
-
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
340
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
341
|
-
const container = {
|
|
342
|
-
scrollLeft: 50,
|
|
343
|
-
scrollTop: 100,
|
|
344
|
-
clientWidth: 1000,
|
|
345
|
-
clientHeight: 800,
|
|
346
|
-
};
|
|
347
|
-
const result = calculatePosition({
|
|
371
|
+
// left: relativeLeft + triggerWidth - flyoutWidth + contentShift = 100 + 50 - 40 + 5 = 115
|
|
372
|
+
// right: relativeRight - contentShift = 850 - 5 = 845
|
|
373
|
+
expect(topEnd.styles.left).toBe(115);
|
|
374
|
+
expect(topEnd.styles.right).toBe(845);
|
|
375
|
+
const startTop = calculatePosition({
|
|
348
376
|
triggerBounds,
|
|
349
377
|
flyoutBounds,
|
|
350
|
-
|
|
351
|
-
passedContainer: container,
|
|
352
|
-
position: "top",
|
|
378
|
+
position: "start-top",
|
|
353
379
|
rtl: false,
|
|
354
380
|
contentGap: 0,
|
|
355
|
-
contentShift:
|
|
381
|
+
contentShift: 5,
|
|
356
382
|
});
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
// So left = 150 + centerBySize(50, 40) = 155
|
|
361
|
-
expect(result.boundaries.left).toBe(150 + 5);
|
|
362
|
-
});
|
|
363
|
-
test("handles window scrolling when no container is provided", () => {
|
|
364
|
-
Object.defineProperty(window, "scrollX", { value: 100, writable: true });
|
|
365
|
-
Object.defineProperty(window, "scrollY", { value: 200, writable: true });
|
|
366
|
-
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
367
|
-
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
368
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
369
|
-
const result = calculatePosition({
|
|
383
|
+
// top: relativeTop + contentShift = 200 + 5 = 205
|
|
384
|
+
expect(startTop.styles.top).toBe(205);
|
|
385
|
+
const startBottom = calculatePosition({
|
|
370
386
|
triggerBounds,
|
|
371
387
|
flyoutBounds,
|
|
372
|
-
|
|
373
|
-
position: "top",
|
|
388
|
+
position: "start-bottom",
|
|
374
389
|
rtl: false,
|
|
375
390
|
contentGap: 0,
|
|
376
|
-
contentShift:
|
|
391
|
+
contentShift: 5,
|
|
377
392
|
});
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
expect(result.boundaries.left).toBe(105);
|
|
383
|
-
Object.defineProperty(window, "scrollX", { value: 0, writable: true });
|
|
384
|
-
Object.defineProperty(window, "scrollY", { value: 0, writable: true });
|
|
393
|
+
// top: relativeTop + triggerHeight - flyoutHeight + contentShift = 200 + 30 - 60 + 5 = 175
|
|
394
|
+
// bottom: relativeBottom - contentShift = 570 - 5 = 565
|
|
395
|
+
expect(startBottom.styles.top).toBe(175);
|
|
396
|
+
expect(startBottom.styles.bottom).toBe(565);
|
|
385
397
|
});
|
|
386
|
-
test("
|
|
398
|
+
test("converts positions for RTL", () => {
|
|
387
399
|
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
388
400
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
389
|
-
|
|
390
|
-
const
|
|
401
|
+
// 'start' in RTL should behave like 'end' in LTR
|
|
402
|
+
const startRTL = calculatePosition({
|
|
391
403
|
triggerBounds,
|
|
392
404
|
flyoutBounds,
|
|
393
|
-
containerBounds,
|
|
394
405
|
position: "start",
|
|
395
|
-
rtl:
|
|
406
|
+
rtl: true,
|
|
396
407
|
contentGap: 0,
|
|
397
408
|
contentShift: 0,
|
|
398
409
|
});
|
|
399
|
-
|
|
400
|
-
// right = relativeRight + triggerWidth = 850 + 50 = 900
|
|
401
|
-
// translateX = -900
|
|
402
|
-
expect(start.styles.right).toBe("0px");
|
|
403
|
-
expect(start.styles.left).toBe(null);
|
|
404
|
-
expect(start.styles.transform).toContain("translate(-900px");
|
|
405
|
-
const end = calculatePosition({
|
|
410
|
+
const endLTR = calculatePosition({
|
|
406
411
|
triggerBounds,
|
|
407
412
|
flyoutBounds,
|
|
408
|
-
containerBounds,
|
|
409
413
|
position: "end",
|
|
410
414
|
rtl: false,
|
|
411
415
|
contentGap: 0,
|
|
412
416
|
contentShift: 0,
|
|
413
417
|
});
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
expect(end.styles.transform).toContain("translate(150px");
|
|
419
|
-
});
|
|
420
|
-
test("calculates transform correctly for top and bottom positioning", () => {
|
|
421
|
-
const triggerTop = 200;
|
|
422
|
-
const triggerHeight = 30;
|
|
423
|
-
const triggerBounds = createBounds(100, triggerTop, 50, triggerHeight);
|
|
424
|
-
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
425
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
426
|
-
const top = calculatePosition({
|
|
418
|
+
expect(startRTL.position).toBe("end");
|
|
419
|
+
expect(startRTL.styles).toEqual(endLTR.styles);
|
|
420
|
+
// 'top-start' in RTL should behave like 'top-end' in LTR
|
|
421
|
+
const topStartRTL = calculatePosition({
|
|
427
422
|
triggerBounds,
|
|
428
423
|
flyoutBounds,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
rtl: false,
|
|
424
|
+
position: "top-start",
|
|
425
|
+
rtl: true,
|
|
432
426
|
contentGap: 0,
|
|
433
427
|
contentShift: 0,
|
|
434
428
|
});
|
|
435
|
-
|
|
436
|
-
// containerBoundsBottom = 800, relativeBottom = 800 - 230 = 570
|
|
437
|
-
expect(top.styles.bottom).toBe("0px");
|
|
438
|
-
expect(top.styles.top).toBe(null);
|
|
439
|
-
expect(top.styles.transform).toBe(`translate(105px, ${triggerTop - window.innerHeight}px)`);
|
|
440
|
-
const bottom = calculatePosition({
|
|
429
|
+
const topEndLTR = calculatePosition({
|
|
441
430
|
triggerBounds,
|
|
442
431
|
flyoutBounds,
|
|
443
|
-
|
|
444
|
-
position: "bottom",
|
|
432
|
+
position: "top-end",
|
|
445
433
|
rtl: false,
|
|
446
434
|
contentGap: 0,
|
|
447
435
|
contentShift: 0,
|
|
448
436
|
});
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
expect(bottom.styles.transform).toBe(`translate(105px, ${triggerTop + triggerHeight}px)`);
|
|
454
|
-
});
|
|
455
|
-
test("handles width option '100%'", () => {
|
|
456
|
-
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
457
|
-
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
458
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
459
|
-
const result = calculatePosition({
|
|
437
|
+
expect(topStartRTL.position).toBe("top-end");
|
|
438
|
+
expect(topStartRTL.styles).toEqual(topEndLTR.styles);
|
|
439
|
+
// 'end-bottom' in RTL should behave like 'start-bottom' in LTR
|
|
440
|
+
const endBottomRTL = calculatePosition({
|
|
460
441
|
triggerBounds,
|
|
461
442
|
flyoutBounds,
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
rtl: false,
|
|
465
|
-
width: "100%",
|
|
443
|
+
position: "end-bottom",
|
|
444
|
+
rtl: true,
|
|
466
445
|
contentGap: 0,
|
|
467
446
|
contentShift: 0,
|
|
468
447
|
});
|
|
469
|
-
|
|
470
|
-
expect(result.boundaries.width).toBe(window.innerWidth - CONTAINER_OFFSET * 2);
|
|
471
|
-
expect(result.styles.width).toBe(`${window.innerWidth - CONTAINER_OFFSET * 2}px`);
|
|
472
|
-
});
|
|
473
|
-
test("handles width option 'trigger'", () => {
|
|
474
|
-
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
475
|
-
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
476
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
477
|
-
const result = calculatePosition({
|
|
448
|
+
const startBottomLTR = calculatePosition({
|
|
478
449
|
triggerBounds,
|
|
479
450
|
flyoutBounds,
|
|
480
|
-
|
|
481
|
-
position: "top",
|
|
451
|
+
position: "start-bottom",
|
|
482
452
|
rtl: false,
|
|
483
|
-
width: "trigger",
|
|
484
453
|
contentGap: 0,
|
|
485
454
|
contentShift: 0,
|
|
486
455
|
});
|
|
487
|
-
expect(
|
|
488
|
-
expect(
|
|
456
|
+
expect(endBottomRTL.position).toBe("start-bottom");
|
|
457
|
+
expect(endBottomRTL.styles).toEqual(startBottomLTR.styles);
|
|
489
458
|
});
|
|
490
|
-
test("handles
|
|
491
|
-
const triggerBounds = createBounds(
|
|
459
|
+
test("handles different viewport sizes", () => {
|
|
460
|
+
const triggerBounds = createBounds(100, 200, 50, 30);
|
|
492
461
|
const flyoutBounds = createBounds(0, 0, 40, 60);
|
|
493
|
-
|
|
494
|
-
Object.defineProperty(window, "
|
|
495
|
-
Object.defineProperty(window, "scrollY", { value: 0, writable: true });
|
|
462
|
+
Object.defineProperty(window, "innerWidth", { value: 1920, writable: true });
|
|
463
|
+
Object.defineProperty(window, "innerHeight", { value: 1080, writable: true });
|
|
496
464
|
const result = calculatePosition({
|
|
497
465
|
triggerBounds,
|
|
498
466
|
flyoutBounds,
|
|
499
|
-
|
|
500
|
-
position: "top", // Vertical position - checks horizontal overflow
|
|
467
|
+
position: "start",
|
|
501
468
|
rtl: false,
|
|
502
469
|
contentGap: 0,
|
|
503
470
|
contentShift: 0,
|
|
504
|
-
fallbackAdjustLayout: true,
|
|
505
471
|
});
|
|
506
|
-
//
|
|
507
|
-
//
|
|
508
|
-
expect(result.
|
|
509
|
-
|
|
510
|
-
test("handles fallbackAdjustLayout for vertical positions with overflow and height adjustment", () => {
|
|
511
|
-
const triggerBounds = createBounds(100, 5, 50, 30); // Very close to top
|
|
512
|
-
const flyoutBounds = createBounds(0, 0, 40, 200); // Large flyout
|
|
513
|
-
const containerBounds = createBounds(0, 0, 1000, 800);
|
|
514
|
-
Object.defineProperty(window, "scrollX", { value: 0, writable: true });
|
|
515
|
-
Object.defineProperty(window, "scrollY", { value: 0, writable: true });
|
|
516
|
-
const result = calculatePosition({
|
|
472
|
+
// relativeRight = 1920 - 150 = 1770
|
|
473
|
+
// right: relativeRight + triggerWidth + contentGap = 1770 + 50 + 0 = 1820
|
|
474
|
+
expect(result.styles.right).toBe(1820);
|
|
475
|
+
const result2 = calculatePosition({
|
|
517
476
|
triggerBounds,
|
|
518
477
|
flyoutBounds,
|
|
519
|
-
containerBounds,
|
|
520
478
|
position: "top",
|
|
521
479
|
rtl: false,
|
|
522
480
|
contentGap: 0,
|
|
523
481
|
contentShift: 0,
|
|
524
|
-
fallbackAdjustLayout: true,
|
|
525
|
-
fallbackMinHeight: "50",
|
|
526
482
|
});
|
|
527
|
-
//
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
if (result.styles.height) {
|
|
531
|
-
const height = parseInt(result.styles.height);
|
|
532
|
-
expect(height).toBeGreaterThanOrEqual(50); // fallbackMinHeight
|
|
533
|
-
}
|
|
534
|
-
}
|
|
483
|
+
// relativeBottom = 1080 - 230 = 850
|
|
484
|
+
// bottom: relativeBottom + triggerHeight + contentGap = 850 + 30 + 0 = 880
|
|
485
|
+
expect(result2.styles.bottom).toBe(880);
|
|
535
486
|
});
|
|
536
487
|
});
|