blue-web 1.3.1 → 1.3.3

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.
Files changed (40) hide show
  1. package/dist/js/actions.bundle.js +1 -0
  2. package/dist/js/actions.d.ts +6 -0
  3. package/dist/js/actions.js +70 -0
  4. package/dist/js/color-mode.bundle.js +1 -0
  5. package/dist/js/color-mode.d.ts +4 -0
  6. package/dist/js/color-mode.js +37 -0
  7. package/dist/js/edit-view.bundle.js +1 -0
  8. package/dist/js/edit-view.d.ts +14 -0
  9. package/dist/js/edit-view.js +56 -0
  10. package/dist/js/input-splitted.bundle.js +1 -0
  11. package/dist/js/input-splitted.d.ts +19 -0
  12. package/dist/js/input-splitted.js +229 -0
  13. package/dist/js/read-view.bundle.js +1 -0
  14. package/dist/js/read-view.d.ts +35 -0
  15. package/dist/js/read-view.js +123 -0
  16. package/dist/js/select-list.bundle.js +1 -0
  17. package/dist/js/select-list.d.ts +31 -0
  18. package/dist/js/select-list.js +112 -0
  19. package/dist/js/side-layout.bundle.js +1 -0
  20. package/dist/js/side-layout.d.ts +7 -0
  21. package/dist/js/side-layout.js +171 -0
  22. package/dist/merged.scss +12455 -0
  23. package/dist/style.css +9317 -5694
  24. package/dist/style.css.map +1 -0
  25. package/dist/style.min.css +9 -13
  26. package/dist/style.scss +1 -1
  27. package/dist/styles/_action-menu.scss +4 -0
  28. package/dist/styles/_caret.scss +4 -0
  29. package/dist/styles/_general.scss +14 -1
  30. package/dist/styles/_layout.scss +27 -0
  31. package/dist/styles/_search.scss +4 -0
  32. package/dist/styles/_sidebar.scss +8 -0
  33. package/dist/styles/_status.scss +9 -29
  34. package/dist/styles/_tooltips.scss +16 -0
  35. package/dist/styles/mixins/_action-menu.scss +5 -0
  36. package/dist/styles/mixins/_menu-item.scss +12 -0
  37. package/dist/styles/mixins/_misc.scss +8 -0
  38. package/dist/styles/mixins/_sidebar.scss +8 -0
  39. package/dist/styles/mixins/_switch.scss +16 -10
  40. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ (()=>{"use strict";window.blueWeb=window.blueWeb||{},window.blueWeb.actions={init:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;function s(){for(const e of t.children)e.style.display="none";for(const e of i.children)e.style.display="",e.classList.add("BLUE-actions-collapse-visible");let s=0;for(const n of t.children){if(n.style.display="",i.children[s].style.display="none",i.children[s].classList.remove("BLUE-actions-collapse-visible"),e.scrollWidth>e.clientWidth){n.style.display="none",i.children[s].style.display="",i.children[s].classList.add("BLUE-actions-collapse-visible");break}s++}}t||(t=e.querySelector(".BLUE-actions-menu")),i||(i=e.querySelector(".BLUE-actions-collapse-menu")),s();const n=()=>{requestAnimationFrame(s)},o=new ResizeObserver(n);o.observe(e);const l=new MutationObserver(n);l.observe(e,{attributes:!1,childList:!0,subtree:!0});const c=t=>{if(!e)return;const i=e.querySelectorAll("details[open]");!i||i.length<=0||i.forEach((e=>{e.contains(t.target)||e.removeAttribute("open")}))};return document.addEventListener("click",c),{updateActions:s,resizeObserver:o,mutationObserver:l,destroy(){o.disconnect(),l.disconnect(),document.removeEventListener("click",c)}}}}})();
