@nectary/labs 2.5.39 → 2.5.41
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/color-select/index.js +89 -88
- package/imports.d.ts +2 -0
- package/index.js +6 -5
- package/package.json +8 -7
- package/phone-preview/index.js +81 -89
- package/phone-preview-rcs-channel/index.js +158 -172
- package/phone-preview-rcs-channel-actions/index.js +108 -115
- package/phone-preview-rcs-channel-info/index.js +59 -61
- package/phone-preview-rcs-channel-info-option/index.js +94 -99
- package/phone-preview-rcs-channel-options/index.js +42 -42
- package/phone-preview-rcs-channel-tabs/index.js +74 -74
- package/phone-preview-rcs-chat/index.js +190 -73
- package/phone-preview-rcs-chat-message/index.js +40 -42
- package/utils/element.js +63 -54
- package/utils/index.js +7 -1
- package/vite.config.js +66 -0
|
@@ -1,64 +1,62 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defineCustomElement, NectaryElement } from
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
const template = document.createElement(
|
|
1
|
+
import "@nectary/components/icon";
|
|
2
|
+
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
3
|
+
import "../phone-preview-rcs-channel-info-option/index.js";
|
|
4
|
+
const templateHTML = '<style>\n:where(*, *::before, *::after) {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n margin: 0;\n font: inherit;\n}\n\n.info {\n display: flex;\n flex-flow: column;\n font: var(--sinch-sys-font-body-xs);\n}\n</style>\n\n<section class="info" id="info-container">\n <slot name="contacts"></slot>\n <slot></slot>\n</section>\n';
|
|
5
|
+
const template = document.createElement("template");
|
|
6
6
|
template.innerHTML = templateHTML;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const options = this.#getOptionElements();
|
|
38
|
-
// If no options are provided, show placeholder data
|
|
39
|
-
if (options.length === 0) {
|
|
40
|
-
this.#showPlaceholders();
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
#getOptionElements() {
|
|
44
|
-
const assignedElements = this.#optionSlot.assignedElements();
|
|
45
|
-
return assignedElements.filter((el) => el.tagName.toLowerCase() === 'sinch-labs-phone-preview-rcs-channel-info-option');
|
|
46
|
-
}
|
|
47
|
-
#showPlaceholders() {
|
|
48
|
-
// Create placeholder options when no content is provided
|
|
49
|
-
const placeholders = [
|
|
50
|
-
{ type: 'phone', contact: '+1234567890', label: 'Contact us' },
|
|
51
|
-
{ type: 'website', contact: 'https://company.com', label: 'Contact us' },
|
|
52
|
-
{ type: 'email', contact: 'mail@company.com', label: 'Contact us' },
|
|
53
|
-
];
|
|
54
|
-
placeholders.forEach(({ type, contact, label }) => {
|
|
55
|
-
const option = document.createElement('sinch-labs-phone-preview-rcs-channel-info-option');
|
|
56
|
-
option.setAttribute('type', type);
|
|
57
|
-
option.setAttribute('contact', contact);
|
|
58
|
-
option.setAttribute('label', label);
|
|
59
|
-
option.setAttribute('placeholder', '');
|
|
60
|
-
this.appendChild(option);
|
|
61
|
-
});
|
|
7
|
+
class PhonePreviewRcsChannelInfo extends NectaryElement {
|
|
8
|
+
#optionSlot;
|
|
9
|
+
#controller = null;
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
const shadowRoot = this.attachShadow();
|
|
13
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
14
|
+
this.#optionSlot = shadowRoot.querySelector("slot");
|
|
15
|
+
}
|
|
16
|
+
connectedCallback() {
|
|
17
|
+
super.connectedCallback();
|
|
18
|
+
this.#controller = new AbortController();
|
|
19
|
+
const { signal } = this.#controller;
|
|
20
|
+
this.#optionSlot.addEventListener("slotchange", this.#onSlotChange, { signal });
|
|
21
|
+
this.#onSlotChange();
|
|
22
|
+
}
|
|
23
|
+
disconnectedCallback() {
|
|
24
|
+
super.disconnectedCallback();
|
|
25
|
+
this.#controller?.abort();
|
|
26
|
+
this.#controller = null;
|
|
27
|
+
}
|
|
28
|
+
static get observedAttributes() {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
32
|
+
}
|
|
33
|
+
#onSlotChange = () => {
|
|
34
|
+
const options = this.#getOptionElements();
|
|
35
|
+
if (options.length === 0) {
|
|
36
|
+
this.#showPlaceholders();
|
|
62
37
|
}
|
|
38
|
+
};
|
|
39
|
+
#getOptionElements() {
|
|
40
|
+
const assignedElements = this.#optionSlot.assignedElements();
|
|
41
|
+
return assignedElements.filter((el) => el.tagName.toLowerCase() === "sinch-labs-phone-preview-rcs-channel-info-option");
|
|
42
|
+
}
|
|
43
|
+
#showPlaceholders() {
|
|
44
|
+
const placeholders = [
|
|
45
|
+
{ type: "phone", contact: "+1234567890", label: "Contact us" },
|
|
46
|
+
{ type: "website", contact: "https://company.com", label: "Contact us" },
|
|
47
|
+
{ type: "email", contact: "mail@company.com", label: "Contact us" }
|
|
48
|
+
];
|
|
49
|
+
placeholders.forEach(({ type, contact, label }) => {
|
|
50
|
+
const option = document.createElement("sinch-labs-phone-preview-rcs-channel-info-option");
|
|
51
|
+
option.setAttribute("type", type);
|
|
52
|
+
option.setAttribute("contact", contact);
|
|
53
|
+
option.setAttribute("label", label);
|
|
54
|
+
option.setAttribute("placeholder", "");
|
|
55
|
+
this.appendChild(option);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
63
58
|
}
|
|
64
|
-
defineCustomElement(
|
|
59
|
+
defineCustomElement("sinch-labs-phone-preview-rcs-channel-info", PhonePreviewRcsChannelInfo);
|
|
60
|
+
export {
|
|
61
|
+
PhonePreviewRcsChannelInfo
|
|
62
|
+
};
|
|
@@ -1,106 +1,101 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defineCustomElement, NectaryElement } from
|
|
3
|
-
|
|
4
|
-
const template = document.createElement(
|
|
1
|
+
import "@nectary/components/icon";
|
|
2
|
+
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
3
|
+
const templateHTML = '<style>\n:where(*, *::before, *::after) {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n margin: 0;\n font: inherit;\n}\n\na {\n display: grid;\n grid-template:\n "icon contact" auto\n "icon label " auto\n / auto 1fr;\n align-items: center;\n gap: 0 16px;\n padding: 8px 16px;\n border-block-end:\n 1px solid\n var(--sinch-sys-color-surface-secondary-active);\n color: currentcolor;\n word-break: break-all;\n text-decoration: none;\n}\n\na > sinch-icon {\n grid-area: icon;\n}\n\na > #contact {\n grid-area: contact;\n}\n\na > #contact::before {\n content: "\\200b";\n}\n\na > #label {\n grid-area: label;\n}\n\na > #label::before {\n content: "\\200b";\n}\n\na[inert] {\n --sinch-global-color-icon: currentcolor;\n\n color: var(--sinch-sys-color-text-muted);\n}\n</style>\n\n<a target="_blank">\n <sinch-icon icons-version="2"></sinch-icon>\n <span id="contact"></span>\n <p id="label"></p>\n</a>\n';
|
|
4
|
+
const template = document.createElement("template");
|
|
5
5
|
template.innerHTML = templateHTML;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
class PhonePreviewRcsChannelInfoOption extends NectaryElement {
|
|
7
|
+
#link;
|
|
8
|
+
#icon;
|
|
9
|
+
#contact;
|
|
10
|
+
#label;
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
const shadowRoot = this.attachShadow();
|
|
14
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
15
|
+
this.#link = shadowRoot.querySelector("a");
|
|
16
|
+
this.#icon = shadowRoot.querySelector("sinch-icon");
|
|
17
|
+
this.#contact = shadowRoot.querySelector("#contact");
|
|
18
|
+
this.#label = shadowRoot.querySelector("#label");
|
|
19
|
+
}
|
|
20
|
+
connectedCallback() {
|
|
21
|
+
super.connectedCallback();
|
|
22
|
+
this.#updateUI();
|
|
23
|
+
}
|
|
24
|
+
static get observedAttributes() {
|
|
25
|
+
return ["type", "contact", "label", "placeholder"];
|
|
26
|
+
}
|
|
27
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
28
|
+
if (oldVal === newVal) {
|
|
29
|
+
return;
|
|
19
30
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
this.#updateUI();
|
|
32
|
+
}
|
|
33
|
+
get type() {
|
|
34
|
+
return this.getAttribute("type") ?? "phone";
|
|
35
|
+
}
|
|
36
|
+
set type(value) {
|
|
37
|
+
this.setAttribute("type", value);
|
|
38
|
+
}
|
|
39
|
+
get contact() {
|
|
40
|
+
return this.getAttribute("contact") ?? "";
|
|
41
|
+
}
|
|
42
|
+
set contact(value) {
|
|
43
|
+
this.setAttribute("contact", value);
|
|
44
|
+
}
|
|
45
|
+
get label() {
|
|
46
|
+
return this.getAttribute("label") ?? "";
|
|
47
|
+
}
|
|
48
|
+
set label(value) {
|
|
49
|
+
this.setAttribute("label", value);
|
|
50
|
+
}
|
|
51
|
+
get placeholder() {
|
|
52
|
+
return this.hasAttribute("placeholder");
|
|
53
|
+
}
|
|
54
|
+
set placeholder(value) {
|
|
55
|
+
if (value) {
|
|
56
|
+
this.setAttribute("placeholder", "");
|
|
57
|
+
} else {
|
|
58
|
+
this.removeAttribute("placeholder");
|
|
23
59
|
}
|
|
24
|
-
|
|
25
|
-
|
|
60
|
+
}
|
|
61
|
+
#updateUI() {
|
|
62
|
+
if (!this.isDomConnected) {
|
|
63
|
+
return;
|
|
26
64
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
const type = this.type;
|
|
66
|
+
const contact = this.contact;
|
|
67
|
+
const label = this.label;
|
|
68
|
+
const isPlaceholder = this.placeholder;
|
|
69
|
+
let iconName = "fa-phone";
|
|
70
|
+
let href = `tel:${contact}`;
|
|
71
|
+
switch (type) {
|
|
72
|
+
case "website":
|
|
73
|
+
iconName = "fa-earth-americas";
|
|
74
|
+
href = contact;
|
|
75
|
+
break;
|
|
76
|
+
case "email":
|
|
77
|
+
iconName = "envelope";
|
|
78
|
+
href = `mailto:${contact}`;
|
|
79
|
+
break;
|
|
80
|
+
case "phone":
|
|
81
|
+
default:
|
|
82
|
+
iconName = "fa-phone";
|
|
83
|
+
href = `tel:${contact}`;
|
|
84
|
+
break;
|
|
32
85
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return this.getAttribute('contact') ?? '';
|
|
41
|
-
}
|
|
42
|
-
set contact(value) {
|
|
43
|
-
this.setAttribute('contact', value);
|
|
44
|
-
}
|
|
45
|
-
get label() {
|
|
46
|
-
return this.getAttribute('label') ?? '';
|
|
47
|
-
}
|
|
48
|
-
set label(value) {
|
|
49
|
-
this.setAttribute('label', value);
|
|
50
|
-
}
|
|
51
|
-
get placeholder() {
|
|
52
|
-
return this.hasAttribute('placeholder');
|
|
53
|
-
}
|
|
54
|
-
set placeholder(value) {
|
|
55
|
-
if (value) {
|
|
56
|
-
this.setAttribute('placeholder', '');
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
this.removeAttribute('placeholder');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
#updateUI() {
|
|
63
|
-
if (!this.isDomConnected) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const type = this.type;
|
|
67
|
-
const contact = this.contact;
|
|
68
|
-
const label = this.label;
|
|
69
|
-
const isPlaceholder = this.placeholder;
|
|
70
|
-
// Set icon based on type
|
|
71
|
-
let iconName = 'fa-phone';
|
|
72
|
-
let href = `tel:${contact}`;
|
|
73
|
-
switch (type) {
|
|
74
|
-
case 'website':
|
|
75
|
-
iconName = 'fa-earth-americas';
|
|
76
|
-
href = contact;
|
|
77
|
-
break;
|
|
78
|
-
case 'email':
|
|
79
|
-
iconName = 'envelope';
|
|
80
|
-
href = `mailto:${contact}`;
|
|
81
|
-
break;
|
|
82
|
-
case 'phone':
|
|
83
|
-
default:
|
|
84
|
-
iconName = 'fa-phone';
|
|
85
|
-
href = `tel:${contact}`;
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
// Update icon
|
|
89
|
-
this.#icon.setAttribute('name', iconName);
|
|
90
|
-
// Update link
|
|
91
|
-
this.#link.href = href;
|
|
92
|
-
this.#link.target = '_blank';
|
|
93
|
-
// Set inert if it's a placeholder
|
|
94
|
-
if (isPlaceholder) {
|
|
95
|
-
this.#link.setAttribute('inert', '');
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
this.#link.removeAttribute('inert');
|
|
99
|
-
}
|
|
100
|
-
// Update contact text
|
|
101
|
-
this.#contact.textContent = contact;
|
|
102
|
-
// Update label text
|
|
103
|
-
this.#label.textContent = label;
|
|
86
|
+
this.#icon.setAttribute("name", iconName);
|
|
87
|
+
this.#link.href = href;
|
|
88
|
+
this.#link.target = "_blank";
|
|
89
|
+
if (isPlaceholder) {
|
|
90
|
+
this.#link.setAttribute("inert", "");
|
|
91
|
+
} else {
|
|
92
|
+
this.#link.removeAttribute("inert");
|
|
104
93
|
}
|
|
94
|
+
this.#contact.textContent = contact;
|
|
95
|
+
this.#label.textContent = label;
|
|
96
|
+
}
|
|
105
97
|
}
|
|
106
|
-
defineCustomElement(
|
|
98
|
+
defineCustomElement("sinch-labs-phone-preview-rcs-channel-info-option", PhonePreviewRcsChannelInfoOption);
|
|
99
|
+
export {
|
|
100
|
+
PhonePreviewRcsChannelInfoOption
|
|
101
|
+
};
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { defineCustomElement, NectaryElement } from
|
|
2
|
-
|
|
3
|
-
const template = document.createElement(
|
|
1
|
+
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
2
|
+
const templateHTML = '<style>\n:where(*, *::before, *::after) {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n margin: 0;\n font: inherit;\n}\n\n.options {\n display: flex;\n flex-flow: column;\n font: var(--sinch-sys-font-body-xs);\n}\n\n.options > header {\n padding-block-end: 8px;\n}\n\n.options > span {\n font: var(--sinch-sys-font-body-xxs);\n}\n\n.options > button {\n padding: 4px;\n outline: none;\n background: transparent;\n text-align: start;\n}\n\n.options > hr {\n border-color: var(--sinch-sys-color-surface-secondary-active);\n}\n</style>\n\n<section class="options" id="options-container">\n <header>Notifications</header>\n <span>Business</span>\n <button>Block & report spam</button>\n <hr />\n <button>View Privacy Policy</button>\n <hr />\n <button>View Terms of Service</button>\n <hr />\n <button>Learn mode</button>\n</section>\n';
|
|
3
|
+
const template = document.createElement("template");
|
|
4
4
|
template.innerHTML = templateHTML;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
5
|
+
class PhonePreviewRcsChannelOptions extends NectaryElement {
|
|
6
|
+
#optionsContainer;
|
|
7
|
+
#controller = null;
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
const shadowRoot = this.attachShadow();
|
|
11
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
12
|
+
this.#optionsContainer = shadowRoot.querySelector("#options-container");
|
|
13
|
+
}
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
super.connectedCallback();
|
|
16
|
+
this.#controller = new AbortController();
|
|
17
|
+
const { signal } = this.#controller;
|
|
18
|
+
this.#optionsContainer.addEventListener("click", this.#onOptionClick, { signal });
|
|
19
|
+
}
|
|
20
|
+
disconnectedCallback() {
|
|
21
|
+
super.disconnectedCallback();
|
|
22
|
+
this.#controller?.abort();
|
|
23
|
+
this.#controller = null;
|
|
24
|
+
}
|
|
25
|
+
static get observedAttributes() {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
29
|
+
}
|
|
30
|
+
#onOptionClick = (event) => {
|
|
31
|
+
const target = event.target;
|
|
32
|
+
if (target.tagName === "BUTTON") {
|
|
33
|
+
const buttonText = target.textContent?.trim();
|
|
34
|
+
this.dispatchEvent(new CustomEvent("-option-click", {
|
|
35
|
+
detail: {
|
|
36
|
+
action: buttonText,
|
|
37
|
+
element: target
|
|
31
38
|
}
|
|
39
|
+
}));
|
|
32
40
|
}
|
|
33
|
-
|
|
34
|
-
const target = event.target;
|
|
35
|
-
if (target.tagName === 'BUTTON') {
|
|
36
|
-
const buttonText = target.textContent?.trim();
|
|
37
|
-
this.dispatchEvent(new CustomEvent('-option-click', {
|
|
38
|
-
detail: {
|
|
39
|
-
action: buttonText,
|
|
40
|
-
element: target,
|
|
41
|
-
},
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
};
|
|
41
|
+
};
|
|
45
42
|
}
|
|
46
|
-
defineCustomElement(
|
|
43
|
+
defineCustomElement("sinch-labs-phone-preview-rcs-channel-options", PhonePreviewRcsChannelOptions);
|
|
44
|
+
export {
|
|
45
|
+
PhonePreviewRcsChannelOptions
|
|
46
|
+
};
|
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import { defineCustomElement, NectaryElement } from
|
|
2
|
-
|
|
3
|
-
const template = document.createElement(
|
|
1
|
+
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
2
|
+
const templateHTML = '<style>\n:where(*, *::before, *::after) {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n margin: 0;\n font: inherit;\n}\n\n.tabs {\n --highlight-color: var(--sinch-sys-color-text-default);\n\n display: flex;\n}\n\n.tabs > button {\n flex: 1;\n padding-block-end: 10px;\n border-block-end: 2px solid transparent;\n outline: none;\n background: transparent;\n color: var(--sinch-sys-color-text-disabled);\n font: var(--sinch-sys-font-desktop-title-xs);\n}\n\n.tabs > button.active {\n color: var(--sinch-sys-color-primary-default);\n border-block-end: 2px solid var(--highlight-color);\n}\n</style>\n\n<section class="tabs" id="tabs-container">\n <button>Info</button>\n <button>Options</button>\n</section>\n';
|
|
3
|
+
const template = document.createElement("template");
|
|
4
4
|
template.innerHTML = templateHTML;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
class PhonePreviewRcsChannelTabs extends NectaryElement {
|
|
6
|
+
#tabsContainer;
|
|
7
|
+
#controller = null;
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
const shadowRoot = this.attachShadow();
|
|
11
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
12
|
+
this.#tabsContainer = shadowRoot.querySelector("#tabs-container");
|
|
13
|
+
}
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
super.connectedCallback();
|
|
16
|
+
this.#controller = new AbortController();
|
|
17
|
+
const { signal } = this.#controller;
|
|
18
|
+
this.#tabsContainer.addEventListener("click", this.#onTabClick, { signal });
|
|
19
|
+
this.#updateUI();
|
|
20
|
+
}
|
|
21
|
+
disconnectedCallback() {
|
|
22
|
+
super.disconnectedCallback();
|
|
23
|
+
this.#controller?.abort();
|
|
24
|
+
this.#controller = null;
|
|
25
|
+
}
|
|
26
|
+
static get observedAttributes() {
|
|
27
|
+
return ["color", "active-tab"];
|
|
28
|
+
}
|
|
29
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
30
|
+
if (oldVal === newVal) {
|
|
31
|
+
return;
|
|
13
32
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
this.#updateUI();
|
|
34
|
+
}
|
|
35
|
+
get color() {
|
|
36
|
+
return this.getAttribute("color") ?? "var(--sinch-sys-color-primary-default)";
|
|
37
|
+
}
|
|
38
|
+
set color(value) {
|
|
39
|
+
this.setAttribute("color", value);
|
|
40
|
+
}
|
|
41
|
+
get activeTab() {
|
|
42
|
+
const value = this.getAttribute("active-tab");
|
|
43
|
+
return value !== null ? parseInt(value, 10) : 0;
|
|
44
|
+
}
|
|
45
|
+
set activeTab(value) {
|
|
46
|
+
this.setAttribute("active-tab", value.toString());
|
|
47
|
+
}
|
|
48
|
+
#updateUI() {
|
|
49
|
+
if (!this.isDomConnected) {
|
|
50
|
+
return;
|
|
20
51
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
52
|
+
this.#tabsContainer.style.setProperty("--highlight-color", this.color);
|
|
53
|
+
const buttons = this.#tabsContainer.querySelectorAll("button");
|
|
54
|
+
buttons.forEach((button, index) => {
|
|
55
|
+
if (index === this.activeTab) {
|
|
56
|
+
button.classList.add("active");
|
|
57
|
+
} else {
|
|
58
|
+
button.classList.remove("active");
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
#onTabClick = (event) => {
|
|
63
|
+
const target = event.target;
|
|
64
|
+
if (target.tagName === "BUTTON") {
|
|
65
|
+
const buttons = Array.from(this.#tabsContainer.querySelectorAll("button"));
|
|
66
|
+
const clickedIndex = buttons.indexOf(target);
|
|
67
|
+
if (clickedIndex !== -1) {
|
|
68
|
+
this.activeTab = clickedIndex;
|
|
69
|
+
this.dispatchEvent(new CustomEvent("-tab-change", {
|
|
70
|
+
detail: clickedIndex
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
25
73
|
}
|
|
26
|
-
|
|
27
|
-
return ['color', 'active-tab'];
|
|
28
|
-
}
|
|
29
|
-
attributeChangedCallback(name, oldVal, newVal) {
|
|
30
|
-
if (oldVal === newVal) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
this.#updateUI();
|
|
34
|
-
}
|
|
35
|
-
get color() {
|
|
36
|
-
return this.getAttribute('color') ?? 'var(--sinch-sys-color-primary-default)';
|
|
37
|
-
}
|
|
38
|
-
set color(value) {
|
|
39
|
-
this.setAttribute('color', value);
|
|
40
|
-
}
|
|
41
|
-
get activeTab() {
|
|
42
|
-
const value = this.getAttribute('active-tab');
|
|
43
|
-
return (value !== null) ? parseInt(value, 10) : 0;
|
|
44
|
-
}
|
|
45
|
-
set activeTab(value) {
|
|
46
|
-
this.setAttribute('active-tab', value.toString());
|
|
47
|
-
}
|
|
48
|
-
#updateUI() {
|
|
49
|
-
if (!this.isDomConnected) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
// Update CSS custom property for highlight color
|
|
53
|
-
this.#tabsContainer.style.setProperty('--highlight-color', this.color);
|
|
54
|
-
// Update active tab state
|
|
55
|
-
const buttons = this.#tabsContainer.querySelectorAll('button');
|
|
56
|
-
buttons.forEach((button, index) => {
|
|
57
|
-
if (index === this.activeTab) {
|
|
58
|
-
button.classList.add('active');
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
button.classList.remove('active');
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
#onTabClick = (event) => {
|
|
66
|
-
const target = event.target;
|
|
67
|
-
if (target.tagName === 'BUTTON') {
|
|
68
|
-
const buttons = Array.from(this.#tabsContainer.querySelectorAll('button'));
|
|
69
|
-
const clickedIndex = buttons.indexOf(target);
|
|
70
|
-
if (clickedIndex !== -1) {
|
|
71
|
-
this.activeTab = clickedIndex;
|
|
72
|
-
this.dispatchEvent(new CustomEvent('-tab-change', {
|
|
73
|
-
detail: clickedIndex,
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
};
|
|
74
|
+
};
|
|
78
75
|
}
|
|
79
|
-
defineCustomElement(
|
|
76
|
+
defineCustomElement("sinch-labs-phone-preview-rcs-channel-tabs", PhonePreviewRcsChannelTabs);
|
|
77
|
+
export {
|
|
78
|
+
PhonePreviewRcsChannelTabs
|
|
79
|
+
};
|