@nectary/components 1.4.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/accordion/index.js +0 -3
  2. package/accordion/types.d.ts +0 -3
  3. package/accordion-item/index.d.ts +2 -0
  4. package/accordion-item/index.js +33 -34
  5. package/action-menu/index.js +5 -1
  6. package/action-menu-option/index.js +2 -2
  7. package/alert/index.js +4 -21
  8. package/alert/utils.d.ts +0 -3
  9. package/alert/utils.js +1 -6
  10. package/avatar/index.js +5 -21
  11. package/avatar/utils.d.ts +0 -4
  12. package/avatar/utils.js +2 -15
  13. package/badge/index.js +36 -68
  14. package/badge/types.d.ts +0 -4
  15. package/badge/utils.d.ts +0 -6
  16. package/badge/utils.js +1 -17
  17. package/button/index.js +25 -27
  18. package/button/types.d.ts +2 -2
  19. package/button/utils.d.ts +0 -3
  20. package/button/utils.js +1 -9
  21. package/card/index.js +5 -16
  22. package/card/types.d.ts +0 -6
  23. package/card-container/index.js +1 -1
  24. package/chat-block/index.js +1 -1
  25. package/chat-bubble/index.d.ts +0 -1
  26. package/chat-bubble/index.js +3 -25
  27. package/checkbox/index.js +32 -33
  28. package/checkbox/types.d.ts +0 -3
  29. package/chip/index.js +54 -44
  30. package/chip/utils.d.ts +0 -1
  31. package/chip/utils.js +2 -7
  32. package/code-tag/index.js +1 -1
  33. package/color-menu/index.d.ts +0 -3
  34. package/color-menu/index.js +55 -101
  35. package/color-menu/types.d.ts +0 -4
  36. package/color-menu-option/index.d.ts +14 -0
  37. package/color-menu-option/index.js +52 -0
  38. package/color-menu-option/types.d.ts +9 -0
  39. package/color-menu-option/utils.d.ts +1 -0
  40. package/color-menu-option/utils.js +11 -0
  41. package/color-swatch/index.js +2 -5
  42. package/color-swatch/utils.d.ts +0 -1
  43. package/color-swatch/utils.js +2 -7
  44. package/date-picker/index.js +3 -40
  45. package/date-picker/types.d.ts +0 -3
  46. package/date-picker/utils.d.ts +0 -8
  47. package/date-picker/utils.js +0 -20
  48. package/dialog/index.js +2 -6
  49. package/dialog/types.d.ts +0 -2
  50. package/emoji/index.js +1 -1
  51. package/emoji-picker/index.d.ts +1 -0
  52. package/emoji-picker/index.js +36 -34
  53. package/field/index.js +39 -32
  54. package/file-drop/index.js +1 -1
  55. package/file-status/index.js +4 -25
  56. package/file-status/utils.d.ts +0 -3
  57. package/file-status/utils.js +1 -6
  58. package/flag/index.js +1 -1
  59. package/grid/index.js +1 -1
  60. package/help-tooltip/index.d.ts +0 -1
  61. package/help-tooltip/index.js +3 -13
  62. package/horizontal-stepper/index.js +1 -1
  63. package/horizontal-stepper-item/index.d.ts +2 -0
  64. package/horizontal-stepper-item/index.js +8 -12
  65. package/icon/index.js +1 -1
  66. package/icon-button/index.js +23 -27
  67. package/icon-button/utils.d.ts +0 -3
  68. package/icon-button/utils.js +1 -9
  69. package/inline-alert/index.js +20 -37
  70. package/inline-alert/utils.d.ts +0 -3
  71. package/inline-alert/utils.js +1 -6
  72. package/input/index.d.ts +0 -3
  73. package/input/index.js +22 -58
  74. package/input/types.d.ts +1 -5
  75. package/input/utils.d.ts +0 -3
  76. package/input/utils.js +1 -6
  77. package/link/index.js +35 -37
  78. package/list-item/index.js +1 -1
  79. package/package.json +11 -11
  80. package/pagination/index.js +8 -21
  81. package/pagination/types.d.ts +0 -3
  82. package/pop/index.js +39 -38
  83. package/pop/utils.d.ts +0 -3
  84. package/pop/utils.js +0 -5
  85. package/popover/index.js +42 -51
  86. package/popover/utils.d.ts +0 -3
  87. package/popover/utils.js +0 -5
  88. package/progress/index.js +20 -15
  89. package/radio/index.js +19 -6
  90. package/radio/types.d.ts +3 -3
  91. package/radio-option/index.js +35 -27
  92. package/rich-text/index.js +3 -10
  93. package/rich-text/utils.d.ts +0 -3
  94. package/rich-text/utils.js +1 -6
  95. package/segment/index.js +3 -7
  96. package/segment-collapse/index.js +2 -11
  97. package/segment-collapse/types.d.ts +0 -3
  98. package/segmented-control/index.js +0 -3
  99. package/segmented-control/types.d.ts +0 -3
  100. package/segmented-control-option/index.js +20 -19
  101. package/segmented-icon-control/index.js +1 -4
  102. package/segmented-icon-control/types.d.ts +0 -3
  103. package/segmented-icon-control-option/index.js +18 -14
  104. package/select-button/index.js +29 -31
  105. package/select-menu/index.js +18 -8
  106. package/select-menu-option/index.js +2 -5
  107. package/skeleton/index.js +1 -1
  108. package/skeleton-item/index.js +1 -1
  109. package/spinner/index.js +3 -10
  110. package/table/index.js +1 -1
  111. package/table-body/index.js +1 -1
  112. package/table-cell/index.js +1 -1
  113. package/table-head-cell/index.d.ts +1 -0
  114. package/table-head-cell/index.js +12 -3
  115. package/table-row/index.js +18 -2
  116. package/tabs/index.js +1 -4
  117. package/tabs/types.d.ts +0 -3
  118. package/tabs-icon-option/index.js +4 -2
  119. package/tabs-option/index.js +25 -20
  120. package/tag/index.js +17 -12
  121. package/tag/utils.d.ts +0 -1
  122. package/tag/utils.js +2 -7
  123. package/text/index.js +24 -21
  124. package/text/utils.d.ts +0 -3
  125. package/text/utils.js +1 -6
  126. package/textarea/index.js +10 -6
  127. package/textarea/types.d.ts +0 -3
  128. package/tile-control/index.js +23 -25
  129. package/tile-control/types.d.ts +0 -3
  130. package/tile-control-option/index.js +1 -1
  131. package/time-picker/index.js +2 -11
  132. package/time-picker/types.d.ts +0 -3
  133. package/time-picker/utils.d.ts +1 -1
  134. package/time-picker/utils.js +17 -5
  135. package/title/index.js +28 -30
  136. package/title/utils.d.ts +0 -7
  137. package/title/utils.js +1 -29
  138. package/toast/index.js +22 -39
  139. package/toast/utils.d.ts +0 -3
  140. package/toast/utils.js +1 -6
  141. package/toggle/index.js +33 -30
  142. package/toggle/types.d.ts +0 -3
  143. package/tooltip/index.js +3 -15
  144. package/tooltip/types.d.ts +0 -12
  145. package/tooltip/utils.d.ts +0 -5
  146. package/tooltip/utils.js +0 -10
  147. package/utils/dom.js +0 -5
  148. package/utils/element.js +2 -2
  149. package/utils/size.d.ts +0 -5
  150. package/utils/size.js +1 -17
  151. package/vertical-stepper/index.js +1 -1
  152. package/vertical-stepper-item/index.d.ts +2 -0
  153. package/vertical-stepper-item/index.js +8 -12
  154. package/logo/create-logo-class.d.ts +0 -1
  155. package/logo/create-logo-class.js +0 -52
  156. package/logo/engage-icon/index.d.ts +0 -11
  157. package/logo/engage-icon/index.js +0 -4
  158. package/logo/engage-icon-wordmark/index.d.ts +0 -11
  159. package/logo/engage-icon-wordmark/index.js +0 -4
  160. package/logo/sinch-icon/index.d.ts +0 -11
  161. package/logo/sinch-icon/index.js +0 -4
  162. package/logo/sinch-icon-wordmark/index.d.ts +0 -11
  163. package/logo/sinch-icon-wordmark/index.js +0 -4
  164. package/logo/types.d.ts +0 -11
  165. package/theme/accordion-item.css +0 -4
  166. package/theme/alert.css +0 -6
  167. package/theme/avatar.css +0 -25
  168. package/theme/badge.css +0 -15
  169. package/theme/button.css +0 -146
  170. package/theme/chat.css +0 -9
  171. package/theme/chip.css +0 -68
  172. package/theme/color-menu.css +0 -4
  173. package/theme/color-swatch.css +0 -71
  174. package/theme/colors.d.ts +0 -4
  175. package/theme/colors.js +0 -4
  176. package/theme/contextual.css +0 -40
  177. package/theme/date-picker.css +0 -7
  178. package/theme/dialog.css +0 -4
  179. package/theme/elevation.css +0 -7
  180. package/theme/emoji-picker.css +0 -13
  181. package/theme/emoji.css +0 -5
  182. package/theme/file-status.css +0 -7
  183. package/theme/flag.css +0 -4
  184. package/theme/fonts.css +0 -86
  185. package/theme/fonts.json +0 -89
  186. package/theme/help-tooltip.css +0 -5
  187. package/theme/horizontal-stepper.css +0 -5
  188. package/theme/icon-button.css +0 -68
  189. package/theme/icon.css +0 -7
  190. package/theme/index.css +0 -4
  191. package/theme/index.d.ts +0 -39
  192. package/theme/index.js +0 -39
  193. package/theme/inline-alert.css +0 -7
  194. package/theme/input.css +0 -10
  195. package/theme/link.css +0 -5
  196. package/theme/pagination.css +0 -5
  197. package/theme/palette.css +0 -90
  198. package/theme/segment.css +0 -4
  199. package/theme/select-button.css +0 -10
  200. package/theme/select-menu.css +0 -6
  201. package/theme/shapes.css +0 -8
  202. package/theme/size.css +0 -9
  203. package/theme/spinner.css +0 -7
  204. package/theme/tag.css +0 -67
  205. package/theme/time-picker.css +0 -4
  206. package/theme/toast.css +0 -7
  207. package/theme/typography.css +0 -16
  208. package/theme/vertical-stepper.css +0 -5
  209. /package/{logo → color-menu-option}/types.js +0 -0