@@ -0,0 +1,6 @@
1
+ export declare function init(actionsElement: HTMLElement, menu?: HTMLElement | undefined, collapseMenu?: HTMLElement | undefined): {
2
+ updateActions: () => void;
3
+ resizeObserver: ResizeObserver;
4
+ mutationObserver: MutationObserver;
5
+ destroy(): void;
6
+ };
@@ -0,0 +1,70 @@
1
+ export function init(actionsElement) {
2
+ let menu = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
3
+ let collapseMenu = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
4
+ if (!menu) menu = actionsElement.querySelector(".BLUE-actions-menu");
5
+ if (!collapseMenu) collapseMenu = actionsElement.querySelector(".BLUE-actions-collapse-menu");
6
+ function updateActions() {
7
+ // reset
8
+ for (const item of menu.children) {
9
+ ;
10
+ item.style.display = "none";
11
+ }
12
+ for (const item of collapseMenu.children) {
13
+ ;
14
+ item.style.display = "";
15
+ item.classList.add("BLUE-actions-collapse-visible");
16
+ }
17
+ let i = 0;
18
+ for (const item of menu.children) {
19
+ ;
20
+ item.style.display = "";
21
+ collapseMenu.children[i].style.display = "none";
22
+ collapseMenu.children[i].classList.remove("BLUE-actions-collapse-visible");
23
+ if (actionsElement.scrollWidth > actionsElement.clientWidth) {
24
+ ;
25
+ item.style.display = "none";
26
+ collapseMenu.children[i].style.display = "";
27
+ collapseMenu.children[i].classList.add("BLUE-actions-collapse-visible");
28
+ break;
29
+ }
30
+ i++;
31
+ }
32
+ }
33
+ updateActions();
34
+ const callback = () => {
35
+ requestAnimationFrame(updateActions);
36
+ };
37
+ const resizeObserver = new ResizeObserver(callback);
38
+ resizeObserver.observe(actionsElement);
39
+ const mutationObserver = new MutationObserver(callback);
40
+ mutationObserver.observe(actionsElement, {
41
+ attributes: false,
42
+ childList: true,
43
+ subtree: true
44
+ });
45
+ const outsideClickHandler = event => {
46
+ if (!actionsElement) return;
47
+ const openDetails = actionsElement.querySelectorAll("details[open]");
48
+ if (!openDetails || openDetails.length <= 0) return;
49
+ openDetails.forEach(details => {
50
+ if (!details.contains(event.target)) {
51
+ details.removeAttribute("open");
52
+ }
53
+ });
54
+ };
55
+ document.addEventListener("click", outsideClickHandler);
56
+ return {
57
+ updateActions,
58
+ resizeObserver,
59
+ mutationObserver,
60
+ destroy() {
61
+ resizeObserver.disconnect();
62
+ mutationObserver.disconnect();
63
+ document.removeEventListener("click", outsideClickHandler);
64
+ }
65
+ };
66
+ }
67
+ window.blueWeb = window.blueWeb || {};
68
+ window.blueWeb.actions = {
69
+ init
70
+ };
@@ -0,0 +1 @@
1
+ (()=>{"use strict";const e=()=>localStorage.getItem("blue-web-color-mode"),t=()=>e()||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),o=()=>{const e=t();"auto"===e&&window.matchMedia("(prefers-color-scheme: dark)").matches?document.documentElement.setAttribute("data-bs-theme","dark"):document.documentElement.setAttribute("data-bs-theme",e)};window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(()=>{localStorage.removeItem("blue-web-color-mode"),o()})),o(),window.blueWeb=window.blueWeb||{},window.blueWeb.colorMode={getStored:e,getPreferred:t,set:e=>{"auto"===e?localStorage.removeItem("blue-web-color-mode"):localStorage.setItem("blue-web-color-mode",e),o()},init:o}})();
@@ -0,0 +1,4 @@
1
+ export declare const getStored: () => string | null;
2
+ export declare const getPreferred: () => string;
3
+ export declare const set: (colorMode: string) => void;
4
+ export declare const init: () => void;
@@ -0,0 +1,37 @@
1
+ export const getStored = () => localStorage.getItem("blue-web-color-mode");
2
+ export const getPreferred = () => {
3
+ const stored = getStored();
4
+ if (stored) {
5
+ return stored;
6
+ }
7
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
8
+ };
9
+ export const set = colorMode => {
10
+ if (colorMode === "auto") {
11
+ localStorage.removeItem("blue-web-color-mode");
12
+ } else {
13
+ localStorage.setItem("blue-web-color-mode", colorMode);
14
+ }
15
+ init();
16
+ };
17
+ export const init = () => {
18
+ const colorMode = getPreferred();
19
+ if (colorMode === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches) {
20
+ document.documentElement.setAttribute("data-bs-theme", "dark");
21
+ } else {
22
+ document.documentElement.setAttribute("data-bs-theme", colorMode);
23
+ }
24
+ };
25
+ const onMatchMediaChange = () => {
26
+ localStorage.removeItem("blue-web-color-mode");
27
+ init();
28
+ };
29
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", onMatchMediaChange);
30
+ init();
31
+ window.blueWeb = window.blueWeb || {};
32
+ window.blueWeb.colorMode = {
33
+ getStored,
34
+ getPreferred,
35
+ set,
36
+ init
37
+ };
@@ -0,0 +1 @@
1
+ (()=>{"use strict";class e extends HTMLElement{connectedCallback(){this.render()}disconnectedCallback(){this.confirmTimeout&&clearTimeout(this.confirmTimeout)}render(){const e=document.createElement("form");e.style.position="relative";const t=Array.from(this.childNodes);this.appendChild(e),t.forEach((t=>e.appendChild(t))),e.addEventListener("submit",this.onSubmit.bind(this)),e.addEventListener("keydown",this.onKeydown.bind(this)),e.addEventListener("focusout",this.onFocusout.bind(this))}onSubmit(e){e.preventDefault(),this.confirm()}onKeydown(e){"Esc"!==e.key&&"Escape"!==e.key||this.dismiss()}onFocusout(e){this.contains(e.relatedTarget)||(this.confirmTimeout&&clearTimeout(this.confirmTimeout),this.confirmTimeout=setTimeout((()=>{this.confirm(),this.confirmTimeout=null}),500))}confirm(){this.dispatchEvent(new CustomEvent("Confirm",{bubbles:!0,composed:!0}))}dismiss(){this.dispatchEvent(new CustomEvent("Dismiss",{bubbles:!0,composed:!0}))}}customElements.define("edit-view",e)})();
@@ -0,0 +1,14 @@
1
+ /**
2
+ * EditView is a Custom Element that displays a edit view of its content and allows the user to confirm or dismiss the changes.
3
+ */
4
+ export declare class EditView extends HTMLElement {
5
+ private confirmTimeout;
6
+ connectedCallback(): void;
7
+ disconnectedCallback(): void;
8
+ private render;
9
+ private onSubmit;
10
+ private onKeydown;
11
+ private onFocusout;
12
+ private confirm;
13
+ private dismiss;
14
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * EditView is a Custom Element that displays a edit view of its content and allows the user to confirm or dismiss the changes.
3
+ */
4
+ export class EditView extends HTMLElement {
5
+ connectedCallback() {
6
+ this.render();
7
+ }
8
+ disconnectedCallback() {
9
+ if (this.confirmTimeout) {
10
+ clearTimeout(this.confirmTimeout);
11
+ }
12
+ }
13
+ render() {
14
+ const root = document.createElement("form");
15
+ root.style.position = "relative";
16
+ const children = Array.from(this.childNodes);
17
+ this.appendChild(root);
18
+ children.forEach(child => root.appendChild(child));
19
+ root.addEventListener("submit", this.onSubmit.bind(this));
20
+ root.addEventListener("keydown", this.onKeydown.bind(this));
21
+ root.addEventListener("focusout", this.onFocusout.bind(this));
22
+ }
23
+ onSubmit(e) {
24
+ e.preventDefault();
25
+ this.confirm();
26
+ }
27
+ onKeydown(e) {
28
+ if (e.key === "Esc" || e.key === "Escape") {
29
+ this.dismiss();
30
+ }
31
+ }
32
+ onFocusout(e) {
33
+ if (!this.contains(e.relatedTarget)) {
34
+ if (this.confirmTimeout) {
35
+ clearTimeout(this.confirmTimeout);
36
+ }
37
+ this.confirmTimeout = setTimeout(() => {
38
+ this.confirm();
39
+ this.confirmTimeout = null;
40
+ }, 500);
41
+ }
42
+ }
43
+ confirm() {
44
+ this.dispatchEvent(new CustomEvent("Confirm", {
45
+ bubbles: true,
46
+ composed: true
47
+ }));
48
+ }
49
+ dismiss() {
50
+ this.dispatchEvent(new CustomEvent("Dismiss", {
51
+ bubbles: true,
52
+ composed: true
53
+ }));
54
+ }
55
+ }
56
+ customElements.define("edit-view", EditView);
@@ -0,0 +1 @@
1
+ (()=>{"use strict";class t extends HTMLElement{#t;#e=[];#s=[];#i=!1;get lightDom(){return this.#i}set lightDom(t){this.#i=t,!0===this.lightDom?this.innerHTML=this.#r:(this.shadowRoot||this.attachShadow({mode:"open",delegatesFocus:!0}),this.shadowRoot.innerHTML=this.#r),this.#l()}#h="";get value(){return this.#h}set value(t){const e=this.#h;this.#h=t,this.#e=this.value.split("");for(let t=0;t<this.length;t++)this.#s[t]&&(this.#s[t].value=this.#e[t]||"");e!==t&&this.dispatchEvent(new CustomEvent("changeValue",{bubbles:!0,detail:t}))}#o=0;get length(){return this.#o}set length(t){if(this.#o=t,this.length>this.#s.length)for(let t=0;t<this.length;t++)!this.#s[t]&&this.didInit&&this.#n(this.#s.length);else if(this.length<this.#s.length){const t=Math.abs(this.#s.length-this.length);for(let e=0;e<t;e++){const t=this.#s.pop();t?.remove()}}this.#s=[...this.#s]}#a="";get controlClass(){return this.#a}set controlClass(t){this.#a=t;for(const t of this.#s)t.className=this.controlClass}#u="";get control1Id(){return this.#u}set control1Id(t){this.#u=t,this.#s[0]&&(this.#s[0].id=this.control1Id)}#r="<style>\n input {\n display: var(--blue-input-splitted-display, revert);\n background-color: var(--blue-input-splitted-background-color, revert);\n border: var(--blue-input-splitted-border, revert);\n border-radius: var(--blue-input-splitted-border-radius, revert);\n box-shadow: var(--blue-input-splitted-box-shadow, revert);\n color: var(--blue-input-splitted-color, revert);\n margin: var(--blue-input-splitted-margin, revert);\n padding: var(--blue-input-splitted-padding, revert);\n text-align: var(--blue-input-splitted-text-align, revert);\n width: var(--blue-input-splitted-width, revert);\n }\n</style>";didInit=!1;constructor(){super(),this.onFocus=this.onFocus.bind(this)}connectedCallback(){this.didInit=!0,this.lightDom=null!==this.getAttribute("light-dom"),this.#l(),this.value=this.getAttribute("value")||this.value,this.length=e(this),this.controlClass=this.getAttribute("control-class")||this.controlClass,this.control1Id=this.getAttribute("control-1-id")||this.control1Id,this.#d()}#n(t){const e=document.createElement("input");this.#s.push(e),e.type="text",e.className=this.controlClass,0===t&&(e.id=this.control1Id),e.maxLength=1,e.value=this.#e[t]||"",e.addEventListener("input",(e=>{let{target:s}=e;const i=s;""!==i.value&&this.#s[t+1]&&this.#s[t+1].focus(),this.#e[t]=i.value,this.value=this.#e.join("")})),e.addEventListener("keydown",(e=>{let{key:s,target:i}=e;"Backspace"===s&&""===i.value&&void 0!==this.#s[t-1]&&this.#s[t-1].focus()})),e.addEventListener("paste",(e=>{let{clipboardData:s}=e;const i=s.getData("Text");let r=0;for(let e=t;e<this.length;e++)this.#e[e]=i.split("")[r],this.#s[e].focus(),r+=1;this.value=this.#e.join("")})),this.lightDom?this.appendChild(e):this.shadowRoot.appendChild(e)}onFocus(){this.#s[0]&&this.#s[0].focus()}#l(){this.value=this.getAttribute("value")||"",this.length=e(this),this.lightDom?(this.innerHTML=this.#r,this.addEventListener("focus",this.onFocus)):(this.shadowRoot.innerHTML=this.#r,this.shadowRoot.addEventListener("focus",this.onFocus)),this.#e=this.value.split(""),this.#s=[];for(let t=0;t<this.length;t++)this.#n(t)}#d(){this.#t=this.#t||new MutationObserver((t=>{t.forEach((t=>{"value"===t.attributeName&&(this.value=this.getAttribute("value")||this.value),"length"===t.attributeName&&(this.length=e(this)),"control-class"===t.attributeName&&(this.controlClass=this.getAttribute("control-class")||this.controlClass),"control-1-id"===t.attributeName&&(this.control1Id=this.getAttribute("control-1-id")||this.control1Id),"light-dom"===t.attributeName&&(this.lightDom=null!==this.getAttribute("light-dom"))}))})),this.#t.observe(this,{attributeFilter:["value","length","control-class","control-1-id","light-dom"],attributeOldValue:!0,childList:!0,subtree:!0})}#c(){this.#t&&(this.#t.takeRecords(),this.#t.disconnect())}disconnectedCallback(){this.#c()}static get formAssociated(){return!0}}function e(t){const e=t.getAttribute("length");if(e)return parseInt(e)}customElements.define("bl-input-splitted",t)})();
@@ -0,0 +1,19 @@
1
+ export declare class InputSplitted extends HTMLElement {
2
+ #private;
3
+ get lightDom(): boolean;
4
+ set lightDom(_lightDom: boolean);
5
+ get value(): string;
6
+ set value(_value: string);
7
+ get length(): number;
8
+ set length(_length: number);
9
+ get controlClass(): string;
10
+ set controlClass(value: string);
11
+ get control1Id(): string;
12
+ set control1Id(value: string);
13
+ didInit: boolean;
14
+ constructor();
15
+ connectedCallback(): void;
16
+ onFocus(): void;
17
+ disconnectedCallback(): void;
18
+ static get formAssociated(): boolean;
19
+ }
@@ -0,0 +1,229 @@
1
+ export class InputSplitted extends HTMLElement {
2
+ #observer;
3
+ #valueArray = [];
4
+ #refArray = [];
5
+ #lightDom = false;
6
+ get lightDom() {
7
+ return this.#lightDom;
8
+ }
9
+ set lightDom(_lightDom) {
10
+ this.#lightDom = _lightDom;
11
+ if (this.lightDom === true) {
12
+ this.innerHTML = this.#styling;
13
+ } else {
14
+ if (!this.shadowRoot) this.attachShadow({
15
+ mode: "open",
16
+ delegatesFocus: true
17
+ });
18
+ this.shadowRoot.innerHTML = this.#styling;
19
+ }
20
+ this.#initDom();
21
+ }
22
+ #value = "";
23
+ get value() {
24
+ return this.#value;
25
+ }
26
+ set value(_value) {
27
+ const oldValue = this.#value;
28
+ this.#value = _value;
29
+ this.#valueArray = this.value.split("");
30
+ for (let i = 0; i < this.length; i++) {
31
+ if (this.#refArray[i]) this.#refArray[i].value = this.#valueArray[i] || "";
32
+ }
33
+ if (oldValue !== _value) {
34
+ this.dispatchEvent(new CustomEvent("changeValue", {
35
+ bubbles: true,
36
+ detail: _value
37
+ }));
38
+ }
39
+ }
40
+ #length = 0;
41
+ get length() {
42
+ return this.#length;
43
+ }
44
+ set length(_length) {
45
+ this.#length = _length;
46
+ if (this.length > this.#refArray.length) {
47
+ // Added length
48
+
49
+ for (let j = 0; j < this.length; j++) {
50
+ if (!this.#refArray[j] && this.didInit) {
51
+ this.#addInput(this.#refArray.length);
52
+ }
53
+ }
54
+ } else if (this.length < this.#refArray.length) {
55
+ // Removed length
56
+
57
+ const difference = Math.abs(this.#refArray.length - this.length);
58
+ for (let j = 0; j < difference; j++) {
59
+ const el = this.#refArray.pop();
60
+ el?.remove();
61
+ }
62
+ }
63
+ this.#refArray = [...this.#refArray];
64
+ }
65
+ #controlClass = "";
66
+ get controlClass() {
67
+ return this.#controlClass;
68
+ }
69
+ set controlClass(value) {
70
+ this.#controlClass = value;
71
+ for (const el of this.#refArray) {
72
+ el.className = this.controlClass;
73
+ }
74
+ }
75
+ #control1Id = "";
76
+ get control1Id() {
77
+ return this.#control1Id;
78
+ }
79
+ set control1Id(value) {
80
+ this.#control1Id = value;
81
+ if (this.#refArray[0]) {
82
+ this.#refArray[0].id = this.control1Id;
83
+ }
84
+ }
85
+ #styling = /* html */`<style>
86
+ input {
87
+ display: var(--blue-input-splitted-display, revert);
88
+ background-color: var(--blue-input-splitted-background-color, revert);
89
+ border: var(--blue-input-splitted-border, revert);
90
+ border-radius: var(--blue-input-splitted-border-radius, revert);
91
+ box-shadow: var(--blue-input-splitted-box-shadow, revert);
92
+ color: var(--blue-input-splitted-color, revert);
93
+ margin: var(--blue-input-splitted-margin, revert);
94
+ padding: var(--blue-input-splitted-padding, revert);
95
+ text-align: var(--blue-input-splitted-text-align, revert);
96
+ width: var(--blue-input-splitted-width, revert);
97
+ }
98
+ </style>`;
99
+ didInit = false;
100
+ constructor() {
101
+ super();
102
+ this.onFocus = this.onFocus.bind(this);
103
+ }
104
+ connectedCallback() {
105
+ this.didInit = true;
106
+ this.lightDom = this.getAttribute("light-dom") !== null;
107
+ this.#initDom();
108
+ this.value = this.getAttribute("value") || this.value;
109
+ this.length = getLength(this);
110
+ this.controlClass = this.getAttribute("control-class") || this.controlClass;
111
+ this.control1Id = this.getAttribute("control-1-id") || this.control1Id;
112
+ this.#observe();
113
+ }
114
+ #addInput(i) {
115
+ const input = document.createElement("input");
116
+ this.#refArray.push(input);
117
+ input.type = "text";
118
+ input.className = this.controlClass;
119
+ if (i === 0) {
120
+ input.id = this.control1Id;
121
+ }
122
+ input.maxLength = 1;
123
+ input.value = this.#valueArray[i] || "";
124
+ input.addEventListener("input", _ref => {
125
+ let {
126
+ target
127
+ } = _ref;
128
+ const inputTarget = target;
129
+ if (inputTarget.value !== "" && this.#refArray[i + 1]) {
130
+ this.#refArray[i + 1].focus();
131
+ }
132
+ this.#valueArray[i] = inputTarget.value;
133
+ this.value = this.#valueArray.join("");
134
+ });
135
+ input.addEventListener("keydown", _ref2 => {
136
+ let {
137
+ key,
138
+ target
139
+ } = _ref2;
140
+ const inputTarget = target;
141
+ if (key === "Backspace" && inputTarget.value === "" && this.#refArray[i - 1] !== undefined) {
142
+ this.#refArray[i - 1].focus();
143
+ }
144
+ });
145
+ input.addEventListener("paste", _ref3 => {
146
+ let {
147
+ clipboardData
148
+ } = _ref3;
149
+ const pastedData = clipboardData.getData("Text");
150
+ let k = 0;
151
+ for (let j = i; j < this.length; j++) {
152
+ this.#valueArray[j] = pastedData.split("")[k];
153
+ this.#refArray[j].focus();
154
+ k = k + 1;
155
+ }
156
+ this.value = this.#valueArray.join("");
157
+ });
158
+ if (this.lightDom) {
159
+ this.appendChild(input);
160
+ } else {
161
+ this.shadowRoot.appendChild(input);
162
+ }
163
+ }
164
+ onFocus() {
165
+ if (this.#refArray[0]) this.#refArray[0].focus();
166
+ }
167
+ #initDom() {
168
+ this.value = this.getAttribute("value") || "";
169
+ this.length = getLength(this);
170
+ if (this.lightDom) {
171
+ this.innerHTML = this.#styling;
172
+ this.addEventListener("focus", this.onFocus);
173
+ } else {
174
+ this.shadowRoot.innerHTML = this.#styling;
175
+ this.shadowRoot.addEventListener("focus", this.onFocus);
176
+ }
177
+ this.#valueArray = this.value.split("");
178
+ this.#refArray = [];
179
+ for (let i = 0; i < this.length; i++) {
180
+ this.#addInput(i);
181
+ }
182
+ }
183
+ #observe() {
184
+ // Observer prüft, ob sich HTML-Attribute geändert haben.
185
+ // Props-Änderungen werden ohne bemerkt.
186
+ this.#observer = this.#observer || new MutationObserver(mutations => {
187
+ mutations.forEach(m => {
188
+ if (m.attributeName === "value") {
189
+ this.value = this.getAttribute("value") || this.value;
190
+ }
191
+ if (m.attributeName === "length") {
192
+ this.length = getLength(this);
193
+ }
194
+ if (m.attributeName === "control-class") {
195
+ this.controlClass = this.getAttribute("control-class") || this.controlClass;
196
+ }
197
+ if (m.attributeName === "control-1-id") {
198
+ this.control1Id = this.getAttribute("control-1-id") || this.control1Id;
199
+ }
200
+ if (m.attributeName === "light-dom") {
201
+ this.lightDom = this.getAttribute("light-dom") !== null;
202
+ }
203
+ });
204
+ });
205
+ this.#observer.observe(this, {
206
+ attributeFilter: ["value", "length", "control-class", "control-1-id", "light-dom"],
207
+ attributeOldValue: true,
208
+ childList: true,
209
+ subtree: true
210
+ });
211
+ }
212
+ #unobserve() {
213
+ if (this.#observer) {
214
+ this.#observer.takeRecords();
215
+ this.#observer.disconnect();
216
+ }
217
+ }
218
+ disconnectedCallback() {
219
+ this.#unobserve();
220
+ }
221
+ static get formAssociated() {
222
+ return true;
223
+ }
224
+ }
225
+ function getLength(element) {
226
+ const attr = element.getAttribute("length");
227
+ if (attr) return parseInt(attr);
228
+ }
229
+ customElements.define("bl-input-splitted", InputSplitted);
@@ -0,0 +1 @@
1
+ (()=>{"use strict";class t extends HTMLElement{startX=0;startY=0;constructor(){super(),this.attachShadow({mode:"open"})}static get observedAttributes(){return["disabled"]}connectedCallback(){this.render()}attributeChangedCallback(t,e,n){"disabled"===t&&this.updateDisabledState()}render(){this.shadowRoot&&(this.shadowRoot.innerHTML='\n <style>\n button {\n display: block;\n margin: 0;\n padding: 0;\n appearance: none;\n background-color: transparent;\n border: none;\n line-height: 1;\n outline: 0;\n }\n\n button:focus-visible + div {\n outline: 0;\n box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 25%);\n border-color: rgba(var(--bs-primary-rgb), 50%);\n }\n\n div {\n display: inline-block;\n box-sizing: border-box;\n width: auto;\n max-width: 100%;\n border-color: transparent;\n border-radius: var(--bs-border-radius-sm, 3px);\n border: 1px solid transparent;\n transition: background 0.2s;\n }\n\n div:hover {\n background-color: var(--bs-secondary-bg-subtle);\n }\n\n :host([disabled]) div {\n background-color: transparent;\n }\n </style>\n <button aria-label="Edit"></button>\n <div role="presentation">\n <slot></slot>\n </div>\n ',this.button=this.shadowRoot.querySelector("button"),this.container=this.shadowRoot.querySelector("div"),this.button.addEventListener("click",this.onEditRequested.bind(this)),this.container.addEventListener("click",this.onReadViewClick.bind(this)),this.container.addEventListener("mousedown",this.onMouseDown.bind(this)),this.updateDisabledState())}updateDisabledState(){const t=this.hasAttribute("disabled");this.button?.setAttribute("aria-disabled",String(t)),this.container?.setAttribute("aria-disabled",String(t))}onEditRequested(){this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("EditRequested",{bubbles:!0,composed:!0}))}onMouseDown(t){this.hasAttribute("disabled")||(this.startX=t.clientX,this.startY=t.clientY)}mouseHasMovedAfterMouseDown(t){return Math.abs(this.startX-t.clientX)>=5||Math.abs(this.startY-t.clientY)>=5}onReadViewClick(t){this.hasAttribute("disabled")||"a"===t.target.tagName.toLowerCase()||this.mouseHasMovedAfterMouseDown(t)||(t.preventDefault(),this.onEditRequested())}}customElements.define("bl-read-view",t)})();
@@ -0,0 +1,35 @@
1
+ /**
2
+ * A Web Component that displays a read view of its content and allows the user to switch to an edit view.
3
+ * Fires event "EditRequested" when the user clicks the read view.
4
+ * @element read-view
5
+ * @fires EditRequested
6
+ * @attr {boolean} disabled - Disables the component, preventing interactions and removing hover effects.
7
+ * @cssprop --bs-primary-rgb - The primary color as an RGB value.
8
+ * @cssprop --bs-secondary-bg-subtle - The subtle background color for the read view.
9
+ * @cssprop --bs-border-radius-sm - The border radius for the read view.
10
+ * @slot - The content to display in the read view.
11
+ * @example
12
+ * <bl-read-view id="my-read-view" onEditRequested="setEditing(true)">
13
+ * <a href="#">bla</a> {value}
14
+ * </bl-read-view>
15
+ * @example
16
+ * document.getElementById("my-read-view").addEventListener("EditRequested", () => {
17
+ * setEditing(true)
18
+ * })
19
+ */
20
+ export declare class ReadView extends HTMLElement {
21
+ private button;
22
+ private container;
23
+ private startX;
24
+ private startY;
25
+ constructor();
26
+ static get observedAttributes(): string[];
27
+ connectedCallback(): void;
28
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
29
+ private render;
30
+ private updateDisabledState;
31
+ private onEditRequested;
32
+ private onMouseDown;
33
+ private mouseHasMovedAfterMouseDown;
34
+ private onReadViewClick;
35
+ }
@@ -0,0 +1,123 @@
1
+ const DRAG_THRESHOLD = 5;
2
+
3
+ /**
4
+ * A Web Component that displays a read view of its content and allows the user to switch to an edit view.
5
+ * Fires event "EditRequested" when the user clicks the read view.
6
+ * @element read-view
7
+ * @fires EditRequested
8
+ * @attr {boolean} disabled - Disables the component, preventing interactions and removing hover effects.
9
+ * @cssprop --bs-primary-rgb - The primary color as an RGB value.
10
+ * @cssprop --bs-secondary-bg-subtle - The subtle background color for the read view.
11
+ * @cssprop --bs-border-radius-sm - The border radius for the read view.
12
+ * @slot - The content to display in the read view.
13
+ * @example
14
+ * <bl-read-view id="my-read-view" onEditRequested="setEditing(true)">
15
+ * <a href="#">bla</a> {value}
16
+ * </bl-read-view>
17
+ * @example
18
+ * document.getElementById("my-read-view").addEventListener("EditRequested", () => {
19
+ * setEditing(true)
20
+ * })
21
+ */
22
+ export class ReadView extends HTMLElement {
23
+ startX = 0;
24
+ startY = 0;
25
+ constructor() {
26
+ super();
27
+ this.attachShadow({
28
+ mode: "open"
29
+ });
30
+ }
31
+ static get observedAttributes() {
32
+ return ["disabled"];
33
+ }
34
+ connectedCallback() {
35
+ this.render();
36
+ }
37
+ attributeChangedCallback(name, oldValue, newValue) {
38
+ if (name === "disabled") {
39
+ this.updateDisabledState();
40
+ }
41
+ }
42
+ render() {
43
+ if (!this.shadowRoot) return;
44
+ this.shadowRoot.innerHTML = /* HTML */`
45
+ <style>
46
+ button {
47
+ display: block;
48
+ margin: 0;
49
+ padding: 0;
50
+ appearance: none;
51
+ background-color: transparent;
52
+ border: none;
53
+ line-height: 1;
54
+ outline: 0;
55
+ }
56
+
57
+ button:focus-visible + div {
58
+ outline: 0;
59
+ box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 25%);
60
+ border-color: rgba(var(--bs-primary-rgb), 50%);
61
+ }
62
+
63
+ div {
64
+ display: inline-block;
65
+ box-sizing: border-box;
66
+ width: auto;
67
+ max-width: 100%;
68
+ border-color: transparent;
69
+ border-radius: var(--bs-border-radius-sm, 3px);
70
+ border: 1px solid transparent;
71
+ transition: background 0.2s;
72
+ }
73
+
74
+ div:hover {
75
+ background-color: var(--bs-secondary-bg-subtle);
76
+ }
77
+
78
+ :host([disabled]) div {
79
+ background-color: transparent;
80
+ }
81
+ </style>
82
+ <button aria-label="Edit"></button>
83
+ <div role="presentation">
84
+ <slot></slot>
85
+ </div>
86
+ `;
87
+ this.button = this.shadowRoot.querySelector("button");
88
+ this.container = this.shadowRoot.querySelector("div");
89
+ this.button.addEventListener("click", this.onEditRequested.bind(this));
90
+ this.container.addEventListener("click", this.onReadViewClick.bind(this));
91
+ this.container.addEventListener("mousedown", this.onMouseDown.bind(this));
92
+ this.updateDisabledState();
93
+ }
94
+ updateDisabledState() {
95
+ const isDisabled = this.hasAttribute("disabled");
96
+ this.button?.setAttribute("aria-disabled", String(isDisabled));
97
+ this.container?.setAttribute("aria-disabled", String(isDisabled));
98
+ }
99
+ onEditRequested() {
100
+ if (this.hasAttribute("disabled")) return;
101
+ this.dispatchEvent(new CustomEvent("EditRequested", {
102
+ bubbles: true,
103
+ composed: true
104
+ }));
105
+ }
106
+ onMouseDown(event) {
107
+ if (this.hasAttribute("disabled")) return;
108
+ this.startX = event.clientX;
109
+ this.startY = event.clientY;
110
+ }
111
+ mouseHasMovedAfterMouseDown(event) {
112
+ return Math.abs(this.startX - event.clientX) >= DRAG_THRESHOLD || Math.abs(this.startY - event.clientY) >= DRAG_THRESHOLD;
113
+ }
114
+ onReadViewClick(event) {
115
+ if (this.hasAttribute("disabled")) return;
116
+ const target = event.target;
117
+ if (target.tagName.toLowerCase() !== "a" && !this.mouseHasMovedAfterMouseDown(event)) {
118
+ event.preventDefault();
119
+ this.onEditRequested();
120
+ }
121
+ }
122
+ }
123
+ customElements.define("bl-read-view", ReadView);
@@ -0,0 +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 t=this.getAttribute("for");this.inputElement=t?document.getElementById(t):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-blue-select-list-index]"):null;if(e&&e.hasAttribute("data-blue-select-list-index")){const t=Number(e.getAttribute("data-blue-select-list-index"));this.select(t)}}))}updateItems(){this.items=Array.from(this.children),this.items.forEach(((t,e)=>{t.hasAttribute("id")||t.setAttribute("id",`${this.id}-option-${e}`),t.setAttribute("data-blue-select-list-index",e.toString()),t.setAttribute("aria-selected","false"),t.setAttribute("role","option"),t.tabIndex=-1}))}onKeyDown(t){if(console.log("select-list onKeyDown"),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){const t=this.items[this.activeIndex];t?.click()}}updateActiveItem(){this.items.forEach(((t,e)=>{const i=e===this.activeIndex;t.classList.toggle("active",i),t.setAttribute("aria-selected",i.toString())}));const t=this.items[this.activeIndex];t&&this.inputElement&&(this.inputElement.setAttribute("aria-activedescendant",t.id),t.scrollIntoView({block:"nearest"}))}select(t){this.activeIndex=t,this.updateActiveItem();const e=this.items[t];e&&(this.dispatchEvent(new CustomEvent("bl-select",{detail:{index:t,item:e},bubbles:!0,composed:!0})),e.click())}}customElements.define("bl-select-list",t)})();
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A Web Component that provides a keyboard-accessible selectable list, typically used for dropdowns or autocomplete lists.
3
+ * Together with `popover` and CSS Anchoring, it's also useful to create a dropdown list.
4
+ * Supports keyboard navigation and selection, and integrates with an input element for combobox behavior.
5
+ *
6
+ * The Web Component will automatically set attributes for accessibility.
7
+ *
8
+ * @element blue-select-list
9
+ * @attr {string} for - The id of the input element to associate as the combobox controller.
10
+ * @slot - The list options.
11
+ * @example
12
+ * <input id="my-input" />
13
+ * <blue-select-list for="my-input">
14
+ * <div>Option 1</div>
15
+ * <div>Option 2</div>
16
+ * </blue-select-list>
17
+ */
18
+ export declare class SelectList extends HTMLElement {
19
+ activeIndex: number;
20
+ items: HTMLElement[];
21
+ inputElement: HTMLElement | null;
22
+ constructor();
23
+ connectedCallback(): void;
24
+ updateItems(): void;
25
+ onKeyDown(e: {
26
+ key: string;
27
+ preventDefault: () => void;
28
+ }): void;
29
+ updateActiveItem(): void;
30
+ select(index: number): void;
31
+ }