@aurodesignsystem/auro-library 2.7.0 → 2.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Semantic Release Automated Changelog
2
2
 
3
+ # [2.8.0](https://github.com/AlaskaAirlines/auro-library/compare/v2.7.0...v2.8.0) (2024-09-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * add runtime script for Floating UI [#65](https://github.com/AlaskaAirlines/auro-library/issues/65) ([e180fcb](https://github.com/AlaskaAirlines/auro-library/commit/e180fcb319e9ab6673765041b5a96057e562bd60))
9
+
3
10
  # [2.7.0](https://github.com/AlaskaAirlines/auro-library/compare/v2.6.3...v2.7.0) (2024-08-21)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurodesignsystem/auro-library",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "This repository holds shared scripts, utilities, and workflows utilized across repositories along the Auro Design System.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,141 @@
1
+ /* eslint-disable line-comment-position, no-inline-comments */
2
+
3
+ import {computePosition, offset, autoPlacement, flip} from '@floating-ui/dom';
4
+
5
+ export default class AuroFloatingUI {
6
+ bibUpdate(element) {
7
+ this.position(element, element.trigger, element.bib);
8
+ }
9
+
10
+ position(element, referenceEl, floatingEl) {
11
+ const middleware = [offset(element.floaterConfig.offset || 0)];
12
+
13
+ if (element.floaterConfig.flip) {
14
+ middleware.push(flip());
15
+ }
16
+
17
+ if (element.floaterConfig.autoPlacement) {
18
+ middleware.push(autoPlacement());
19
+ }
20
+
21
+ computePosition(referenceEl, floatingEl, {
22
+ placement: element.floaterConfig.placement || 'bottom',
23
+ middleware: middleware || []
24
+ }).then(({x, y}) => { // eslint-disable-line id-length
25
+ Object.assign(floatingEl.style, {
26
+ left: `${x}px`,
27
+ top: `${y}px`,
28
+ });
29
+ });
30
+ }
31
+
32
+ showBib(element) {
33
+ if (!element.disabled && !element.isPopoverVisible) {
34
+ // First, close any other dropdown that is already open
35
+ if (document.expandedAuroDropdown) {
36
+ // document.expandedAuroDropdown.hideBib();
37
+ this.hideBib(document.expandedAuroDropdown);
38
+ }
39
+
40
+ document.expandedAuroDropdown = this;
41
+
42
+ // Then, show this dropdown
43
+ element.bib.style.display = 'block';
44
+ this.bibUpdate(element);
45
+ element.isPopoverVisible = true; // does Floating UI already surface this?
46
+ element.trigger.setAttribute('aria-expanded', true);
47
+
48
+ // wrap this so we can clean it up when the bib is hidden
49
+ // document.querySelector('body').addEventListener('click', (evt) => {
50
+ // if (!evt.composedPath().includes(this)) {
51
+ // this.hideBib();
52
+ // }
53
+ // });
54
+ if (!element.noHideOnThisFocusLoss && !element.hasAttribute('noHideOnThisFocusLoss')) {
55
+ document.activeElement.addEventListener('focusout', () => {
56
+ if (document.activeElement !== document.querySelector('body') && !element.contains(document.activeElement)) {
57
+ this.hideBib(element);
58
+ }
59
+ });
60
+
61
+ document.querySelector('body').addEventListener('click', (evt) => {
62
+ if (!evt.composedPath().includes(element)) {
63
+ this.hideBib(element);
64
+ }
65
+ });
66
+ }
67
+ }
68
+ }
69
+
70
+ hideBib(element) {
71
+ if (element.isPopoverVisible && !element.disabled && !element.noToggle) { // do we really want noToggle here?
72
+ element.bib.style.display = ''; // should this be unset or none?
73
+ element.isPopoverVisible = false;
74
+ element.trigger.setAttribute('aria-expanded', false);
75
+ }
76
+ }
77
+
78
+ configure(element) {
79
+ element.trigger = element.shadowRoot.querySelector('#trigger');
80
+ element.bib = element.shadowRoot.querySelector('#bib');
81
+
82
+ element.trigger.addEventListener('click', (event) => this.handleEvent(event, element));
83
+ element.trigger.addEventListener('mouseenter', (event) => this.handleEvent(event, element));
84
+ element.trigger.addEventListener('mouseleave', (event) => this.handleEvent(event, element));
85
+ element.trigger.addEventListener('focus', (event) => this.handleEvent(event, element));
86
+ element.trigger.addEventListener('blur', (event) => this.handleEvent(event, element));
87
+ }
88
+
89
+ handleClick(element) {
90
+ if (this.isPopoverVisible) {
91
+ this.hideBib(element);
92
+ } else {
93
+ this.showBib(element);
94
+ }
95
+
96
+ // should this be left in dropdown?
97
+ const event = new CustomEvent('auroDropdown-triggerClick', {
98
+ composed: true,
99
+ details: {
100
+ expanded: this.isPopoverVisible
101
+ }
102
+ });
103
+
104
+ element.dispatchEvent(event);
105
+ }
106
+
107
+ handleEvent(event, element) {
108
+ if (!element.disableEventShow) {
109
+ switch (event.type) {
110
+ case 'mouseenter':
111
+ if (element.hoverToggle) {
112
+ this.showBib(element);
113
+ }
114
+ break;
115
+ case 'mouseleave':
116
+ if (element.hoverToggle) {
117
+ this.hideBib(element);
118
+ }
119
+ break;
120
+ case 'focus':
121
+ if (element.focusShow) {
122
+ // this needs to better handle clicking that gives focus - currently it shows and then immediately hides the bib
123
+ this.showBib(element);
124
+ }
125
+ break;
126
+ case 'blur':
127
+ // this likely needs to be improved to handle focus within the bib for datepicker
128
+ if (!element.noHideOnThisFocusLoss && !element.hasAttribute('noHideOnThisFocusLoss')) { // why do we have to do both here?
129
+ this.hideBib(element);
130
+ }
131
+ break;
132
+ case 'click':
133
+ this.handleClick(element);
134
+ break;
135
+ default:
136
+ // do nothing
137
+ // add cases for show and toggle by keyboard space and enter key - maybe this is handled already?
138
+ }
139
+ }
140
+ }
141
+ }