@@ -1,6 +1 @@
1
- export const sizeValues = ['m', 's', 'xs', 'xxs'];
2
- export const assertSize = value => {
3
- if (value === null || !sizeValues.includes(value)) {
4
- throw new Error(`sinch-rich-text: invalid "size" attribute: "${value}"`);
5
- }
6
- };
1
+ export const sizeValues = ['m', 's', 'xs', 'xxs'];
package/segment/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import '../title';
2
2
  import { getTitleLevelFromType } from '../title/utils';
3
3
  import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, getRect, isAttrTrue, NectaryElement, setClass, updateAttribute, updateBooleanAttribute, updateLiteralAttribute } from '../utils';
4
- import { assertSize, DEFAULT_SIZE, sizeValues } from '../utils/size';
5
- const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;gap:12px;width:100%;height:100%;border:1px solid var(--sinch-color-snow-700);border-radius:var(--sinch-shape-radius-l);box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-text-m);padding:8px 0 16px}#header{display:flex;flex-direction:row;align-items:center;height:48px;gap:8px;padding:0 24px;--sinch-size-icon:32px}#caption{color:var(--sinch-color-text-default);min-width:1em}#info{display:flex;flex-direction:row;align-items:center;gap:8px;margin-left:auto;align-self:stretch}#info.empty{display:none}#preview{flex:1;flex-basis:auto;height:48px;min-width:0;overflow:hidden;margin-left:24px}#preview.empty{display:none}#info.empty+#collapse{margin-left:auto}#collapse.empty{display:none}#preview:not(.empty)+#info.empty+#collapse:not(.empty),#preview:not(.empty)+#info:not(.empty){margin-left:24px}#content-wrapper{flex:1;min-height:0;overflow-y:auto;padding:4px 24px}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;padding:0 24px}#action.empty{display:none}:host([collapsed]:not([collapsed=false])) :is(#content-wrapper,#action){display:none}:host([collapsed]:not([collapsed=false])) #wrapper{padding-bottom:8px}::slotted([slot=icon]){margin-right:8px}</style><div id="wrapper"><div id="header"><slot name="icon"></slot><sinch-title id="caption" level="3" type="m" ellipsis></sinch-title><div id="preview"><slot name="preview"></slot></div><div id="info"><slot name="info"></slot></div><div id="collapse"><slot name="collapse"></slot></div></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
4
+ import { DEFAULT_SIZE, sizeValues } from '../utils/size';
5
+ const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;gap:12px;width:100%;height:100%;border:1px solid var(--sinch-comp-segment-color-default-border-initial);border-radius:var(--sinch-comp-segment-shape-radius);box-sizing:border-box;background-color:var(--sinch-comp-segment-color-default-background-initial);padding:8px 0 16px}#header{display:flex;flex-direction:row;align-items:center;height:48px;gap:8px;padding:0 24px}#icon{--sinch-global-size-icon:32px}#caption{min-width:1em;--sinch-comp-title-font:var(--sinch-comp-segment-font-size-m-title)}:host([size="l"]) #caption{--sinch-comp-title-font:var(--sinch-comp-segment-font-size-l-title)}:host([size="s"]) #caption{--sinch-comp-title-font:var(--sinch-comp-segment-font-size-s-title)}#info{display:flex;flex-direction:row;align-items:center;gap:8px;margin-left:auto;align-self:stretch}#info.empty{display:none}#preview{flex:1;flex-basis:auto;height:48px;min-width:0;overflow:hidden;margin-left:24px}#preview.empty{display:none}#info.empty+#collapse{margin-left:auto}#collapse.empty{display:none}#preview:not(.empty)+#info.empty+#collapse:not(.empty),#preview:not(.empty)+#info:not(.empty){margin-left:24px}#content-wrapper{flex:1;min-height:0;overflow-y:auto;padding:4px 24px}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;padding:0 24px}#action.empty{display:none}:host([collapsed]) :is(#content-wrapper,#action){display:none}:host([collapsed]) #wrapper{padding-bottom:8px}::slotted([slot=icon]){margin-right:8px}</style><div id="wrapper"><div id="header"><slot id="icon" name="icon"></slot><sinch-title id="caption" level="3" type="m" ellipsis></sinch-title><div id="preview"><slot name="preview"></slot></div><div id="info"><slot name="info"></slot></div><div id="collapse"><slot name="collapse"></slot></div></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
6
6
  import { getTitleTypeFromSize } from './utils';
