@nectary/labs 2.3.4 → 2.4.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.
Files changed (35) hide show
  1. package/README.md +354 -0
  2. package/color-select/index.d.ts +39 -0
  3. package/color-select/index.js +96 -0
  4. package/index.d.ts +2 -0
  5. package/index.js +3 -0
  6. package/package.json +2 -6
  7. package/{phone-preview.d.ts → phone-preview/index.d.ts} +18 -7
  8. package/phone-preview/index.js +94 -0
  9. package/phone-preview-rcs-channel/index.d.ts +49 -0
  10. package/phone-preview-rcs-channel/index.js +175 -0
  11. package/phone-preview-rcs-channel-actions/index.d.ts +37 -0
  12. package/phone-preview-rcs-channel-actions/index.js +126 -0
  13. package/phone-preview-rcs-channel-info/index.d.ts +29 -0
  14. package/phone-preview-rcs-channel-info/index.js +64 -0
  15. package/phone-preview-rcs-channel-info-option/index.d.ts +40 -0
  16. package/phone-preview-rcs-channel-info-option/index.js +106 -0
  17. package/phone-preview-rcs-channel-options/index.d.ts +27 -0
  18. package/phone-preview-rcs-channel-options/index.js +46 -0
  19. package/phone-preview-rcs-channel-tabs/index.d.ts +34 -0
  20. package/phone-preview-rcs-channel-tabs/index.js +79 -0
  21. package/{phone-preview-rcs-chat.d.ts → phone-preview-rcs-chat/index.d.ts} +20 -8
  22. package/phone-preview-rcs-chat/index.js +79 -0
  23. package/phone-preview-rcs-chat-message/index.d.ts +35 -0
  24. package/phone-preview-rcs-chat-message/index.js +48 -0
  25. package/utils/element.d.ts +9 -0
  26. package/utils/element.js +35 -0
  27. package/utils/index.d.ts +1 -1
  28. package/utils/index.js +1 -1
  29. package/Readme.md +0 -1
  30. package/color-select.d.ts +0 -34
  31. package/color-select.js +0 -79
  32. package/phone-preview-rcs-channel.d.ts +0 -50
  33. package/phone-preview-rcs-channel.js +0 -319
  34. package/phone-preview-rcs-chat.js +0 -162
  35. package/phone-preview.js +0 -120
