@oscarpalmer/oui 0.21.0 → 0.22.0
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/css/popover.css +9 -9
- package/dist/css/tooltip.css +20 -20
- package/dist/js/index.d.mts +46 -3
- package/dist/js/index.mjs +2536 -6
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +3 -0
- package/dist/js/internal/floatable.d.mts +2 -2
- package/dist/js/internal/floatable.mjs +38 -135
- package/dist/js/movable.d.mts +1 -1
- package/dist/js/popover.mjs +1 -1
- package/dist/js/sortable.d.mts +1 -1
- package/dist/js/tooltip.d.mts +1 -1
- package/dist/js/tooltip.mjs +95 -97
- package/package.json +13 -5
- package/src/css/mixins.scss +8 -12
- package/src/css/popover.scss +1 -1
- package/src/css/tooltip.scss +22 -22
- package/src/js/internal/floatable.ts +53 -270
- package/src/js/popover.ts +1 -1
- package/src/js/tooltip.ts +129 -131
- /package/dist/js/{movable-BEo2LbUI.d.mts → movable-BKFgoaOl.d.mts} +0 -0
package/src/css/tooltip.scss
CHANGED
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
background-color: var(--oui-absolute);
|
|
38
38
|
border-radius: 0.25rem;
|
|
39
39
|
font-size: 0.875rem;
|
|
40
|
+
pointer-events: none;
|
|
40
41
|
transition: opacity 0.125s ease-in-out;
|
|
41
|
-
transition-delay: 0s;
|
|
42
42
|
|
|
43
43
|
&::after {
|
|
44
44
|
content: '';
|
|
@@ -46,49 +46,49 @@
|
|
|
46
46
|
position: absolute;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
&[position^='above'],
|
|
50
|
-
&[position^='below'],
|
|
51
|
-
&[position^='bottom'],
|
|
52
|
-
&[position^='top'] {
|
|
49
|
+
&[oui-position^='above'],
|
|
50
|
+
&[oui-position^='below'],
|
|
51
|
+
&[oui-position^='bottom'],
|
|
52
|
+
&[oui-position^='top'] {
|
|
53
53
|
&::after {
|
|
54
54
|
width: 100%;
|
|
55
|
-
height: 0.
|
|
55
|
+
height: 0.5em;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
&[position^='above'],
|
|
60
|
-
&[position^='top'] {
|
|
59
|
+
&[oui-position^='above'],
|
|
60
|
+
&[oui-position^='top'] {
|
|
61
61
|
&::after {
|
|
62
62
|
inset: 100% 0 0;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
&[position^='below'],
|
|
67
|
-
&[position^='bottom'] {
|
|
66
|
+
&[oui-position^='below'],
|
|
67
|
+
&[oui-position^='bottom'] {
|
|
68
68
|
&::after {
|
|
69
|
-
inset: -
|
|
69
|
+
inset: -0.5em 0 0;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
&[position^='end'],
|
|
74
|
-
&[position^='left'],
|
|
75
|
-
&[position^='right'],
|
|
76
|
-
&[position^='start'] {
|
|
73
|
+
&[oui-position^='end'],
|
|
74
|
+
&[oui-position^='left'],
|
|
75
|
+
&[oui-position^='right'],
|
|
76
|
+
&[oui-position^='start'] {
|
|
77
77
|
&::after {
|
|
78
|
-
width: 0.
|
|
78
|
+
width: 0.5em;
|
|
79
79
|
height: 100%;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
&[position^='end'],
|
|
84
|
-
&[position^='right'] {
|
|
83
|
+
&[oui-position^='end'],
|
|
84
|
+
&[oui-position^='right'] {
|
|
85
85
|
&::after {
|
|
86
|
-
inset: 0 0 0 -0.
|
|
86
|
+
inset: 0 0 0 -0.5em;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
&[position^='left'],
|
|
91
|
-
&[position^='start'] {
|
|
90
|
+
&[oui-position^='left'],
|
|
91
|
+
&[oui-position^='start'] {
|
|
92
92
|
&::after {
|
|
93
93
|
inset: 0 0 0 100%;
|
|
94
94
|
}
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
|
|
98
98
|
:where([oui-tooltip-content][oui-tooltip-content-active]) {
|
|
99
99
|
opacity: 1;
|
|
100
|
-
|
|
100
|
+
pointer-events: auto;
|
|
101
101
|
}
|
|
@@ -100,7 +100,7 @@ type Options = {
|
|
|
100
100
|
defaultPosition: Position;
|
|
101
101
|
interactive: boolean;
|
|
102
102
|
positionAttribute: string;
|
|
103
|
-
|
|
103
|
+
reusable: boolean;
|
|
104
104
|
onAfter?: (active: boolean) => void;
|
|
105
105
|
};
|
|
106
106
|
|
|
@@ -114,15 +114,9 @@ type Position =
|
|
|
114
114
|
| 'end'
|
|
115
115
|
| 'end-bottom'
|
|
116
116
|
| 'end-top'
|
|
117
|
-
| 'horizontal'
|
|
118
|
-
| 'horizontal-bottom'
|
|
119
|
-
| 'horizontal-top'
|
|
120
117
|
| 'start'
|
|
121
118
|
| 'start-bottom'
|
|
122
|
-
| 'start-top'
|
|
123
|
-
| 'vertical'
|
|
124
|
-
| 'vertical-end'
|
|
125
|
-
| 'vertical-start';
|
|
119
|
+
| 'start-top';
|
|
126
120
|
|
|
127
121
|
type State = {
|
|
128
122
|
active: Set<Floatable>;
|
|
@@ -139,7 +133,7 @@ function activate(floatable: Floatable): void {
|
|
|
139
133
|
|
|
140
134
|
floatable.options.content.hidden = false;
|
|
141
135
|
|
|
142
|
-
|
|
136
|
+
setPosition(floatable);
|
|
143
137
|
}
|
|
144
138
|
|
|
145
139
|
function closeAbove(element: HTMLElement): void {
|
|
@@ -185,166 +179,25 @@ function closeNonInteractive(state: State): void {
|
|
|
185
179
|
export function deactivate(floatable: Floatable): void {
|
|
186
180
|
floatable.active = false;
|
|
187
181
|
|
|
188
|
-
floatable.options.
|
|
182
|
+
if (!floatable.options.reusable) {
|
|
183
|
+
floatable.options.content.hidden = true;
|
|
189
184
|
|
|
190
|
-
|
|
185
|
+
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
186
|
+
}
|
|
191
187
|
|
|
192
188
|
floatable.options.onAfter?.(false);
|
|
193
189
|
}
|
|
194
190
|
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
anchor: DOMRect,
|
|
198
|
-
top: number,
|
|
199
|
-
left: number,
|
|
200
|
-
): Position | undefined {
|
|
201
|
-
switch (position) {
|
|
202
|
-
case 'horizontal':
|
|
203
|
-
case 'horizontal-bottom':
|
|
204
|
-
case 'horizontal-top':
|
|
205
|
-
return position.replace('horizontal', left >= anchor.right ? 'right' : 'left') as Position;
|
|
206
|
-
|
|
207
|
-
case 'vertical':
|
|
208
|
-
case 'vertical-end':
|
|
209
|
-
case 'vertical-start':
|
|
210
|
-
return position.replace('vertical', top >= anchor.bottom ? 'bottom' : 'top') as Position;
|
|
211
|
-
|
|
212
|
-
default:
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function getMargin(): number {
|
|
218
|
-
try {
|
|
219
|
-
const fontsize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
220
|
-
|
|
221
|
-
if (Number.isNaN(fontsize)) {
|
|
222
|
-
return 5;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const margin = fontsize / 2;
|
|
191
|
+
function getAnchorName(): string {
|
|
192
|
+
index += 1;
|
|
226
193
|
|
|
227
|
-
|
|
228
|
-
} catch {
|
|
229
|
-
return 5;
|
|
230
|
-
}
|
|
194
|
+
return `--oui-floatable-anchor-${index}`;
|
|
231
195
|
}
|
|
232
196
|
|
|
233
197
|
function getState(): State {
|
|
234
198
|
return (window as unknown as FloatableWindow)._oscarpalmer_oui_floatable;
|
|
235
199
|
}
|
|
236
200
|
|
|
237
|
-
function getX(anchor: DOMRect, content: DOMRect, position: Position, margin: number): number {
|
|
238
|
-
if (position === 'above' || position === 'below' || position === 'vertical') {
|
|
239
|
-
const center = anchor.left + anchor.width / 2;
|
|
240
|
-
const width = content.width / 2;
|
|
241
|
-
|
|
242
|
-
if (center + width + margin >= document.body.clientWidth) {
|
|
243
|
-
return document.body.clientWidth - content.width - margin / 2;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (center - width - margin <= 0) {
|
|
247
|
-
return margin / 2;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return center - width;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (position.startsWith('end')) {
|
|
254
|
-
return anchor.right;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (position.startsWith('start')) {
|
|
258
|
-
return anchor.left - content.width;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (position.endsWith('end')) {
|
|
262
|
-
return anchor.right - content.width - margin <= 0 ? margin / 2 : anchor.right - content.width;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (position.endsWith('start')) {
|
|
266
|
-
if (anchor.left + content.width + margin >= document.body.clientWidth) {
|
|
267
|
-
return document.body.clientWidth - content.width - margin / 2;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return anchor.left - margin <= 0 ? margin / 2 : anchor.left;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (!position.startsWith('horizontal')) {
|
|
274
|
-
return 0;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (anchor.right + content.width + margin >= document.body.clientWidth) {
|
|
278
|
-
return anchor.left - content.width;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return anchor.right;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function getY(
|
|
285
|
-
anchor: DOMRect,
|
|
286
|
-
content: DOMRect,
|
|
287
|
-
position: Position,
|
|
288
|
-
margin: number,
|
|
289
|
-
preferAbove: boolean,
|
|
290
|
-
): number {
|
|
291
|
-
if (position === 'end' || position === 'start' || position === 'horizontal') {
|
|
292
|
-
const center = anchor.top + anchor.height / 2;
|
|
293
|
-
const height = content.height / 2;
|
|
294
|
-
|
|
295
|
-
if (center + height + margin >= document.body.clientHeight) {
|
|
296
|
-
return document.body.clientHeight - content.height - margin / 2;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (center - height - margin <= 0) {
|
|
300
|
-
return margin / 2;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
return center - height;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (position.startsWith('above')) {
|
|
307
|
-
return anchor.top - content.height;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (position.startsWith('below')) {
|
|
311
|
-
return anchor.bottom;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (position.endsWith('bottom')) {
|
|
315
|
-
return anchor.bottom - content.height - margin <= 0
|
|
316
|
-
? margin / 2
|
|
317
|
-
: anchor.bottom - content.height;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (position.endsWith('top')) {
|
|
321
|
-
return anchor.top + content.height + margin >= document.body.clientHeight
|
|
322
|
-
? document.body.clientHeight - content.height - margin
|
|
323
|
-
: anchor.top;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (!position.startsWith('vertical')) {
|
|
327
|
-
return 0;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (preferAbove) {
|
|
331
|
-
if (
|
|
332
|
-
anchor.top - content.height - margin <= 0 &&
|
|
333
|
-
anchor.bottom + content.height + margin <= document.body.clientHeight
|
|
334
|
-
) {
|
|
335
|
-
return anchor.bottom;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return anchor.top - content.height;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (anchor.bottom + content.height + margin >= document.body.clientHeight) {
|
|
342
|
-
return anchor.top - content.height;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
return anchor.bottom;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
201
|
function initialize(floatable: Floatable): void {
|
|
349
202
|
const {anchor, content, interactive} = floatable.options;
|
|
350
203
|
|
|
@@ -353,9 +206,13 @@ function initialize(floatable: Floatable): void {
|
|
|
353
206
|
content.setAttribute(ATTRIBUTE_CONTENT, '');
|
|
354
207
|
}
|
|
355
208
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
209
|
+
const anchorName = getAnchorName();
|
|
210
|
+
|
|
211
|
+
anchor.style.anchorName = anchorName;
|
|
212
|
+
|
|
213
|
+
content.style.position = 'absolute';
|
|
214
|
+
content.style.positionAnchor = anchorName;
|
|
215
|
+
content.style.positionTry = 'normal flip-start';
|
|
359
216
|
|
|
360
217
|
const state = getState();
|
|
361
218
|
|
|
@@ -411,20 +268,22 @@ function onKeyDown(event: KeyboardEvent): void {
|
|
|
411
268
|
}
|
|
412
269
|
}
|
|
413
270
|
|
|
414
|
-
function
|
|
415
|
-
position: Position
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
let actual: Position | undefined;
|
|
422
|
-
|
|
423
|
-
if (/^(horizontal|vertical)/.test(position)) {
|
|
424
|
-
actual = getAttribute(position, anchor, top, left);
|
|
271
|
+
function setPosition(floatable: Floatable): void {
|
|
272
|
+
let position: Position =
|
|
273
|
+
(floatable.options.anchor.getAttribute(floatable.options.positionAttribute) as Position) ??
|
|
274
|
+
floatable.options.defaultPosition;
|
|
275
|
+
|
|
276
|
+
if (AREAS[position] == null) {
|
|
277
|
+
position = floatable.options.defaultPosition;
|
|
425
278
|
}
|
|
426
279
|
|
|
427
|
-
|
|
280
|
+
const area = AREAS[position];
|
|
281
|
+
|
|
282
|
+
floatable.options.content.style.positionArea = area;
|
|
283
|
+
|
|
284
|
+
floatable.options.content.setAttribute(ATTRIBUTE_POSITION, POSITIONS[area]);
|
|
285
|
+
|
|
286
|
+
floatable.options.onAfter?.(true);
|
|
428
287
|
}
|
|
429
288
|
|
|
430
289
|
function stop(floatable: Floatable): void {
|
|
@@ -456,117 +315,41 @@ function toggle(anchor: HTMLElement): void {
|
|
|
456
315
|
floatable.toggle(!active);
|
|
457
316
|
}
|
|
458
317
|
|
|
459
|
-
function updatePosition(floatable: Floatable): void {
|
|
460
|
-
let position: Position =
|
|
461
|
-
(floatable.options.anchor
|
|
462
|
-
.getAttribute(floatable.options.positionAttribute)
|
|
463
|
-
?.trim() as Position) ?? floatable.options.defaultPosition;
|
|
464
|
-
|
|
465
|
-
if (!POSITIONS.has(position as Position)) {
|
|
466
|
-
position = floatable.options.defaultPosition;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const margin = getMargin();
|
|
470
|
-
|
|
471
|
-
let previousAnchor: DOMRect;
|
|
472
|
-
let previousContent: DOMRect;
|
|
473
|
-
|
|
474
|
-
let calculated = false;
|
|
475
|
-
let runOnAfter = false;
|
|
476
|
-
|
|
477
|
-
function run(): void {
|
|
478
|
-
const anchor = floatable.options.anchor.getBoundingClientRect();
|
|
479
|
-
const content = floatable.options.content.getBoundingClientRect();
|
|
480
|
-
|
|
481
|
-
if (calculated) {
|
|
482
|
-
if (previousAnchor != null && previousContent != null) {
|
|
483
|
-
if (
|
|
484
|
-
PROPERTIES.every(property => anchor[property] === previousAnchor[property]) &&
|
|
485
|
-
PROPERTIES.every(property => content[property] === previousContent[property])
|
|
486
|
-
) {
|
|
487
|
-
floatable.frame = requestAnimationFrame(run);
|
|
488
|
-
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
} else {
|
|
493
|
-
calculated = true;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
update(anchor, content);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function update(anchor: DOMRect, content: DOMRect): void {
|
|
500
|
-
previousAnchor = anchor;
|
|
501
|
-
previousContent = content;
|
|
502
|
-
|
|
503
|
-
const left = getX(anchor, content, position, margin);
|
|
504
|
-
const top = getY(anchor, content, position, margin, floatable.options.preferAbove);
|
|
505
|
-
|
|
506
|
-
setAttribute(position, anchor, floatable.options.content, top, left);
|
|
507
|
-
|
|
508
|
-
if (top + content.height > window.innerHeight) {
|
|
509
|
-
floatable.options.content.style.height = `${window.innerHeight - top}px`;
|
|
510
|
-
} else {
|
|
511
|
-
floatable.options.content.style.height = '';
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
if (left + content.width > window.innerWidth) {
|
|
515
|
-
floatable.options.content.style.width = `${window.innerWidth - left}px`;
|
|
516
|
-
} else {
|
|
517
|
-
floatable.options.content.style.width = '';
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// floatable.options.content.style.inset = `${top}px auto auto ${left}px`;
|
|
521
|
-
floatable.options.content.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
|
522
|
-
|
|
523
|
-
floatable.frame = requestAnimationFrame(run);
|
|
524
|
-
|
|
525
|
-
if (!runOnAfter) {
|
|
526
|
-
runOnAfter = true;
|
|
527
|
-
|
|
528
|
-
floatable.options.onAfter?.(true);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
floatable.frame = requestAnimationFrame(run);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
318
|
//
|
|
536
319
|
|
|
320
|
+
const AREAS: Record<Position, string> = {
|
|
321
|
+
above: 'block-start',
|
|
322
|
+
'above-end': 'start span-start',
|
|
323
|
+
'above-start': 'start span-end',
|
|
324
|
+
below: 'block-end',
|
|
325
|
+
'below-end': 'end span-start',
|
|
326
|
+
'below-start': 'end span-end',
|
|
327
|
+
end: 'center end',
|
|
328
|
+
'end-bottom': 'span-start end',
|
|
329
|
+
'end-top': 'span-end end',
|
|
330
|
+
start: 'center start',
|
|
331
|
+
'start-bottom': 'span-start start',
|
|
332
|
+
'start-top': 'span-end start',
|
|
333
|
+
};
|
|
334
|
+
|
|
537
335
|
const ATTRIBUTE_ANCHOR = 'oui-floatable-anchor';
|
|
538
336
|
|
|
539
337
|
const ATTRIBUTE_CONTENT = 'oui-floatable-content';
|
|
540
338
|
|
|
339
|
+
const ATTRIBUTE_POSITION = 'oui-position';
|
|
340
|
+
|
|
541
341
|
const INSERT_AFTEREND = 'afterend';
|
|
542
342
|
|
|
543
|
-
const POSITIONS
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
'above-start',
|
|
547
|
-
'below',
|
|
548
|
-
'below-end',
|
|
549
|
-
'below-start',
|
|
550
|
-
'end',
|
|
551
|
-
'end-bottom',
|
|
552
|
-
'end-top',
|
|
553
|
-
'horizontal',
|
|
554
|
-
'horizontal-bottom',
|
|
555
|
-
'horizontal-top',
|
|
556
|
-
'start',
|
|
557
|
-
'start-bottom',
|
|
558
|
-
'start-top',
|
|
559
|
-
'vertical',
|
|
560
|
-
'vertical-end',
|
|
561
|
-
'vertical-start',
|
|
562
|
-
]);
|
|
563
|
-
|
|
564
|
-
const PROPERTIES: (keyof DOMRect)[] = ['bottom', 'left', 'right', 'top'];
|
|
343
|
+
const POSITIONS = Object.fromEntries(
|
|
344
|
+
Object.entries(AREAS).map(([position, area]) => [area, position]),
|
|
345
|
+
) as Record<string, Position>;
|
|
565
346
|
|
|
566
347
|
const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
567
348
|
|
|
568
349
|
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
569
350
|
|
|
351
|
+
let index = 0;
|
|
352
|
+
|
|
570
353
|
//
|
|
571
354
|
|
|
572
355
|
if ((window as unknown as FloatableWindow)._oscarpalmer_oui_floatable == null) {
|
package/src/js/popover.ts
CHANGED
|
@@ -52,7 +52,7 @@ export class OuiPopoverElement extends HTMLElement {
|
|
|
52
52
|
defaultPosition: 'below-start',
|
|
53
53
|
interactive: true,
|
|
54
54
|
positionAttribute: 'position',
|
|
55
|
-
|
|
55
|
+
reusable: false,
|
|
56
56
|
onAfter: (active: boolean): void => {
|
|
57
57
|
if (active) {
|
|
58
58
|
focus(content);
|