7
7
  const template = document.createElement('template');
8
8
  template.innerHTML = templateHTML;
@@ -58,16 +58,12 @@ defineCustomElement('sinch-segment', class extends NectaryElement {
58
58
  }
59
59
  case 'collapsed':
60
60
  {
61
- updateBooleanAttribute(this, 'collapsed', isAttrTrue(newVal));
61
+ updateBooleanAttribute(this, name, isAttrTrue(newVal));
62
62
  break;
63
63
  }
64
64
  case 'size':
65
65
  {
66
- if ('production' !== 'production') {
67
- assertSize(newVal, 'sinch-segment');
68
- }
69
66
  const titleType = getTitleTypeFromSize(this.size);
70
- updateAttribute(this.#$caption, 'type', titleType);
71
67
  updateAttribute(this.#$caption, 'level', getTitleLevelFromType(titleType));
72
68
  break;
73
69
  }
@@ -1,24 +1,21 @@
1
1
  import '../icon';
2
2
  import '../icon-button';
3
- import { defineCustomElement, getBooleanAttribute, getCssVar, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
4
- const templateHTML = '<style>:host{display:block;--sinch-size-icon:32px}#icon-dropdown{display:block;will-change:transform;transform:rotate(180deg)}:host([value]:not([value=false])) #icon-dropdown{transform:rotate(0)}</style><sinch-icon-button id="button" size="s"><sinch-icon id="icon-dropdown" slot="icon"></sinch-icon></sinch-icon-button>';
3
+ import { defineCustomElement, getBooleanAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
4
+ const templateHTML = '<style>:host{display:block;--sinch-global-size-icon:32px}#icon-dropdown{display:block;will-change:transform;transform:rotate(180deg)}:host([value]:not([value=false])) #icon-dropdown{transform:rotate(0)}</style><sinch-icon-button id="button" size="s"><sinch-icon id="icon-dropdown" slot="icon" name="keyboard_arrow_down"></sinch-icon></sinch-icon-button>';
5
5
  const template = document.createElement('template');
6
6
  template.innerHTML = templateHTML;
7
7
  defineCustomElement('sinch-segment-collapse', class extends NectaryElement {
8
8
  #$button;
9
- #$iconDropdown;
10
9
  constructor() {
11
10
  super();
12
11
  const shadowRoot = this.attachShadow();
13
12
  shadowRoot.appendChild(template.content.cloneNode(true));
14
13
  this.#$button = shadowRoot.querySelector('#button');
15
- this.#$iconDropdown = shadowRoot.querySelector('#icon-dropdown');
16
14
  }
17
15
  connectedCallback() {
18
16
  this.setAttribute('role', 'checkbox');
19
17
  this.#$button.addEventListener('click', this.#onClick);
20
18
  this.addEventListener('-change', this.#onChangeReactHandler);
21
- updateAttribute(this.#$iconDropdown, 'name', getCssVar(this, '--sinch-segment-icon-dropdown'));
22
19
  }
23
20
  disconnectedCallback() {
24
21
  this.#$button.removeEventListener('click', this.#onClick);
@@ -36,12 +33,6 @@ defineCustomElement('sinch-segment-collapse', class extends NectaryElement {
36
33
  }
37
34
  }
38
35
  }
39
- get type() {
40
- return 'text';
41
- }
42
- get nodeName() {
43
- return 'input';
44
- }
45
36
  set value(isChecked) {
46
37
  updateBooleanAttribute(this, 'value', isChecked);
47
38
  }
@@ -1,5 +1,4 @@
1
1
  import type { TSinchElementReact } from '../types';
2
- import type { SyntheticEvent } from 'react';
3
2
  export type TSinchSegmentExpandElement = HTMLElement & {
4
3
  value: boolean;
5
4
  addEventListener(type: 'change', listener: (e: CustomEvent<boolean>) => void): void;
@@ -9,7 +8,5 @@ export type TSinchSegmentExpandElement = HTMLElement & {
9
8
  export type TSinchSegmentExpandReact = TSinchElementReact<TSinchSegmentExpandElement> & {
10
9
  value: boolean;
11
10
  'aria-label': string;
12
- /** @deprecated */
13
- onChange?: (e: SyntheticEvent<TSinchSegmentExpandElement, CustomEvent<boolean>>) => void;
14
11
  'on-change'?: (e: CustomEvent<boolean>) => void;
15
12
  };
@@ -24,9 +24,6 @@ defineCustomElement('sinch-segmented-control', class extends NectaryElement {
24
24
  static get observedAttributes() {
25
25
  return ['value'];
26
26
  }
27
- get nodeName() {
28
- return 'select';
29
- }
30
27
  set value(value) {
31
28
  updateAttribute(this, 'value', value);
32
29
  }
@@ -1,5 +1,4 @@
1
1
  import type { TSinchElementReact } from '../types';
2
- import type { SyntheticEvent } from 'react';
3
2
  export type TSinchSegmentedControlElement = HTMLElement & {
4
3
  value: string;
5
4
  addEventListener(type: '-change', listener: (e: CustomEvent<string>) => void): void;
@@ -8,7 +7,5 @@ export type TSinchSegmentedControlElement = HTMLElement & {
8
7
  export type TSinchSegmentedControlReact = TSinchElementReact<TSinchSegmentedControlElement> & {
9
8
  value: string;
10
9
  'aria-label': string;
11
- /** @deprecated */
12
- onChange?: (event: SyntheticEvent<TSinchSegmentedControlElement, CustomEvent<string>>) => void;
13
10
  'on-change'?: (e: CustomEvent<string>) => void;
14
11
  };
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, getAttribute, getBooleanAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
2
- const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;position:relative;flex-direction:row;align-items:center;gap:12px;width:100%;height:32px;padding:0 16px;box-sizing:border-box;border:1px solid var(--sinch-color-snow-600);border-left-width:0;border-right-width:0;color:var(--sinch-color-stormy-500);background-color:var(--sinch-color-snow-100);--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:16px}#wrapper:hover{background-color:var(--sinch-color-snow-400)}:host(:first-child) #wrapper{border-left-width:1px;border-top-left-radius:4px;border-bottom-left-radius:4px}:host(:last-child) #wrapper{border-right-width:1px;border-top-right-radius:4px;border-bottom-right-radius:4px}#content{font:var(--sinch-font-title-s);flex-shrink:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host([data-checked]) #wrapper{border-color:var(--sinch-color-stormy-500)}:host([data-checked]:not(:first-child)) #wrapper::before{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;left:0;top:-1px;bottom:-1px}:host([data-checked]:not(:last-child)) #wrapper::after{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;right:0;top:-1px;bottom:-1px}#button{all:initial;position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus::before{content:"";position:absolute;left:-3px;right:-3px;top:-4px;bottom:-4px;border-style:solid;border-color:var(--sinch-color-border-focus);border-width:0}#button:focus-visible::before{border-width:2px}:host(:first-child) #button:focus::before{left:-4px;border-top-left-radius:6px;border-bottom-left-radius:6px}:host(:last-child) #button:focus::before{right:-4px;border-top-right-radius:6px;border-bottom-right-radius:6px}:host([disabled]:not([disabled=false])) #wrapper{background-color:var(--sinch-color-snow-100);color:var(--sinch-color-stormy-100);--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><slot name="icon"></slot><label for="button" id="content"></label><button id="button"></button></div>';
2
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{position:relative;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;height:32px;padding:0 16px;box-sizing:border-box;color:var(--sinch-local-color-text);background-color:var(--sinch-local-color-background);--sinch-local-color-text:var(--sinch-comp-segmented-control-color-default-text-initial);--sinch-local-shape-radius:var(--sinch-comp-segmented-control-shape-radius);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-default-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-default-background-initial);--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-segmented-control-size-icon)}#wrapper:hover{--sinch-local-color-background:var(--sinch-comp-segmented-control-color-default-background-hover)}:host(:first-child) #wrapper{border-top-left-radius:var(--sinch-local-shape-radius);border-bottom-left-radius:var(--sinch-local-shape-radius)}:host(:last-child) #wrapper{border-top-right-radius:var(--sinch-local-shape-radius);border-bottom-right-radius:var(--sinch-local-shape-radius)}:host([data-checked]) #wrapper{--sinch-local-color-text:var(--sinch-comp-segmented-control-color-checked-text-initial);--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-checked-icon-initial);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-checked-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-checked-background-initial)}#border{position:absolute;inset:0;border:1px solid var(--sinch-local-color-border);border-right-width:0;pointer-events:none;box-sizing:border-box}:host(:first-child) #border{border-top-left-radius:var(--sinch-local-shape-radius);border-bottom-left-radius:var(--sinch-local-shape-radius)}:host(:last-child) #border{border-right-width:1px;border-top-right-radius:var(--sinch-local-shape-radius);border-bottom-right-radius:var(--sinch-local-shape-radius)}:host(:not(:first-child)) #border{left:-1px}:host(:not(:last-child)) #border{right:-1px}:host([data-checked]) #border{border-width:2px;z-index:1}#button{all:initial;position:absolute;left:0;top:0;width:100%;height:100%;box-sizing:border-box;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus-visible::before{content:"";position:absolute;inset:-4px;border:2px solid var(--sinch-comp-segmented-control-color-default-outline-focus)}:host(:first-child) #button:focus-visible::before{border-top-left-radius:calc(var(--sinch-local-shape-radius) + 3px);border-bottom-left-radius:calc(var(--sinch-local-shape-radius) + 3px)}:host(:last-child) #button:focus-visible::before{border-top-right-radius:calc(var(--sinch-local-shape-radius) + 3px);border-bottom-right-radius:calc(var(--sinch-local-shape-radius) + 3px)}:host([disabled]) #wrapper{--sinch-local-color-text:var(--sinch-comp-segmented-control-color-disabled-text-initial);--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-disabled-icon-initial);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-disabled-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-disabled-background-initial)}#content{font:var(--sinch-comp-segmented-control-font-label);flex-shrink:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}::slotted(*){display:block}</style><div id="wrapper"><slot name="icon"></slot><label for="button" id="content"></label><div id="border"></div><button id="button"></button></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-segmented-control-option', class extends NectaryElement {
@@ -30,24 +30,6 @@ defineCustomElement('sinch-segmented-control-option', class extends NectaryEleme
30
30
  static get observedAttributes() {
31
31
  return ['data-checked', 'disabled', 'text'];
32
32
  }
33
- set value(value) {
34
- updateAttribute(this, 'value', value);
35
- }
36
- get value() {
37
- return getAttribute(this, 'value', '');
38
- }
39
- set disabled(isDisabled) {
40
- updateBooleanAttribute(this, 'disabled', isDisabled);
41
- }
42
- get disabled() {
43
- return getBooleanAttribute(this, 'disabled');
44
- }
45
- set text(value) {
46
- updateAttribute(this, 'text', value);
47
- }
48
- get text() {
49
- return getAttribute(this, 'text', '');
50
- }
51
33
  attributeChangedCallback(name, oldVal, newVal) {
52
34
  if (oldVal === newVal) {
53
35
  return;
@@ -66,10 +48,29 @@ defineCustomElement('sinch-segmented-control-option', class extends NectaryEleme
66
48
  case 'disabled':
67
49
  {
68
50
  this.#$button.disabled = isAttrTrue(newVal);
51
+ updateBooleanAttribute(this, name, this.#$button.disabled);
69
52
  break;
70
53
  }
71
54
  }
72
55
  }
56
+ set value(value) {
57
+ updateAttribute(this, 'value', value);
58
+ }
59
+ get value() {
60
+ return getAttribute(this, 'value', '');
61
+ }
62
+ set disabled(isDisabled) {
63
+ updateBooleanAttribute(this, 'disabled', isDisabled);
64
+ }
65
+ get disabled() {
66
+ return getBooleanAttribute(this, 'disabled');
67
+ }
68
+ set text(value) {
69
+ updateAttribute(this, 'text', value);
70
+ }
71
+ get text() {
72
+ return getAttribute(this, 'text', '');
73
+ }
73
74
  get focusable() {
74
75
  return true;
75
76
  }
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, getAttribute, getBooleanAttribute, unpackCsv, getFirstCsvValue, getReactEventHandler, NectaryElement, updateAttribute, updateBooleanAttribute, updateCsv } from '../utils';
2
- const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;flex-direction:row}</style><div id="wrapper"><slot></slot></div>';
2
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;flex-direction:row;width:100%;box-sizing:border-box}</style><div id="wrapper"><slot></slot></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-segmented-icon-control', class extends NectaryElement {
@@ -24,9 +24,6 @@ defineCustomElement('sinch-segmented-icon-control', class extends NectaryElement
24
24
  static get observedAttributes() {
25
25
  return ['value'];
26
26
  }
27
- get nodeName() {
28
- return 'select';
29
- }
30
27
  set value(value) {
31
28
  updateAttribute(this, 'value', value);
32
29
  }
@@ -1,5 +1,4 @@
1
1
  import type { TSinchElementReact } from '../types';
2
- import type { SyntheticEvent } from 'react';
3
2
  export type TSinchSegmentedIconControlElement = HTMLElement & {
4
3
  value: string;
5
4
  multiple: boolean;
@@ -11,7 +10,5 @@ export type TSinchSegmentedIconControlReact = TSinchElementReact<TSinchSegmented
11
10
  value: string;
12
11
  multiple?: boolean;
13
12
  'aria-label': string;
14
- /** @deprecated */
15
- onChange?: (event: SyntheticEvent<TSinchSegmentedIconControlElement, CustomEvent<string>>) => void;
16
13
  'on-change'?: (e: CustomEvent<string>) => void;
17
14
  };
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, getAttribute, getBooleanAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
2
- const templateHTML = '<style>:host{display:block;outline:0}#wrapper{position:relative;width:56px;height:32px;padding:3px 16px;box-sizing:border-box;border:1px solid var(--sinch-color-snow-600);border-left-width:0;border-right-width:0;color:var(--sinch-color-stormy-500);background-color:var(--sinch-color-snow-100);--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:24px}#wrapper:hover{background-color:var(--sinch-color-snow-400)}:host(:first-child) #wrapper{border-left-width:1px;border-top-left-radius:4px;border-bottom-left-radius:4px}:host(:last-child) #wrapper{border-right-width:1px;border-top-right-radius:4px;border-bottom-right-radius:4px}:host([data-checked]) #wrapper{border-color:var(--sinch-color-stormy-500)}:host([data-checked]:not(:first-child)) #wrapper::before{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;left:-1px;top:-1px;bottom:-1px}:host([data-checked]:not(:last-child)) #wrapper::after{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;right:0;top:-1px;bottom:-1px}#button{all:initial;position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus::before{content:"";position:absolute;left:-4px;right:-3px;top:-4px;bottom:-4px;border-style:solid;border-color:var(--sinch-color-border-focus);border-width:0}#button:focus-visible::before{border-width:2px}:host(:first-child) #button:focus::before{left:-4px;border-top-left-radius:6px;border-bottom-left-radius:6px}:host(:last-child) #button:focus::before{right:-4px;border-top-right-radius:6px;border-bottom-right-radius:6px}:host([disabled]:not([disabled=false])) #wrapper{background-color:var(--sinch-color-snow-100);color:var(--sinch-color-stormy-100);--sinch-color-icon:var(--sinch-color-stormy-100)}::slotted(*){display:block}</style><div id="wrapper"><slot name="icon"></slot><button id="button"></button></div>';
2
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{position:relative;width:56px;height:32px;padding:3px 16px;box-sizing:border-box;background-color:var(--sinch-local-color-background);--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-segmented-control-size-icon);--sinch-local-shape-radius:var(--sinch-comp-segmented-control-shape-radius);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-default-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-default-background-initial)}#wrapper:hover{--sinch-local-color-background:var(--sinch-comp-segmented-control-color-default-background-hover)}:host(:first-child) #wrapper{border-top-left-radius:var(--sinch-local-shape-radius);border-bottom-left-radius:var(--sinch-local-shape-radius)}:host(:last-child) #wrapper{border-top-right-radius:var(--sinch-local-shape-radius);border-bottom-right-radius:var(--sinch-local-shape-radius)}:host([data-checked]) #wrapper{--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-checked-icon-initial);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-checked-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-checked-background-initial)}#border{position:absolute;inset:0;border:1px solid var(--sinch-local-color-border);border-right-width:0;pointer-events:none;box-sizing:border-box}:host(:first-child) #border{border-top-left-radius:var(--sinch-local-shape-radius);border-bottom-left-radius:var(--sinch-local-shape-radius)}:host(:last-child) #border{border-right-width:1px;border-top-right-radius:var(--sinch-local-shape-radius);border-bottom-right-radius:var(--sinch-local-shape-radius)}:host(:not(:first-child)) #border{left:-1px}:host(:not(:last-child)) #border{right:-1px}:host([data-checked]) #border{border-width:2px;z-index:1}#button{all:initial;position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus-visible::before{content:"";position:absolute;inset:-4px;border:2px solid var(--sinch-comp-segmented-control-color-default-outline-focus)}:host(:first-child) #button:focus-visible::before{border-top-left-radius:calc(var(--sinch-local-shape-radius) + 3px);border-bottom-left-radius:calc(var(--sinch-local-shape-radius) + 3px)}:host(:last-child) #button:focus-visible::before{border-top-right-radius:calc(var(--sinch-local-shape-radius) + 3px);border-bottom-right-radius:calc(var(--sinch-local-shape-radius) + 3px)}:host([disabled]) #wrapper{--sinch-global-color-icon:var(--sinch-comp-segmented-control-color-disabled-icon-initial);--sinch-local-color-border:var(--sinch-comp-segmented-control-color-disabled-border-initial);--sinch-local-color-background:var(--sinch-comp-segmented-control-color-disabled-background-initial)}::slotted(*){display:block}</style><div id="wrapper"><slot name="icon"></slot><div id="border"></div><button id="button"></button></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-segmented-icon-control-option', class extends NectaryElement {
@@ -28,19 +28,10 @@ defineCustomElement('sinch-segmented-icon-control-option', class extends Nectary
28
28
  static get observedAttributes() {
29
29
  return ['data-checked', 'disabled'];
30
30
  }
31
- set value(value) {
32
- updateAttribute(this, 'value', value);
33
- }
34
- get value() {
35
- return getAttribute(this, 'value', '');
36
- }
37
- set disabled(isDisabled) {
38
- updateBooleanAttribute(this, 'disabled', isDisabled);
39
- }
40
- get disabled() {
41
- return getBooleanAttribute(this, 'disabled');
42
- }
43
- attributeChangedCallback(name, _, newVal) {
31
+ attributeChangedCallback(name, oldVal, newVal) {
32
+ if (oldVal === newVal) {
33
+ return;
34
+ }
44
35
  switch (name) {
45
36
  case 'data-checked':
46
37
  {
@@ -50,10 +41,23 @@ defineCustomElement('sinch-segmented-icon-control-option', class extends Nectary
50
41
  case 'disabled':
51
42
  {
52
43
  this.#$button.disabled = isAttrTrue(newVal);
44
+ updateBooleanAttribute(this, name, this.#$button.disabled);
53
45
  break;
54
46
  }
55
47
  }
56
48
  }
49
+ set value(value) {
50
+ updateAttribute(this, 'value', value);
51
+ }
52
+ get value() {
53
+ return getAttribute(this, 'value', '');
54
+ }
55
+ set disabled(isDisabled) {
56
+ updateBooleanAttribute(this, 'disabled', isDisabled);
57
+ }
58
+ get disabled() {
59
+ return getBooleanAttribute(this, 'disabled');
60
+ }
57
61
  get focusable() {
58
62
  return true;
59
63
  }
@@ -1,14 +1,13 @@
1
1
  import '../text';
2
2
  import '../icon';
3
- import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, getReactEventHandler, isAttrTrue, NectaryElement, setClass, subscribeContext, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateLiteralAttribute, Context, getCssVar } from '../utils';
4
- import { assertSize, DEFAULT_SIZE, sizeValues } from '../utils/size';
5
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-size:var(--sinch-size-m);--sinch-size-icon:var(--sinch-select-button-icon-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([data-size="l"]){--sinch-size:var(--sinch-size-l);--sinch-size-icon:var(--sinch-select-button-icon-size-l);--sinch-shape-radius:var(--sinch-shape-radius-l)}:host([data-size="m"]){--sinch-size:var(--sinch-size-m);--sinch-size-icon:var(--sinch-select-button-icon-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([data-size="s"]){--sinch-size:var(--sinch-size-s);--sinch-size-icon:var(--sinch-select-button-icon-size-s);--sinch-shape-radius:var(--sinch-shape-radius-s)}#wrapper{position:relative;display:flex;flex-direction:row;align-items:center;gap:8px;box-sizing:border-box;width:100%;height:var(--sinch-size);padding:0 8px 0 12px;background-color:var(--sinch-color-bg-primary-light);border-radius:var(--sinch-shape-radius);--sinch-color-icon:var(--sinch-color-stormy-500)}:host([data-size="l"]) #wrapper{padding:0 12px}:host([data-size="m"]) #wrapper{padding:0 8px 0 12px}:host([data-size="s"]) #wrapper{padding:0 4px 0 12px}:host([disabled]:not([disabled=false])) #wrapper{--sinch-color-icon:var(--sinch-color-text-disabled)}#button{all:initial;cursor:pointer;position:absolute;left:0;top:0;width:100%;height:100%;z-index:1}#border{position:absolute;border:1px solid var(--sinch-color-border-dark);border-radius:var(--sinch-shape-radius);inset:0;pointer-events:none}#text{flex:1;min-width:0;color:var(--sinch-color-text-muted)}:host([text]:not([text=""])) #text{color:var(--sinch-color-text-default)}#button:disabled{cursor:initial}#button:disabled+#border{border-color:var(--sinch-color-border-disabled)}#button:focus-visible+#border{border-color:var(--sinch-color-border-focus);border-width:2px}:host([invalid]) #button:enabled+#border{border-color:var(--sinch-color-text-invalid)}#button:disabled~#text{color:var(--sinch-color-text-disabled)}#left{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;margin-left:-4px}#left.empty{display:none}#dropdown-icon{margin-left:-4px}</style><div id="wrapper"><button id="button"></button><div id="border"></div><div id="left"><slot name="left"></slot></div><slot name="icon"></slot><sinch-text id="text" type="m" ellipsis></sinch-text><sinch-icon id="dropdown-icon"></sinch-icon></div>';
3
+ import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, getReactEventHandler, isAttrTrue, NectaryElement, setClass, subscribeContext, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateLiteralAttribute, Context } from '../utils';
4
+ import { DEFAULT_SIZE, sizeValues } from '../utils/size';
5
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative;display:flex;flex-direction:row;align-items:center;gap:8px;box-sizing:border-box;width:100%;height:var(--sinch-local-size);padding:0 8px 0 12px;background-color:var(--sinch-comp-select-button-color-default-background-initial);border-radius:var(--sinch-local-shape-radius);cursor:pointer;--sinch-local-size:var(--sinch-comp-select-button-size-container-m);--sinch-global-size-icon:var(--sinch-comp-select-button-size-icon-m);--sinch-local-shape-radius:var(--sinch-comp-select-button-shape-radius-size-m);--sinch-global-color-icon:var(--sinch-comp-select-button-color-default-icon-initial)}:host([data-size="l"])>#wrapper{--sinch-local-size:var(--sinch-comp-select-button-size-container-l);--sinch-global-size-icon:var(--sinch-comp-select-button-size-icon-l);--sinch-local-shape-radius:var(--sinch-comp-select-button-shape-radius-size-l)}:host([data-size="m"])>#wrapper{--sinch-local-size:var(--sinch-comp-select-button-size-container-m);--sinch-global-size-icon:var(--sinch-comp-select-button-size-icon-m);--sinch-local-shape-radius:var(--sinch-comp-select-button-shape-radius-size-m)}:host([data-size="s"])>#wrapper{--sinch-local-size:var(--sinch-comp-select-button-size-container-s);--sinch-global-size-icon:var(--sinch-comp-select-button-size-icon-s);--sinch-local-shape-radius:var(--sinch-comp-select-button-shape-radius-size-s)}:host([data-size="l"]) #wrapper{padding:0 12px}:host([data-size="m"]) #wrapper{padding:0 8px 0 12px}:host([data-size="s"]) #wrapper{padding:0 4px 0 12px}:host([disabled]) #wrapper{--sinch-global-color-icon:var(--sinch-comp-select-button-color-disabled-icon-initial);cursor:initial}#text{flex:1;min-width:0;--sinch-comp-text-font:var(--sinch-comp-select-button-font-input);--sinch-global-color-text:var(--sinch-comp-select-button-color-default-text-initial)}#text:empty{display:none}#placeholder{display:none;flex:1;min-width:0;--sinch-comp-text-font:var(--sinch-comp-select-button-font-placeholder);--sinch-global-color-text:var(--sinch-comp-select-button-color-default-placeholder-initial)}#text:empty+#placeholder{display:block}#border{position:absolute;border:1px solid var(--sinch-comp-select-button-color-default-border-initial);border-radius:var(--sinch-local-shape-radius);inset:0;pointer-events:none}:host(:focus-visible) #border{border-color:var(--sinch-comp-select-button-color-default-border-focus);border-width:2px}:host([invalid]) #border{border-color:var(--sinch-comp-select-button-color-invalid-border-initial)}:host([disabled]) #border{border-color:var(--sinch-comp-select-button-color-disabled-border-initial)}:host([disabled]) #text{--sinch-global-color-text:var(--sinch-comp-select-button-color-disabled-text-initial)}:host([disabled]) #placeholder{--sinch-global-color-text:var(--sinch-comp-select-button-color-disabled-placeholder-initial)}#left{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;margin-left:-4px}#left.empty{display:none}#dropdown-icon{margin-left:-4px}</style><div id="wrapper" inert><div id="border"></div><div id="left"><slot name="left"></slot></div><slot name="icon"></slot><sinch-text id="text" type="m" ellipsis></sinch-text><sinch-text id="placeholder" type="m" ellipsis></sinch-text><sinch-icon id="dropdown-icon" name="keyboard_arrow_down"></sinch-icon></div>';
6
6
  const template = document.createElement('template');
7
7
  template.innerHTML = templateHTML;
8
8
  defineCustomElement('sinch-select-button', class extends NectaryElement {
9
- #$button;
10
- #$icon;
11
9
  #$text;
10
+ #$placeholder;
12
11
  #$leftSlot;
13
12
  #$leftWrapper;
14
13
  #$wrapper;
@@ -17,12 +16,11 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
17
16
  constructor() {
18
17
  super();
19
18
  const shadowRoot = this.attachShadow({
20
- delegatesFocus: true
19
+ delegatesFocus: false
21
20
  });
22
21
  shadowRoot.appendChild(template.content.cloneNode(true));
23
- this.#$button = shadowRoot.querySelector('#button');
24
- this.#$icon = shadowRoot.querySelector('#dropdown-icon');
25
22
  this.#$text = shadowRoot.querySelector('#text');
23
+ this.#$placeholder = shadowRoot.querySelector('#placeholder');
26
24
  this.#$leftSlot = shadowRoot.querySelector('slot[name="left"]');
27
25
  this.#$leftWrapper = shadowRoot.querySelector('#left');
28
26
  this.#$wrapper = shadowRoot.querySelector('#wrapper');
@@ -34,14 +32,18 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
34
32
  const {
35
33
  signal
36
34
  } = this.#controller;
37
- this.setAttribute('role', 'button');
38
- this.#$button.addEventListener('click', this.#onButtonClick, {
35
+ this.role = 'button';
36
+ this.tabIndex = 0;
37
+ this.addEventListener('click', this.#onButtonClick, {
39
38
  signal
40
39
  });
41
- this.#$button.addEventListener('focus', this.#onButtonFocus, {
40
+ this.addEventListener('focus', this.#onButtonFocus, {
42
41
  signal
43
42
  });
44
- this.#$button.addEventListener('blur', this.#onButtonBlur, {
43
+ this.addEventListener('blur', this.#onButtonBlur, {
44
+ signal
45
+ });
46
+ this.addEventListener('keydown', this.#onButtonKeydown, {
45
47
  signal
46
48
  });
47
49
  this.addEventListener('-click', this.#onClickReactHandler, {
@@ -56,7 +58,6 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
56
58
  this.#$leftSlot.addEventListener('slotchange', this.#onLeftSlotChange, {
57
59
  signal
58
60
  });
59
- updateAttribute(this.#$icon, 'name', getCssVar(this, '--sinch-select-button-icon-dropdown'));
60
61
  this.#sizeContext.listen(this.#controller.signal);
61
62
  subscribeContext(this, 'size', this.#onContextSize, signal);
62
63
  this.#onLeftSlotChange();
@@ -76,29 +77,24 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
76
77
  switch (name) {
77
78
  case 'text':
78
79
  {
79
- const value = newVal ?? '';
80
- this.#$text.textContent = value.length > 0 ? value : this.placeholder;
80
+ this.#$text.textContent = newVal;
81
81
  break;
82
82
  }
83
83
  case 'placeholder':
84
84
  {
85
- const value = this.text;
86
- if (value.length === 0) {
87
- this.#$text.textContent = newVal ?? '';
88
- }
85
+ this.#$placeholder.textContent = newVal;
89
86
  break;
90
87
  }
91
88
  case 'invalid':
92
89
  {
93
90
  const isInvalid = isAttrTrue(newVal);
94
- updateBooleanAttribute(this, 'invalid', isInvalid);
95
91
  updateExplicitBooleanAttribute(this, 'aria-invalid', isInvalid);
92
+ updateBooleanAttribute(this, 'invalid', isInvalid);
96
93
  break;
97
94
  }
98
95
  case 'disabled':
99
96
  {
100
97
  const isDisabled = isAttrTrue(newVal);
101
- this.#$button.disabled = isDisabled;
102
98
  updateBooleanAttribute(this, 'disabled', isDisabled);
103
99
  break;
104
100
  }
@@ -109,9 +105,6 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
109
105
  }
110
106
  case 'data-size':
111
107
  {
112
- if ('production' !== 'production') {
113
- assertSize(newVal, 'sinch-select-button');
114
- }
115
108
  this.#onSizeUpdate();
116
109
  break;
117
110
  }
@@ -150,12 +143,6 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
150
143
  get focusable() {
151
144
  return true;
152
145
  }
153
- focus() {
154
- this.#$button.focus();
155
- }
156
- blur() {
157
- this.#$button.blur();
158
- }
159
146
  #onContextSize = e => {
160
147
  if (this.hasAttribute('size')) {
161
148
  return;
@@ -188,8 +175,19 @@ defineCustomElement('sinch-select-button', class extends NectaryElement {
188
175
  #onButtonBlur = () => {
189
176
  this.dispatchEvent(new CustomEvent('-blur'));
190
177
  };
178
+ #onButtonKeydown = e => {
179
+ switch (e.code) {
180
+ case 'Space':
181
+ case 'Enter':
182
+ {
183
+ this.click();
184
+ }
185
+ }
186
+ };
191
187
  #onButtonClick = () => {
192
- this.dispatchEvent(new CustomEvent('-click'));
188
+ if (!this.disabled) {
189
+ this.dispatchEvent(new CustomEvent('-click'));
190
+ }
193
191
  };
194
192
  #onClickReactHandler = e => {
195
193
  getReactEventHandler(this, 'on-click')?.(e);
@@ -2,8 +2,8 @@ import '../input';
2
2
  import '../icon-button';
3
3
  import '../icon';
4
4
  import '../text';
5
- import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, unpackCsv, getFirstCsvValue, getIntegerAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateCsv, updateExplicitBooleanAttribute, updateIntegerAttribute, debounceTimeout, setClass, subscribeContext, getCssVar, hasClass } from '../utils';
6
- const templateHTML = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto}#search{display:none;margin:10px}#search.active{display:block}#not-found{display:none;width:100%;height:30px;align-items:center;justify-content:center;margin-bottom:10px;color:var(--sinch-color-text-muted);pointer-events:none;user-select:none}#not-found.active{display:flex}::slotted(.hidden){display:none}</style><sinch-input id="search" size="s" placeholder="Search"><sinch-icon id="icon-search" slot="icon"></sinch-icon></sinch-input><div id="not-found"><sinch-text type="m">No results</sinch-text></div><div id="listbox" role="presentation"><slot></slot></div>';
5
+ import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, unpackCsv, getFirstCsvValue, getIntegerAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateCsv, updateExplicitBooleanAttribute, updateIntegerAttribute, debounceTimeout, setClass, subscribeContext, hasClass } from '../utils';
6
+ const templateHTML = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto}#search{display:none;margin:10px}#search.active{display:block}#search-clear:not(.active){display:none}#not-found{display:flex;align-items:center;justify-content:center;width:100%;height:30px;margin-bottom:10px;pointer-events:none;user-select:none;--sinch-comp-text-font:var(--sinch-comp-select-menu-font-not-found-text);--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-not-found-text-initial)}#not-found:not(.active){display:none}::slotted(.hidden){display:none}</style><sinch-input id="search" size="s" placeholder="Search"><sinch-icon id="icon-search" slot="icon" name="search"></sinch-icon><sinch-icon-button id="search-clear" slot="right"><sinch-icon slot="icon" name="close"></sinch-icon></sinch-icon-button></sinch-input><div id="not-found"><sinch-text type="m">No results</sinch-text></div><div id="listbox" role="presentation"><slot></slot></div>';
7
7
  const ITEM_HEIGHT = 40;
8
8
  const NUM_ITEMS_SEARCH = 7;
9
9
  const template = document.createElement('template');
@@ -12,18 +12,20 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
12
12
  #$optionSlot;
13
13
  #$listbox;
14
14
  #$search;
15
- #$iconSearch;
15
+ #$searchClear;
16
16
  #$notFound;
17
17
  #controller = null;
18
18
  #searchDebounce;
19
19
  constructor() {
20
20
  super();
21
- const shadowRoot = this.attachShadow();
21
+ const shadowRoot = this.attachShadow({
22
+ delegatesFocus: false
23
+ });
22
24
  shadowRoot.appendChild(template.content.cloneNode(true));
23
25
  this.#$optionSlot = shadowRoot.querySelector('slot');
24
26
  this.#$listbox = shadowRoot.querySelector('#listbox');
25
27
  this.#$search = shadowRoot.querySelector('#search');
26
- this.#$iconSearch = shadowRoot.querySelector('#icon-search');
28
+ this.#$searchClear = shadowRoot.querySelector('#search-clear');
27
29
  this.#$notFound = shadowRoot.querySelector('#not-found');
28
30
  this.#searchDebounce = debounceTimeout(200)(this.#updateSearch);
29
31
  }
@@ -32,19 +34,19 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
32
34
  const options = {
33
35
  signal: this.#controller.signal
34
36
  };
35
- this.setAttribute('role', 'listbox');
36
- this.setAttribute('tabindex', '0');
37
+ this.role = 'listbox';
38
+ this.tabIndex = 0;
37
39
  this.addEventListener('keydown', this.#onListboxKeyDown, options);
38
40
  this.addEventListener('focus', this.#onFocus, options);
39
41
  this.addEventListener('blur', this.#onListboxBlur, options);
40
42
  this.#$listbox.addEventListener('mousedown', this.#onListboxMousedown, options);
41
43
  this.#$listbox.addEventListener('click', this.#onListboxClick, options);
42
44
  this.#$search.addEventListener('-change', this.#onSearchChange, options);
45
+ this.#$searchClear.addEventListener('-click', this.#onSearchClearClick, options);
43
46
  this.#$optionSlot.addEventListener('slotchange', this.#onOptionSlotChange, options);
44
47
  this.addEventListener('-change', this.#onChangeReactHandler, options);
45
48
  subscribeContext(this, 'keydown', this.#onContextKeyDown, this.#controller.signal);
46
49
  subscribeContext(this, 'visibility', this.#onContextVisibility, this.#controller.signal);
47
- updateAttribute(this.#$iconSearch, 'name', getCssVar(this, '--sinch-select-menu-icon-search'));
48
50
  this.#onOptionSlotChange();
49
51
  }
50
52
  disconnectedCallback() {
@@ -118,6 +120,7 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
118
120
  };
119
121
  #onListboxClick = e => {
120
122
  const $elem = e.target;
123
+ this.focus();
121
124
  if (!getBooleanAttribute($elem, 'disabled')) {
122
125
  this.#selectOption($elem);
123
126
  }
@@ -125,6 +128,13 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
125
128
  #onSearchChange = e => {
126
129
  this.#$search.value = e.detail;
127
130
  this.#searchDebounce.fn();
131
+ setClass(this.#$searchClear, 'active', e.detail.length > 0);
132
+ };
133
+ #onSearchClearClick = () => {
134
+ this.#$search.value = '';
135
+ this.#$search.focus();
136
+ this.#searchDebounce.fn();
137
+ setClass(this.#$searchClear, 'active', false);
128
138
  };
129
139
  #updateSearch = () => {
130
140
  const searchValue = this.#$search.value.toLowerCase();
@@ -1,22 +1,19 @@
1
1
  import '../icon';
2
2
  import '../text';
3
- import { defineCustomElement, getAttribute, getBooleanAttribute, getCssVar, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
4
- const templateHTML = '<style>:host{display:block}#wrapper{display:flex;position:relative;box-sizing:border-box;height:40px;padding:8px 16px;align-items:center;gap:10px;user-select:none;cursor:pointer;color:var(--sinch-color-text-default);--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:24px}#content{flex:1}#icon-check{display:none;margin-right:-6px}:host([data-checked]) #icon-check{display:block}:host([disabled])>#wrapper{cursor:initial;color:var(--sinch-color-text-disabled);--sinch-color-icon:var(--sinch-color-stormy-100)}:host(:hover:not([disabled]))>#wrapper,:host([data-selected])>#wrapper{background-color:var(--sinch-color-snow-400)}::slotted(*){margin-left:-6px}</style><div id="wrapper"><slot name="icon"></slot><sinch-text id="content" type="m" ellipsis></sinch-text><sinch-icon id="icon-check"></sinch-icon></div>';
3
+ import { defineCustomElement, getAttribute, getBooleanAttribute, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
4
+ const templateHTML = '<style>:host{display:block}#wrapper{display:flex;position:relative;box-sizing:border-box;height:40px;padding:8px 16px;align-items:center;gap:10px;user-select:none;cursor:pointer;background-color:var(--sinch-comp-select-menu-color-default-background-initial);--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-option-initial);--sinch-global-color-icon:var(--sinch-comp-select-menu-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-select-menu-size-icon)}#content{flex:1;min-width:0;--sinch-comp-text-font:var(--sinch-comp-select-menu-font-option)}#icon-check{display:none;margin-right:-6px}:host([data-checked]) #icon-check{display:block}:host([data-selected])>#wrapper{background-color:var(--sinch-comp-select-menu-color-default-background-selected)}:host(:hover)>#wrapper{background-color:var(--sinch-comp-select-menu-color-default-background-hover)}:host([disabled])>#wrapper{cursor:initial;pointer-events:none;background-color:var(--sinch-comp-select-menu-color-disabled-background-initial);--sinch-global-color-text:var(--sinch-comp-select-menu-color-disabled-option-initial);--sinch-global-color-icon:var(--sinch-comp-select-menu-color-disabled-icon-initial)}::slotted(*){margin-left:-6px}</style><div id="wrapper"><slot name="icon"></slot><sinch-text id="content" type="m" ellipsis></sinch-text><sinch-icon id="icon-check" name="check"></sinch-icon></div>';
5
5
  const template = document.createElement('template');
6
6
  template.innerHTML = templateHTML;
7
7
  export class SelectMenuOption extends NectaryElement {
8
- #$iconCheck;
9
8
  #$content;
10
9
  constructor() {
11
10
  super();
12
11
  const shadowRoot = this.attachShadow();
13
12
  shadowRoot.appendChild(template.content.cloneNode(true));
14
13
  this.#$content = shadowRoot.querySelector('#content');
15
- this.#$iconCheck = shadowRoot.querySelector('#icon-check');
16
14
  }
17
15
  connectedCallback() {
18
16
  this.setAttribute('role', 'option');
19
- updateAttribute(this.#$iconCheck, 'name', getCssVar(this, '--sinch-select-menu-icon-check'));
20
17
  }
21
18
  static get observedAttributes() {
22
19
  return ['text', 'data-checked', 'disabled'];
package/skeleton/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, getUid, isAttrTrue, NectaryElement, shouldReduceMotion } from '../utils';
2
- const templateHTML = '<style>:host{display:block}#wrapper{position:relative;display:flex;flex-direction:column;gap:16px;height:100%;box-sizing:border-box;overflow:hidden}:host([card]:not([card=false]))>#wrapper{padding:16px;background-color:var(--sinch-color-snow-100);border-radius:var(--sinch-shape-radius-l);border:1px solid var(--sinch-color-snow-500)}#shimmer{position:absolute;inset:0;background-image:linear-gradient(90deg,transparent 0,var(--sinch-color-snow-400) 100px,transparent 200px);clip-path:url("#clip")}#svg{display:block;width:0;height:0}</style><svg id="svg"><defs><clipPath id="clip"></clipPath></defs></svg><div id="wrapper"><slot></slot><div id="shimmer"></div></div>';
2
+ const templateHTML = '<style>:host{display:block}#wrapper{position:relative;display:flex;flex-direction:column;gap:16px;height:100%;box-sizing:border-box;overflow:hidden}:host([card]:not([card=false]))>#wrapper{padding:16px;background-color:var(--sinch-sys-color-container-main-default);border-radius:var(--sinch-sys-shape-radius-l);border:1px solid var(--sinch-sys-color-border-light)}#shimmer{position:absolute;inset:0;background-image:linear-gradient(90deg,transparent 0,var(--sinch-sys-color-container-contrast-primary-default) 100px,transparent 200px);clip-path:url("#clip")}#svg{display:block;width:0;height:0}</style><svg id="svg"><defs><clipPath id="clip"></clipPath></defs></svg><div id="wrapper"><slot></slot><div id="shimmer"></div></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  const ANIMATION_DURATION = 2000;
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, getCssVar, NectaryElement, attrValueToInteger, shouldReduceMotion } from '../utils';
2
- const templateHTML = '<style>:host{display:block;height:var(--sinch-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([size=xs]){height:var(--sinch-size-xs);--sinch-shape-radius:var(--sinch-shape-radius-xs)}:host([size="s"]){height:var(--sinch-size-s);--sinch-shape-radius:var(--sinch-shape-radius-s)}:host([size="m"]){height:var(--sinch-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([size="l"]){height:var(--sinch-size-l);--sinch-shape-radius:var(--sinch-shape-radius-l)}#content{height:100%;background-color:var(--sinch-color-snow-500);border-radius:var(--sinch-shape-radius)}</style><div id="content"></div>';
2
+ const templateHTML = '<style>:host{display:block;height:var(--sinch-sys-size-m);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-m)}:host([size=xs]){height:var(--sinch-sys-size-xs);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-xs)}:host([size="s"]){height:var(--sinch-sys-size-s);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-s)}:host([size="m"]){height:var(--sinch-sys-size-m);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-m)}:host([size="l"]){height:var(--sinch-sys-size-l);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-l)}#content{height:100%;background-color:var(--sinch-sys-color-border-light);border-radius:var(--sinch-local-shape-radius)}</style><div id="content"></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-skeleton-item', class extends NectaryElement {