blue-web 1.20.0 → 1.21.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/dist/js/odometer.bundle.js +1 -1
- package/dist/js/odometer.d.ts +13 -0
- package/dist/js/odometer.js +38 -3
- package/dist/js/select-list.bundle.js +1 -1
- package/dist/js/select-list.d.ts +19 -4
- package/dist/js/select-list.js +91 -24
- package/dist/merged.scss +99 -222
- package/dist/style.css +94 -78
- package/dist/style.css.map +1 -1
- package/dist/style.min.css +4 -4
- package/dist/style.scss +2 -1
- package/dist/styles/_action-menu.scss +1 -1
- package/dist/styles/_anchor.scss +6 -0
- package/dist/styles/_bootstrap-variables.scss +1 -0
- package/dist/styles/_bootstrap.scss +2 -3
- package/dist/styles/_buttons.scss +10 -0
- package/dist/styles/_devexpress.scss +1 -1
- package/dist/styles/_general.scss +12 -31
- package/dist/styles/_intro.scss +22 -0
- package/dist/styles/_layout.scss +13 -9
- package/dist/styles/_menu-item.scss +7 -176
- package/dist/styles/_scrollspy.scss +8 -1
- package/dist/styles/_utils.scss +14 -0
- package/dist/styles/_variables.scss +1 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var
|
|
1
|
+
(()=>{"use strict";var e={};function t(e,t,i){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var i=t.call(e,"string");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}e.d=(t,i)=>{for(var n in i)e.o(i,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:i[n]})},e.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);class i extends HTMLElement{static get observedAttributes(){return["value","max"]}constructor(){super(),t(this,"_initialized",!1),t(this,"_resetTimer",null),this.attachShadow({mode:"open"})}connectedCallback(){this._initialized||(this.setup(),this._initialized=!0,this.updateValue(this.value))}setup(){const e=document.createElement("style");e.textContent="\n :host {\n display: inline-flex;\n min-width: 1em;\n height: 1em;\n text-align: center;\n overflow: hidden;\n line-height: 1em;\n }\n .numbers {\n display: flex;\n flex-direction: column;\n transition: transform var(--bl-odometer-duration, 0.4s) cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n .numbers span {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 1em;\n }";const t=document.createElement("span");t.classList.add("numbers"),t.setAttribute("aria-hidden","true"),this.shadowRoot.append(e,t),this.wrapper=t,this.rebuildNumbers()}rebuildNumbers(){this.wrapper.innerHTML="";const e=this.max;for(let t=0;t<=e;t++){const e=document.createElement("span");e.textContent=String(t),this.wrapper.appendChild(e)}const t=document.createElement("span");t.textContent="".concat(e,"+"),this.wrapper.appendChild(t),this._initialized&&this.updateValue(this.value)}attributeChangedCallback(e,t,i){if(i!==t&&this._initialized)if("value"===e){const e=parseInt(null!=t?t:"0",10)||0,n=parseInt(null!=i?i:"0",10)||0;this.applyChangeState(e,n),this.updateValue(n)}else"max"===e&&this.rebuildNumbers()}updateValue(e){const t=this.max,i=e>t?t+1:Math.max(0,e),n=this.wrapper.getBoundingClientRect().height||16;this.wrapper.style.transform="translateY(-".concat(i*n,"px)");const r=e>t?"".concat(t,"+"):"".concat(e);this.setAttribute("aria-label",r)}clearResetTimer(){null!==this._resetTimer&&(clearTimeout(this._resetTimer),this._resetTimer=null)}scheduleResetChange(){this.clearResetTimer(),this._resetTimer=window.setTimeout(()=>{this.removeAttribute("data-change"),this._resetTimer=null},3e3)}applyChangeState(e,t){t>e?(this.setAttribute("data-change","up"),this.scheduleResetChange()):t<e&&(this.setAttribute("data-change","down"),this.scheduleResetChange())}set value(e){this.value!==e&&(this.setAttribute("value",String(e)),this._initialized&&this.dispatchEvent(new CustomEvent("change",{detail:{value:e},bubbles:!0,composed:!0})))}get value(){return parseInt(this.getAttribute("value")||"0",10)||0}set max(e){this.setAttribute("max",String(e))}get max(){return parseInt(this.getAttribute("max")||"9",10)||9}}customElements.get("bl-odometer")||customElements.define("bl-odometer",i)})();
|
package/dist/js/odometer.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Odometer web component for animated number display
|
|
3
|
+
*
|
|
4
|
+
* @element bl-odometer
|
|
5
|
+
* @attr {number} value - Current value to display
|
|
6
|
+
* @attr {number} max - Maximum value before showing "+"
|
|
7
|
+
* @fires change - Fired when value changes
|
|
8
|
+
* @cssprop --bl-odometer-duration - Transition duration for number animation (default: 0.4s)
|
|
9
|
+
*/
|
|
1
10
|
declare class Odometer extends HTMLElement {
|
|
2
11
|
private wrapper;
|
|
3
12
|
private _initialized;
|
|
13
|
+
private _resetTimer;
|
|
4
14
|
static get observedAttributes(): string[];
|
|
5
15
|
constructor();
|
|
6
16
|
connectedCallback(): void;
|
|
@@ -8,6 +18,9 @@ declare class Odometer extends HTMLElement {
|
|
|
8
18
|
private rebuildNumbers;
|
|
9
19
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
10
20
|
private updateValue;
|
|
21
|
+
private clearResetTimer;
|
|
22
|
+
private scheduleResetChange;
|
|
23
|
+
private applyChangeState;
|
|
11
24
|
set value(value: number);
|
|
12
25
|
get value(): number;
|
|
13
26
|
set max(value: number);
|
package/dist/js/odometer.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
2
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
+
/**
|
|
5
|
+
* Odometer web component for animated number display
|
|
6
|
+
*
|
|
7
|
+
* @element bl-odometer
|
|
8
|
+
* @attr {number} value - Current value to display
|
|
9
|
+
* @attr {number} max - Maximum value before showing "+"
|
|
10
|
+
* @fires change - Fired when value changes
|
|
11
|
+
* @cssprop --bl-odometer-duration - Transition duration for number animation (default: 0.4s)
|
|
12
|
+
*/
|
|
4
13
|
class Odometer extends HTMLElement {
|
|
5
14
|
static get observedAttributes() {
|
|
6
15
|
return ["value", "max"];
|
|
@@ -8,6 +17,7 @@ class Odometer extends HTMLElement {
|
|
|
8
17
|
constructor() {
|
|
9
18
|
super();
|
|
10
19
|
_defineProperty(this, "_initialized", false);
|
|
20
|
+
_defineProperty(this, "_resetTimer", null);
|
|
11
21
|
this.attachShadow({
|
|
12
22
|
mode: "open"
|
|
13
23
|
});
|
|
@@ -22,7 +32,7 @@ class Odometer extends HTMLElement {
|
|
|
22
32
|
}
|
|
23
33
|
setup() {
|
|
24
34
|
const style = document.createElement("style");
|
|
25
|
-
style.textContent = /* CSS */"\n :host {\n display: inline-flex;\n min-width: 1em;\n height: 1em;\n text-align: center;\n overflow: hidden;\n line-height: 1em;\n
|
|
35
|
+
style.textContent = /* CSS */"\n :host {\n display: inline-flex;\n min-width: 1em;\n height: 1em;\n text-align: center;\n overflow: hidden;\n line-height: 1em;\n }\n .numbers {\n display: flex;\n flex-direction: column;\n transition: transform var(--bl-odometer-duration, 0.4s) cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n .numbers span {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 1em;\n }";
|
|
26
36
|
const wrapper = document.createElement("span");
|
|
27
37
|
wrapper.classList.add("numbers");
|
|
28
38
|
wrapper.setAttribute("aria-hidden", "true");
|
|
@@ -50,7 +60,10 @@ class Odometer extends HTMLElement {
|
|
|
50
60
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
51
61
|
if (newValue !== oldValue && this._initialized) {
|
|
52
62
|
if (name === "value") {
|
|
53
|
-
|
|
63
|
+
const prev = parseInt(oldValue !== null && oldValue !== void 0 ? oldValue : "0", 10) || 0;
|
|
64
|
+
const next = parseInt(newValue !== null && newValue !== void 0 ? newValue : "0", 10) || 0;
|
|
65
|
+
this.applyChangeState(prev, next);
|
|
66
|
+
this.updateValue(next);
|
|
54
67
|
} else if (name === "max") {
|
|
55
68
|
this.rebuildNumbers();
|
|
56
69
|
}
|
|
@@ -64,12 +77,34 @@ class Odometer extends HTMLElement {
|
|
|
64
77
|
const displayValue = value > max ? "".concat(max, "+") : "".concat(value);
|
|
65
78
|
this.setAttribute("aria-label", displayValue);
|
|
66
79
|
}
|
|
80
|
+
clearResetTimer() {
|
|
81
|
+
if (this._resetTimer !== null) {
|
|
82
|
+
clearTimeout(this._resetTimer);
|
|
83
|
+
this._resetTimer = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
scheduleResetChange() {
|
|
87
|
+
this.clearResetTimer();
|
|
88
|
+
const delay = 3000;
|
|
89
|
+
this._resetTimer = window.setTimeout(() => {
|
|
90
|
+
this.removeAttribute("data-change");
|
|
91
|
+
this._resetTimer = null;
|
|
92
|
+
}, delay);
|
|
93
|
+
}
|
|
94
|
+
applyChangeState(previous, next) {
|
|
95
|
+
if (next > previous) {
|
|
96
|
+
this.setAttribute("data-change", "up");
|
|
97
|
+
this.scheduleResetChange();
|
|
98
|
+
} else if (next < previous) {
|
|
99
|
+
this.setAttribute("data-change", "down");
|
|
100
|
+
this.scheduleResetChange();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
67
103
|
set value(value) {
|
|
68
104
|
const current = this.value;
|
|
69
105
|
if (current !== value) {
|
|
70
106
|
this.setAttribute("value", String(value));
|
|
71
107
|
if (this._initialized) {
|
|
72
|
-
this.updateValue(value);
|
|
73
108
|
this.dispatchEvent(new CustomEvent("change", {
|
|
74
109
|
detail: {
|
|
75
110
|
value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";class t extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML='<slot style="border-radius: inherit"></slot>',this.activeIndex=-1,this.items=[],this.inputElement=null}connectedCallback(){this.setAttribute("role","listbox"),this.tabIndex=-1,this.updateItems();const
|
|
1
|
+
(()=>{"use strict";var t={};function e(t,e,i){return(e=function(t){var e=function(t){if("object"!=typeof t||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,"string");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}t.d=(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},t.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);class i extends Event{constructor(t,e){super(i.eventName,{bubbles:!0,composed:!0}),this.index=t,this.item=e}}e(i,"eventName","bl-select");class s extends HTMLElement{constructor(){super(),e(this,"handleChildrenChanged",()=>{var t;const e=null===(t=this.items[this.activeIndex])||void 0===t?void 0:t.id;if(this.updateItems(),e){const t=this.items.findIndex(t=>t.id===e);this.activeIndex=t>=0?t:-1}else this.activeIndex=-1;this.updateActiveItem()}),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML='<slot style="border-radius: inherit"></slot>',this.activeIndex=-1,this.items=[],this.inputElement=null,this.slotElement=null,this.observer=null}get activeClass(){return this.getAttribute("active-class")||"active"}connectedCallback(){var t,e;this.setAttribute("role","listbox"),this.tabIndex=-1,this.updateItems(),this.syncActiveIndexFromDataSelected(),this.updateActiveItem();const i=this.getAttribute("for");this.inputElement=i?document.getElementById(i):null,this.inputElement&&(this.inputElement.setAttribute("role","combobox"),this.inputElement.setAttribute("aria-controls",this.id),this.inputElement.setAttribute("aria-expanded","true"),this.inputElement.addEventListener("keydown",this.onKeyDown.bind(this))),this.addEventListener("keydown",this.onKeyDown.bind(this)),this.addEventListener("click",t=>{const e=t.target instanceof Element?t.target.closest("[data-select-list-index]"):null;if(e&&e.hasAttribute("data-select-list-index")){const t=Number(e.getAttribute("data-select-list-index"));this.select(t)}}),this.observer=new MutationObserver(t=>{t.some(t=>"childList"===t.type)&&this.handleChildrenChanged(),t.some(t=>"attributes"===t.type&&"data-selected"===t.attributeName)&&(this.syncActiveIndexFromDataSelected(),this.updateActiveItem())}),this.observer.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-selected"]}),this.slotElement=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("slot"),null===(e=this.slotElement)||void 0===e||e.addEventListener("slotchange",this.handleChildrenChanged)}disconnectedCallback(){var t,e;null===(t=this.observer)||void 0===t||t.disconnect(),this.observer=null,null===(e=this.slotElement)||void 0===e||e.removeEventListener("slotchange",this.handleChildrenChanged)}syncActiveIndexFromDataSelected(){const t=this.items.findIndex(t=>t.hasAttribute("data-selected"));t>=0&&(this.activeIndex=t)}updateItems(){const t=["button:not([disabled])","a[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])','[role="option"]'].join(", ");this.items=Array.from(this.querySelectorAll(t)),this.items.forEach((t,e)=>{t.hasAttribute("id")||t.setAttribute("id","".concat(this.id,"-option-").concat(e)),t.setAttribute("data-select-list-index",e.toString()),t.setAttribute("aria-selected","false"),t.setAttribute("role","option"),t.tabIndex=-1})}onKeyDown(t){if(this.items.length)if("ArrowDown"===t.key)t.preventDefault(),this.activeIndex=(this.activeIndex+1)%this.items.length,this.updateActiveItem();else if("ArrowUp"===t.key)t.preventDefault(),this.activeIndex=(this.activeIndex-1+this.items.length)%this.items.length,this.updateActiveItem();else if("Enter"===t.key&&this.activeIndex>=0){t.preventDefault();const e=this.items[this.activeIndex];null==e||e.click()}}updateActiveItem(){const t=this.activeClass.split(" ");this.items.forEach((e,i)=>{const s=i===this.activeIndex;t.forEach(t=>{e.classList.toggle(t,s)}),e.setAttribute("aria-selected",s.toString())});const e=this.items[this.activeIndex];e&&this.inputElement?(this.inputElement.setAttribute("aria-activedescendant",e.id),e.scrollIntoView({block:"nearest"})):this.inputElement&&this.inputElement.removeAttribute("aria-activedescendant")}select(t){this.activeIndex=t,this.items.forEach(t=>t.removeAttribute("data-selected"));const e=this.items[t];e&&(e.setAttribute("data-selected",""),this.dispatchEvent(new i(t,e)),this.updateActiveItem())}}customElements.get("bl-select-list")||customElements.define("bl-select-list",s)})();
|
package/dist/js/select-list.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
declare class BlSelectEvent extends Event {
|
|
2
|
+
static readonly eventName = "bl-select";
|
|
3
|
+
readonly index: number;
|
|
4
|
+
readonly item: HTMLElement;
|
|
5
|
+
constructor(index: number, item: HTMLElement);
|
|
6
|
+
}
|
|
1
7
|
/**
|
|
2
8
|
* A Web Component that provides a keyboard-accessible selectable list, typically used for dropdowns or autocomplete lists.
|
|
3
9
|
* Together with `popover` and CSS Anchoring, it's also useful to create a dropdown list.
|
|
@@ -5,22 +11,29 @@
|
|
|
5
11
|
*
|
|
6
12
|
* The Web Component will automatically set attributes for accessibility.
|
|
7
13
|
*
|
|
8
|
-
* @element
|
|
14
|
+
* @element bl-select-list
|
|
9
15
|
* @attr {string} for - The id of the input element to associate as the combobox controller.
|
|
16
|
+
* @attr {string} active-class - The CSS class name to apply to the active item (default: "active").
|
|
10
17
|
* @slot - The list options.
|
|
11
18
|
* @example
|
|
12
19
|
* <input id="my-input" />
|
|
13
|
-
* <
|
|
20
|
+
* <bl-select-list for="my-input">
|
|
14
21
|
* <div>Option 1</div>
|
|
15
22
|
* <div>Option 2</div>
|
|
16
|
-
* </
|
|
23
|
+
* </bl-select-list>
|
|
17
24
|
*/
|
|
18
|
-
|
|
25
|
+
declare class SelectList extends HTMLElement {
|
|
19
26
|
activeIndex: number;
|
|
20
27
|
items: HTMLElement[];
|
|
21
28
|
inputElement: HTMLElement | null;
|
|
29
|
+
slotElement: HTMLSlotElement | null;
|
|
30
|
+
observer: MutationObserver | null;
|
|
22
31
|
constructor();
|
|
32
|
+
get activeClass(): string;
|
|
23
33
|
connectedCallback(): void;
|
|
34
|
+
disconnectedCallback(): void;
|
|
35
|
+
handleChildrenChanged: () => void;
|
|
36
|
+
syncActiveIndexFromDataSelected(): void;
|
|
24
37
|
updateItems(): void;
|
|
25
38
|
onKeyDown(e: {
|
|
26
39
|
key: string;
|
|
@@ -29,3 +42,5 @@ export declare class SelectList extends HTMLElement {
|
|
|
29
42
|
updateActiveItem(): void;
|
|
30
43
|
select(index: number): void;
|
|
31
44
|
}
|
|
45
|
+
export { SelectList, BlSelectEvent };
|
|
46
|
+
export default SelectList;
|
package/dist/js/select-list.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
+
class BlSelectEvent extends Event {
|
|
5
|
+
constructor(index, item) {
|
|
6
|
+
super(BlSelectEvent.eventName, {
|
|
7
|
+
bubbles: true,
|
|
8
|
+
composed: true
|
|
9
|
+
});
|
|
10
|
+
this.index = index;
|
|
11
|
+
this.item = item;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
/**
|
|
2
16
|
* A Web Component that provides a keyboard-accessible selectable list, typically used for dropdowns or autocomplete lists.
|
|
3
17
|
* Together with `popover` and CSS Anchoring, it's also useful to create a dropdown list.
|
|
@@ -5,19 +19,33 @@
|
|
|
5
19
|
*
|
|
6
20
|
* The Web Component will automatically set attributes for accessibility.
|
|
7
21
|
*
|
|
8
|
-
* @element
|
|
22
|
+
* @element bl-select-list
|
|
9
23
|
* @attr {string} for - The id of the input element to associate as the combobox controller.
|
|
24
|
+
* @attr {string} active-class - The CSS class name to apply to the active item (default: "active").
|
|
10
25
|
* @slot - The list options.
|
|
11
26
|
* @example
|
|
12
27
|
* <input id="my-input" />
|
|
13
|
-
* <
|
|
28
|
+
* <bl-select-list for="my-input">
|
|
14
29
|
* <div>Option 1</div>
|
|
15
30
|
* <div>Option 2</div>
|
|
16
|
-
* </
|
|
31
|
+
* </bl-select-list>
|
|
17
32
|
*/
|
|
18
|
-
|
|
33
|
+
_defineProperty(BlSelectEvent, "eventName", "bl-select");
|
|
34
|
+
class SelectList extends HTMLElement {
|
|
19
35
|
constructor() {
|
|
20
36
|
super();
|
|
37
|
+
_defineProperty(this, "handleChildrenChanged", () => {
|
|
38
|
+
var _this$items$this$acti;
|
|
39
|
+
const previousActiveId = (_this$items$this$acti = this.items[this.activeIndex]) === null || _this$items$this$acti === void 0 ? void 0 : _this$items$this$acti.id;
|
|
40
|
+
this.updateItems();
|
|
41
|
+
if (previousActiveId) {
|
|
42
|
+
const newIndex = this.items.findIndex(el => el.id === previousActiveId);
|
|
43
|
+
this.activeIndex = newIndex >= 0 ? newIndex : -1;
|
|
44
|
+
} else {
|
|
45
|
+
this.activeIndex = -1;
|
|
46
|
+
}
|
|
47
|
+
this.updateActiveItem();
|
|
48
|
+
});
|
|
21
49
|
this.attachShadow({
|
|
22
50
|
mode: "open"
|
|
23
51
|
});
|
|
@@ -25,13 +53,19 @@ export class SelectList extends HTMLElement {
|
|
|
25
53
|
this.activeIndex = -1;
|
|
26
54
|
this.items = [];
|
|
27
55
|
this.inputElement = null;
|
|
56
|
+
this.slotElement = null;
|
|
57
|
+
this.observer = null;
|
|
58
|
+
}
|
|
59
|
+
get activeClass() {
|
|
60
|
+
return this.getAttribute("active-class") || "active";
|
|
28
61
|
}
|
|
29
62
|
connectedCallback() {
|
|
63
|
+
var _this$shadowRoot, _this$slotElement;
|
|
30
64
|
this.setAttribute("role", "listbox");
|
|
31
65
|
this.tabIndex = -1;
|
|
32
66
|
this.updateItems();
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
this.syncActiveIndexFromDataSelected();
|
|
68
|
+
this.updateActiveItem();
|
|
35
69
|
const inputId = this.getAttribute("for");
|
|
36
70
|
this.inputElement = inputId ? document.getElementById(inputId) : null;
|
|
37
71
|
if (this.inputElement) {
|
|
@@ -42,20 +76,50 @@ export class SelectList extends HTMLElement {
|
|
|
42
76
|
}
|
|
43
77
|
this.addEventListener("keydown", this.onKeyDown.bind(this));
|
|
44
78
|
this.addEventListener("click", e => {
|
|
45
|
-
const target = e.target instanceof Element ? e.target.closest("[data-
|
|
46
|
-
if (target && target.hasAttribute("data-
|
|
47
|
-
const index = Number(target.getAttribute("data-
|
|
79
|
+
const target = e.target instanceof Element ? e.target.closest("[data-select-list-index]") : null;
|
|
80
|
+
if (target && target.hasAttribute("data-select-list-index")) {
|
|
81
|
+
const index = Number(target.getAttribute("data-select-list-index"));
|
|
48
82
|
this.select(index);
|
|
49
83
|
}
|
|
50
84
|
});
|
|
85
|
+
this.observer = new MutationObserver(mutations => {
|
|
86
|
+
if (mutations.some(m => m.type === "childList")) {
|
|
87
|
+
this.handleChildrenChanged();
|
|
88
|
+
}
|
|
89
|
+
if (mutations.some(m => m.type === "attributes" && m.attributeName === "data-selected")) {
|
|
90
|
+
this.syncActiveIndexFromDataSelected();
|
|
91
|
+
this.updateActiveItem();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
this.observer.observe(this, {
|
|
95
|
+
childList: true,
|
|
96
|
+
subtree: true,
|
|
97
|
+
attributes: true,
|
|
98
|
+
attributeFilter: ["data-selected"]
|
|
99
|
+
});
|
|
100
|
+
this.slotElement = (_this$shadowRoot = this.shadowRoot) === null || _this$shadowRoot === void 0 ? void 0 : _this$shadowRoot.querySelector("slot");
|
|
101
|
+
(_this$slotElement = this.slotElement) === null || _this$slotElement === void 0 || _this$slotElement.addEventListener("slotchange", this.handleChildrenChanged);
|
|
102
|
+
}
|
|
103
|
+
disconnectedCallback() {
|
|
104
|
+
var _this$observer, _this$slotElement2;
|
|
105
|
+
(_this$observer = this.observer) === null || _this$observer === void 0 || _this$observer.disconnect();
|
|
106
|
+
this.observer = null;
|
|
107
|
+
(_this$slotElement2 = this.slotElement) === null || _this$slotElement2 === void 0 || _this$slotElement2.removeEventListener("slotchange", this.handleChildrenChanged);
|
|
108
|
+
}
|
|
109
|
+
syncActiveIndexFromDataSelected() {
|
|
110
|
+
const selectedIndex = this.items.findIndex(el => el.hasAttribute("data-selected"));
|
|
111
|
+
if (selectedIndex >= 0) {
|
|
112
|
+
this.activeIndex = selectedIndex;
|
|
113
|
+
}
|
|
51
114
|
}
|
|
52
115
|
updateItems() {
|
|
53
|
-
|
|
116
|
+
const selectableSelectors = ["button:not([disabled])", "a[href]", "input:not([disabled])", "select:not([disabled])", "textarea:not([disabled])", '[tabindex]:not([tabindex="-1"])', '[role="option"]'].join(", ");
|
|
117
|
+
this.items = Array.from(this.querySelectorAll(selectableSelectors));
|
|
54
118
|
this.items.forEach((el, i) => {
|
|
55
119
|
if (!el.hasAttribute("id")) {
|
|
56
120
|
el.setAttribute("id", "".concat(this.id, "-option-").concat(i));
|
|
57
121
|
}
|
|
58
|
-
el.setAttribute("data-
|
|
122
|
+
el.setAttribute("data-select-list-index", i.toString());
|
|
59
123
|
el.setAttribute("aria-selected", "false");
|
|
60
124
|
el.setAttribute("role", "option");
|
|
61
125
|
el.tabIndex = -1;
|
|
@@ -72,14 +136,18 @@ export class SelectList extends HTMLElement {
|
|
|
72
136
|
this.activeIndex = (this.activeIndex - 1 + this.items.length) % this.items.length;
|
|
73
137
|
this.updateActiveItem();
|
|
74
138
|
} else if (e.key === "Enter" && this.activeIndex >= 0) {
|
|
139
|
+
e.preventDefault();
|
|
75
140
|
const item = this.items[this.activeIndex];
|
|
76
141
|
item === null || item === void 0 || item.click();
|
|
77
142
|
}
|
|
78
143
|
}
|
|
79
144
|
updateActiveItem() {
|
|
145
|
+
const activeClassNames = this.activeClass.split(" ");
|
|
80
146
|
this.items.forEach((el, i) => {
|
|
81
147
|
const active = i === this.activeIndex;
|
|
82
|
-
|
|
148
|
+
activeClassNames.forEach(activeClassName => {
|
|
149
|
+
el.classList.toggle(activeClassName, active);
|
|
150
|
+
});
|
|
83
151
|
el.setAttribute("aria-selected", active.toString());
|
|
84
152
|
});
|
|
85
153
|
const activeItem = this.items[this.activeIndex];
|
|
@@ -88,24 +156,23 @@ export class SelectList extends HTMLElement {
|
|
|
88
156
|
activeItem.scrollIntoView({
|
|
89
157
|
block: "nearest"
|
|
90
158
|
});
|
|
159
|
+
} else if (this.inputElement) {
|
|
160
|
+
this.inputElement.removeAttribute("aria-activedescendant");
|
|
91
161
|
}
|
|
92
162
|
}
|
|
93
163
|
select(index) {
|
|
94
164
|
this.activeIndex = index;
|
|
95
|
-
this.
|
|
165
|
+
this.items.forEach(el => el.removeAttribute("data-selected"));
|
|
96
166
|
const selectedItem = this.items[index];
|
|
97
167
|
if (selectedItem) {
|
|
98
|
-
|
|
99
|
-
this.dispatchEvent(new
|
|
100
|
-
|
|
101
|
-
index,
|
|
102
|
-
item: selectedItem
|
|
103
|
-
},
|
|
104
|
-
bubbles: true,
|
|
105
|
-
composed: true
|
|
106
|
-
}));
|
|
107
|
-
selectedItem.click();
|
|
168
|
+
selectedItem.setAttribute("data-selected", "");
|
|
169
|
+
this.dispatchEvent(new BlSelectEvent(index, selectedItem));
|
|
170
|
+
this.updateActiveItem();
|
|
108
171
|
}
|
|
109
172
|
}
|
|
110
173
|
}
|
|
111
|
-
customElements.
|
|
174
|
+
if (!customElements.get("bl-select-list")) {
|
|
175
|
+
customElements.define("bl-select-list", SelectList);
|
|
176
|
+
}
|
|
177
|
+
export { SelectList, BlSelectEvent };
|
|
178
|
+
export default SelectList;
|