@@ -0,0 +1,49 @@
1
+ import '@nectary/components/icon';
2
+ import { NectaryElement } from '../utils';
3
+ import '../phone-preview-rcs-channel-actions';
4
+ import '../phone-preview-rcs-channel-info';
5
+ import '../phone-preview-rcs-channel-info-option';
6
+ import '../phone-preview-rcs-channel-options';
7
+ import '../phone-preview-rcs-channel-tabs';
8
+ import type React from 'react';
9
+ export declare class PhonePreviewRcsChannel extends NectaryElement {
10
+ #private;
11
+ constructor();
12
+ connectedCallback(): void;
13
+ disconnectedCallback(): void;
14
+ static get observedAttributes(): string[];
15
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
16
+ get name(): string;
17
+ set name(value: string);
18
+ get description(): string;
19
+ set description(value: string);
20
+ get color(): string;
21
+ set color(value: string);
22
+ get banner(): string;
23
+ set banner(value: string);
24
+ get logo(): string;
25
+ set logo(value: string);
26
+ }
27
+ type RcsChannelProps = {
28
+ name?: string;
29
+ description?: string;
30
+ color?: string;
31
+ banner?: string;
32
+ logo?: string;
33
+ };
34
+ type RcsChannelElementProps = Partial<{
35
+ [K in keyof RcsChannelProps]: RcsChannelProps[K] | string;
36
+ }>;
37
+ declare global {
38
+ interface HTMLElementTagNameMap {
39
+ 'sinch-labs-phone-preview-rcs-channel': RcsChannelElementProps & HTMLElement;
40
+ }
41
+ }
42
+ declare module 'react' {
43
+ namespace JSX {
44
+ interface IntrinsicElements {
45
+ 'sinch-labs-phone-preview-rcs-channel': RcsChannelElementProps & React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement>;
46
+ }
47
+ }
48
+ }
49
+ export {};
@@ -0,0 +1,175 @@
1
+ import '@nectary/components/icon';
2
+ import { defineCustomElement, NectaryElement } from '../utils';
3
+ import '../phone-preview-rcs-channel-actions';
4
+ import '../phone-preview-rcs-channel-info';
5
+ import '../phone-preview-rcs-channel-info-option';
6
+ import '../phone-preview-rcs-channel-options';
7
+ import '../phone-preview-rcs-channel-tabs';
8
+ import templateHTML from './template.html';
9
+ const template = document.createElement('template');
10
+ template.innerHTML = templateHTML;
11
+ export class PhonePreviewRcsChannel extends NectaryElement {
12
+ #bannerImg;
13
+ #logoImg;
14
+ #brandName;
15
+ #brandDescription;
16
+ #actions;
17
+ #tabs;
18
+ #infoContainer;
19
+ #optionsContainer;
20
+ #controller = null;
21
+ #currentTab = 0;
22
+ constructor() {
23
+ super();
24
+ const shadowRoot = this.attachShadow();
25
+ shadowRoot.appendChild(template.content.cloneNode(true));
26
+ this.#bannerImg = shadowRoot.querySelector('#banner-img');
27
+ this.#logoImg = shadowRoot.querySelector('#logo-img');
28
+ this.#brandName = shadowRoot.querySelector('#brand-name');
29
+ this.#brandDescription = shadowRoot.querySelector('#brand-description');
30
+ this.#actions = shadowRoot.querySelector('#actions');
31
+ this.#tabs = shadowRoot.querySelector('#tabs');
32
+ this.#infoContainer = shadowRoot.querySelector('#info-container');
33
+ this.#optionsContainer = shadowRoot.querySelector('#options-container');
34
+ }
35
+ connectedCallback() {
36
+ super.connectedCallback();
37
+ this.#controller = new AbortController();
38
+ const { signal } = this.#controller;
39
+ this.#tabs.addEventListener('-tab-change', this.#onTabChange, { signal });
40
+ // Listen for changes in slotted children
41
+ this.addEventListener('slotchange', this.#onSlotChange, { signal });
42
+ // Watch for changes to child elements
43
+ const observer = new MutationObserver(() => {
44
+ this.#updateActionsFromSlottedChildren();
45
+ });
46
+ observer.observe(this, { childList: true, subtree: true });
47
+ // Clean up observer when disconnected
48
+ signal.addEventListener('abort', () => {
49
+ observer.disconnect();
50
+ });
51
+ this.#updateUI();
52
+ this.#updateTabContent();
53
+ }
54
+ disconnectedCallback() {
55
+ super.disconnectedCallback();
56
+ this.#controller?.abort();
57
+ this.#controller = null;
58
+ }
59
+ static get observedAttributes() {
60
+ return ['name', 'description', 'color', 'banner', 'logo'];
61
+ }
62
+ attributeChangedCallback(name, oldVal, newVal) {
63
+ if (oldVal === newVal) {
64
+ return;
65
+ }
66
+ switch (name) {
67
+ case 'name':
68
+ case 'description':
69
+ case 'color':
70
+ case 'banner':
71
+ case 'logo':
72
+ this.#updateUI();
73
+ break;
74
+ }
75
+ }
76
+ get name() {
77
+ return this.getAttribute('name') ?? '';
78
+ }
79
+ set name(value) {
80
+ this.setAttribute('name', value);
81
+ }
82
+ get description() {
83
+ return this.getAttribute('description') ?? '';
84
+ }
85
+ set description(value) {
86
+ this.setAttribute('description', value);
87
+ }
88
+ get color() {
89
+ return this.getAttribute('color') ?? '';
90
+ }
91
+ set color(value) {
92
+ this.setAttribute('color', value);
93
+ }
94
+ get banner() {
95
+ return this.getAttribute('banner') ?? '';
96
+ }
97
+ set banner(value) {
98
+ this.setAttribute('banner', value);
99
+ }
100
+ get logo() {
101
+ return this.getAttribute('logo') ?? '';
102
+ }
103
+ set logo(value) {
104
+ this.setAttribute('logo', value);
105
+ }
106
+ #updateUI() {
107
+ if (!this.isDomConnected) {
108
+ return;
109
+ }
110
+ // Transparent placeholder for empty images
111
+ const transparentIcon = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
112
+ // Update banner image
113
+ this.#bannerImg.src = this.banner !== '' ? this.banner : transparentIcon;
114
+ // Update logo image
115
+ this.#logoImg.src = this.logo !== '' ? this.logo : transparentIcon;
116
+ // Update brand name
117
+ this.#brandName.textContent = this.name !== '' ? this.name : 'Brand name';
118
+ // Update brand description
119
+ this.#brandDescription.textContent = this.description !== '' ? this.description : 'Brand description';
120
+ // Update banner color
121
+ if (this.color !== '') {
122
+ this.style.setProperty('--banner-color', this.color);
123
+ }
124
+ // Update actions component with data from slotted children
125
+ this.#updateActionsFromSlottedChildren();
126
+ // Update tabs color
127
+ this.#tabs.setAttribute('color', this.color);
128
+ }
129
+ #updateActionsFromSlottedChildren() {
130
+ // Get slotted contact options
131
+ const slottedElements = this.querySelectorAll('sinch-labs-phone-preview-rcs-channel-info-option');
132
+ // Find first phone, website, and email from slotted children
133
+ let firstPhone = '';
134
+ let firstWebsite = '';
135
+ let firstEmail = '';
136
+ for (const element of slottedElements) {
137
+ const type = element.getAttribute('type');
138
+ const contact = element.getAttribute('contact') ?? '';
139
+ if (type === 'phone' && firstPhone === '') {
140
+ firstPhone = contact;
141
+ }
142
+ else if (type === 'website' && firstWebsite === '') {
143
+ firstWebsite = contact;
144
+ }
145
+ else if (type === 'email' && firstEmail === '') {
146
+ firstEmail = contact;
147
+ }
148
+ }
149
+ this.#actions.setAttribute('phone', firstPhone);
150
+ this.#actions.setAttribute('website', firstWebsite);
151
+ this.#actions.setAttribute('email', firstEmail);
152
+ }
153
+ #updateTabContent() {
154
+ // No longer needed since we use slots
155
+ this.#updateTabVisibility();
156
+ }
157
+ #updateTabVisibility() {
158
+ if (this.#currentTab === 0) {
159
+ this.#infoContainer.style.display = 'block';
160
+ this.#optionsContainer.style.display = 'none';
161
+ }
162
+ else {
163
+ this.#infoContainer.style.display = 'none';
164
+ this.#optionsContainer.style.display = 'block';
165
+ }
166
+ }
167
+ #onSlotChange = () => {
168
+ this.#updateActionsFromSlottedChildren();
169
+ };
170
+ #onTabChange = (event) => {
171
+ this.#currentTab = event.detail;
172
+ this.#updateTabVisibility();
173
+ };
174
+ }
175
+ defineCustomElement('sinch-labs-phone-preview-rcs-channel', PhonePreviewRcsChannel);
@@ -0,0 +1,37 @@
1
+ import '@nectary/components/icon';
2
+ import { NectaryElement } from '../utils';
3
+ import type React from 'react';
4
+ export declare class PhonePreviewRcsChannelActions extends NectaryElement {
5
+ #private;
6
+ constructor();
7
+ connectedCallback(): void;
8
+ static get observedAttributes(): string[];
9
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
10
+ get phone(): string;
11
+ set phone(value: string);
12
+ get website(): string;
13
+ set website(value: string);
14
+ get email(): string;
15
+ set email(value: string);
16
+ }
17
+ type Props = {
18
+ phone?: string;
19
+ website?: string;
20
+ email?: string;
21
+ };
22
+ type ElementProps = Partial<{
23
+ [K in keyof Props]: Props[K] | string;
24
+ }>;
25
+ declare global {
26
+ interface HTMLElementTagNameMap {
27
+ 'sinch-labs-phone-preview-rcs-channel-actions': ElementProps & HTMLElement;
28
+ }
29
+ }
30
+ declare module 'react' {
31
+ namespace JSX {
32
+ interface IntrinsicElements {
33
+ 'sinch-labs-phone-preview-rcs-channel-actions': ElementProps & React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement>;
34
+ }
35
+ }
36
+ }
37
+ export {};
@@ -0,0 +1,126 @@
1
+ import '@nectary/components/icon';
2
+ import { defineCustomElement, NectaryElement } from '../utils';
3
+ import templateHTML from './template.html';
4
+ const template = document.createElement('template');
5
+ template.innerHTML = templateHTML;
6
+ console.log(template);
7
+ export class PhonePreviewRcsChannelActions extends NectaryElement {
8
+ #callAction;
9
+ #websiteAction;
10
+ #emailAction;
11
+ constructor() {
12
+ super();
13
+ console.log('[PhonePreviewRcsChannelActions] Constructor called');
14
+ const shadowRoot = this.attachShadow();
15
+ shadowRoot.appendChild(template.content.cloneNode(true));
16
+ this.#callAction = shadowRoot.querySelector('#call-action');
17
+ this.#websiteAction = shadowRoot.querySelector('#website-action');
18
+ this.#emailAction = shadowRoot.querySelector('#email-action');
19
+ console.log('[PhonePreviewRcsChannelActions] Elements queried:', {
20
+ callAction: this.#callAction,
21
+ websiteAction: this.#websiteAction,
22
+ emailAction: this.#emailAction,
23
+ });
24
+ }
25
+ connectedCallback() {
26
+ console.log('[PhonePreviewRcsChannelActions] Connected to DOM');
27
+ super.connectedCallback();
28
+ this.#updateUI();
29
+ }
30
+ static get observedAttributes() {
31
+ return ['phone', 'website', 'email'];
32
+ }
33
+ attributeChangedCallback(name, oldVal, newVal) {
34
+ console.log(`[PhonePreviewRcsChannelActions] Attribute "${name}" changed from "${oldVal}" to "${newVal}"`);
35
+ if (oldVal === newVal) {
36
+ return;
37
+ }
38
+ this.#updateUI();
39
+ }
40
+ get phone() {
41
+ return this.getAttribute('phone') ?? '';
42
+ }
43
+ set phone(value) {
44
+ console.log(`[PhonePreviewRcsChannelActions] Setting phone to "${value}"`);
45
+ if (value !== '') {
46
+ this.setAttribute('phone', value);
47
+ }
48
+ else {
49
+ this.removeAttribute('phone');
50
+ }
51
+ }
52
+ get website() {
53
+ return this.getAttribute('website') ?? '';
54
+ }
55
+ set website(value) {
56
+ console.log(`[PhonePreviewRcsChannelActions] Setting website to "${value}"`);
57
+ if (value !== '') {
58
+ this.setAttribute('website', value);
59
+ }
60
+ else {
61
+ this.removeAttribute('website');
62
+ }
63
+ }
64
+ get email() {
65
+ return this.getAttribute('email') ?? '';
66
+ }
67
+ set email(value) {
68
+ console.log(`[PhonePreviewRcsChannelActions] Setting email to "${value}"`);
69
+ if (value !== '') {
70
+ this.setAttribute('email', value);
71
+ }
72
+ else {
73
+ this.removeAttribute('email');
74
+ }
75
+ }
76
+ #updateUI() {
77
+ console.log('[PhonePreviewRcsChannelActions] Updating UI');
78
+ if (!this.isDomConnected) {
79
+ console.log('[PhonePreviewRcsChannelActions] DOM not connected, skipping UI update');
80
+ return;
81
+ }
82
+ // Get contact values directly as strings
83
+ const phoneNumber = this.phone;
84
+ const websiteUrl = this.website;
85
+ const emailAddress = this.email;
86
+ console.log('[PhonePreviewRcsChannelActions] Current values:', {
87
+ phone: phoneNumber,
88
+ website: websiteUrl,
89
+ email: emailAddress,
90
+ });
91
+ // Update call action
92
+ if (phoneNumber !== '') {
93
+ this.#callAction.href = `tel:${phoneNumber}`;
94
+ this.#callAction.removeAttribute('inert');
95
+ console.log(`[PhonePreviewRcsChannelActions] Enabling call action with href: ${this.#callAction.href}`);
96
+ }
97
+ else {
98
+ this.#callAction.href = '#';
99
+ this.#callAction.setAttribute('inert', '');
100
+ console.log('[PhonePreviewRcsChannelActions] Disabling call action');
101
+ }
102
+ // Update website action
103
+ if (websiteUrl !== '') {
104
+ this.#websiteAction.href = websiteUrl;
105
+ this.#websiteAction.removeAttribute('inert');
106
+ console.log(`[PhonePreviewRcsChannelActions] Enabling website action with href: ${this.#websiteAction.href}`);
107
+ }
108
+ else {
109
+ this.#websiteAction.href = '#';
110
+ this.#websiteAction.setAttribute('inert', '');
111
+ console.log('[PhonePreviewRcsChannelActions] Disabling website action');
112
+ }
113
+ // Update email action
114
+ if (emailAddress !== '') {
115
+ this.#emailAction.href = `mailto:${emailAddress}`;
116
+ this.#emailAction.removeAttribute('inert');
117
+ console.log(`[PhonePreviewRcsChannelActions] Enabling email action with href: ${this.#emailAction.href}`);
118
+ }
119
+ else {
120
+ this.#emailAction.href = '#';
121
+ this.#emailAction.setAttribute('inert', '');
122
+ console.log('[PhonePreviewRcsChannelActions] Disabling email action');
123
+ }
124
+ }
125
+ }
126
+ defineCustomElement('sinch-labs-phone-preview-rcs-channel-actions', PhonePreviewRcsChannelActions);
@@ -0,0 +1,29 @@
1
+ import '@nectary/components/icon';
2
+ import { NectaryElement } from '../utils';
3
+ import '../phone-preview-rcs-channel-info-option';
4
+ import type React from 'react';
5
+ export declare class PhonePreviewRcsChannelInfo extends NectaryElement {
6
+ #private;
7
+ constructor();
8
+ connectedCallback(): void;
9
+ disconnectedCallback(): void;
10
+ static get observedAttributes(): never[];
11
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
12
+ }
13
+ type Props = {};
14
+ type ElementProps = Partial<{
15
+ [K in keyof Props]: Props[K] | string;
16
+ }>;
17
+ declare global {
18
+ interface HTMLElementTagNameMap {
19
+ 'sinch-labs-phone-preview-rcs-channel-info': ElementProps & HTMLElement;
20
+ }
21
+ }
22
+ declare module 'react' {
23
+ namespace JSX {
24
+ interface IntrinsicElements {
25
+ 'sinch-labs-phone-preview-rcs-channel-info': ElementProps & React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement>;
26
+ }
27
+ }
28
+ }
29
+ export {};
@@ -0,0 +1,64 @@
1
+ import '@nectary/components/icon';
2
+ import { defineCustomElement, NectaryElement } from '../utils';
3
+ import '../phone-preview-rcs-channel-info-option';
4
+ import templateHTML from './template.html';
5
+ const template = document.createElement('template');
6
+ template.innerHTML = templateHTML;
7
+ export 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
+ if (oldVal === newVal) {
33
+ // No change needed
34
+ }
35
+ }
36
+ #onSlotChange = () => {
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
+ });
62
+ }
63
+ }
64
+ defineCustomElement('sinch-labs-phone-preview-rcs-channel-info', PhonePreviewRcsChannelInfo);
@@ -0,0 +1,40 @@
1
+ import '@nectary/components/icon';
2
+ import { NectaryElement } from '../utils';
3
+ import type React from 'react';
4
+ export declare class PhonePreviewRcsChannelInfoOption extends NectaryElement {
5
+ #private;
6
+ constructor();
7
+ connectedCallback(): void;
8
+ static get observedAttributes(): string[];
9
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
10
+ get type(): string;
11
+ set type(value: string);
12
+ get contact(): string;
13
+ set contact(value: string);
14
+ get label(): string;
15
+ set label(value: string);
16
+ get placeholder(): boolean;
17
+ set placeholder(value: boolean);
18
+ }
19
+ type Props = {
20
+ type?: 'phone' | 'website' | 'email';
21
+ contact?: string;
22
+ label?: string;
23
+ placeholder?: boolean;
24
+ };
25
+ type ElementProps = Partial<{
26
+ [K in keyof Props]: Props[K] | string;
27
+ }>;
28
+ declare global {
29
+ interface HTMLElementTagNameMap {
30
+ 'sinch-labs-phone-preview-rcs-channel-info-option': ElementProps & HTMLElement;
31
+ }
32
+ }
33
+ declare module 'react' {
34
+ namespace JSX {
35
+ interface IntrinsicElements {
36
+ 'sinch-labs-phone-preview-rcs-channel-info-option': ElementProps & React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement>;
37
+ }
38
+ }
39
+ }
40
+ export {};
@@ -0,0 +1,106 @@
1
+ import '@nectary/components/icon';
2
+ import { defineCustomElement, NectaryElement } from '../utils';
3
+ import templateHTML from './template.html';
4
+ const template = document.createElement('template');
5
+ template.innerHTML = templateHTML;
6
+ export 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;
30
+ }
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
+ }
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;
104
+ }
105
+ }
106
+ defineCustomElement('sinch-labs-phone-preview-rcs-channel-info-option', PhonePreviewRcsChannelInfoOption);
@@ -0,0 +1,27 @@
1
+ import { NectaryElement } from '../utils';
2
+ import type React from 'react';
3
+ export declare class PhonePreviewRcsChannelOptions extends NectaryElement {
4
+ #private;
5
+ constructor();
6
+ connectedCallback(): void;
7
+ disconnectedCallback(): void;
8
+ static get observedAttributes(): never[];
9
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
10
+ }
11
+ type Props = {};
12
+ type ElementProps = Partial<{
13
+ [K in keyof Props]: Props[K] | string;
14
+ }>;
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'sinch-labs-phone-preview-rcs-channel-options': ElementProps & HTMLElement;
18
+ }
19
+ }
20
+ declare module 'react' {
21
+ namespace JSX {
22
+ interface IntrinsicElements {
23
+ 'sinch-labs-phone-preview-rcs-channel-options': ElementProps & React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement>;
24
+ }
25
+ }
26
+ }
27
+ export {};