@nectary/components 0.38.0 → 0.40.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 (148) hide show
  1. package/accordion/index.js +47 -84
  2. package/accordion/types.d.ts +1 -0
  3. package/accordion-item/index.js +26 -53
  4. package/action-menu/index.d.ts +0 -1
  5. package/action-menu/index.js +179 -223
  6. package/action-menu/types.d.ts +8 -18
  7. package/action-menu-option/index.d.ts +1 -0
  8. package/action-menu-option/index.js +51 -62
  9. package/action-menu-option/types.d.ts +9 -0
  10. package/action-menu-option/utils.d.ts +2 -0
  11. package/action-menu-option/utils.js +3 -0
  12. package/alert/index.js +6 -20
  13. package/avatar/index.js +12 -31
  14. package/avatar-badge/index.js +8 -22
  15. package/avatar-status/index.js +1 -1
  16. package/button/index.js +42 -92
  17. package/card/index.d.ts +2 -0
  18. package/card/index.js +24 -87
  19. package/chat-avatar/index.js +8 -22
  20. package/chat-block/index.js +29 -69
  21. package/chat-bubble/index.js +6 -20
  22. package/checkbox/index.js +55 -107
  23. package/chip/index.d.ts +13 -0
  24. package/chip/index.js +137 -0
  25. package/chip/types.d.ts +38 -0
  26. package/color-menu/index.d.ts +13 -0
  27. package/color-menu/index.js +464 -0
  28. package/color-menu/types.d.ts +37 -0
  29. package/color-swatch/index.d.ts +13 -0
  30. package/color-swatch/index.js +59 -0
  31. package/color-swatch/types.d.ts +12 -0
  32. package/colors.json +57 -49
  33. package/date-picker/index.js +196 -287
  34. package/date-picker/types.d.ts +25 -1
  35. package/dialog/index.d.ts +1 -0
  36. package/dialog/index.js +72 -143
  37. package/dropdown-checkbox-option/index.js +6 -20
  38. package/dropdown-radio-option/index.js +6 -20
  39. package/field/index.js +25 -63
  40. package/file-drop/index.js +123 -200
  41. package/file-picker/index.d.ts +0 -1
  42. package/file-picker/index.js +55 -108
  43. package/file-status/index.js +15 -39
  44. package/help-tooltip/index.js +1 -1
  45. package/horizontal-stepper/index.js +33 -59
  46. package/horizontal-stepper-item/index.js +13 -37
  47. package/icon-button/index.js +39 -84
  48. package/icons-channel/notify/index.d.ts +11 -0
  49. package/icons-channel/notify/index.js +4 -0
  50. package/illustrations/create-illustration-class.js +1 -1
  51. package/inline-alert/index.js +30 -82
  52. package/input/index.js +113 -222
  53. package/link/index.js +46 -96
  54. package/list-item/index.js +1 -1
  55. package/package.json +12 -14
  56. package/pagination/index.js +109 -163
  57. package/pagination/types.d.ts +1 -0
  58. package/popover/index.js +224 -294
  59. package/progress/index.js +9 -28
  60. package/radio/index.js +103 -169
  61. package/radio/types.d.ts +1 -0
  62. package/radio-option/index.js +24 -48
  63. package/segment/index.js +50 -131
  64. package/segment-collapse/index.js +24 -49
  65. package/segment-collapse/types.d.ts +1 -0
  66. package/segmented-control/index.js +36 -73
  67. package/segmented-control/types.d.ts +1 -0
  68. package/segmented-control-option/index.js +41 -87
  69. package/segmented-icon-control/index.js +47 -84
  70. package/segmented-icon-control/types.d.ts +1 -0
  71. package/segmented-icon-control-option/index.js +38 -79
  72. package/select-button/index.d.ts +13 -0
  73. package/select-button/index.js +153 -0
  74. package/select-button/types.d.ts +43 -0
  75. package/select-menu/index.d.ts +11 -0
  76. package/select-menu/index.js +346 -0
  77. package/select-menu/types.d.ts +29 -0
  78. package/{dropdown-text-option → select-menu-option}/index.d.ts +5 -7
  79. package/select-menu-option/index.js +76 -0
  80. package/{select-option → select-menu-option}/types.d.ts +8 -9
  81. package/stop-events/index.js +7 -20
  82. package/table-head-cell/index.js +7 -21
  83. package/tabs/index.js +103 -165
  84. package/tabs/types.d.ts +1 -0
  85. package/tabs-option/index.js +20 -44
  86. package/tag/index.d.ts +1 -1
  87. package/tag/index.js +42 -36
  88. package/tag/types.d.ts +13 -7
  89. package/textarea/index.js +92 -167
  90. package/theme.css +80 -49
  91. package/tile-control/index.js +55 -96
  92. package/tile-control-option/index.js +40 -86
  93. package/time-picker/index.js +224 -368
  94. package/time-picker/types.d.ts +5 -1
  95. package/title/index.js +6 -20
  96. package/toast/index.d.ts +17 -0
  97. package/toast/index.js +115 -0
  98. package/toast/types.d.ts +28 -0
  99. package/toast/utils.d.ts +5 -0
  100. package/toast/utils.js +6 -0
  101. package/toast-manager/index.d.ts +17 -0
  102. package/toast-manager/index.js +195 -0
  103. package/toast-manager/types.d.ts +7 -0
  104. package/toggle/index.js +55 -108
  105. package/toggle/types.d.ts +1 -0
  106. package/types.d.ts +7 -0
  107. package/utils/colors.d.ts +10 -0
  108. package/utils/colors.js +121 -0
  109. package/{utils.d.ts → utils/index.d.ts} +18 -9
  110. package/{utils.js → utils/index.js} +118 -39
  111. package/vertical-stepper/index.js +29 -50
  112. package/vertical-stepper-item/index.js +13 -37
  113. package/card-button/index.d.ts +0 -11
  114. package/card-button/index.js +0 -77
  115. package/card-button/types.d.ts +0 -12
  116. package/card-link/index.d.ts +0 -12
  117. package/card-link/index.js +0 -115
  118. package/card-link/types.d.ts +0 -14
  119. package/dropdown/index.d.ts +0 -12
  120. package/dropdown/index.js +0 -415
  121. package/dropdown/types.d.ts +0 -30
  122. package/dropdown-text-option/index.js +0 -104
  123. package/dropdown-text-option/types.d.ts +0 -16
  124. package/search/index.d.ts +0 -14
  125. package/search/index.js +0 -523
  126. package/search/types.d.ts +0 -25
  127. package/search-option/index.d.ts +0 -11
  128. package/search-option/index.js +0 -55
  129. package/search-option/types.d.ts +0 -9
  130. package/select/index.d.ts +0 -13
  131. package/select/index.js +0 -316
  132. package/select/types.d.ts +0 -53
  133. package/select-option/index.d.ts +0 -11
  134. package/select-option/index.js +0 -8
  135. package/tag/utils.d.ts +0 -2
  136. package/tag/utils.js +0 -1
  137. package/tag-close/index.d.ts +0 -12
  138. package/tag-close/index.js +0 -38
  139. package/tag-close/types.d.ts +0 -3
  140. package/tag-close/types.js +0 -1
  141. /package/{card-button → chip}/types.js +0 -0
  142. /package/{card-link → color-menu}/types.js +0 -0
  143. /package/{dropdown-text-option → color-swatch}/types.js +0 -0
  144. /package/{dropdown → select-button}/types.js +0 -0
  145. /package/{search → select-menu}/types.js +0 -0
  146. /package/{search-option → select-menu-option}/types.js +0 -0
  147. /package/{select → toast}/types.js +0 -0
  148. /package/{select-option → toast-manager}/types.js +0 -0
@@ -0,0 +1,38 @@
1
+ import type { TSinchElementReact } from '../types';
2
+ import type { TSinchColorName } from '../utils/colors';
3
+ export declare type TSinchChipElement = HTMLElement & {
4
+ /** Text */
5
+ text: string;
6
+ /** Color, gray by default */
7
+ color: TSinchColorName | null;
8
+ /** Small */
9
+ small: boolean;
10
+ /** Click event */
11
+ addEventListener(type: '-click', listener: (e: CustomEvent<void>) => void): void;
12
+ /** Focus event */
13
+ addEventListener(type: '-focus', listener: (e: CustomEvent<void>) => void): void;
14
+ /** Blur event */
15
+ addEventListener(type: '-blur', listener: (e: CustomEvent<void>) => void): void;
16
+ /** Text */
17
+ setAttribute(name: 'text', value: string): void;
18
+ /** Color, gray by default */
19
+ setAttribute(name: 'color', value: TSinchColorName): void;
20
+ /** Small */
21
+ setAttribute(name: 'small', value: ''): void;
22
+ };
23
+ export declare type TSinchChipReact = TSinchElementReact<TSinchChipElement> & {
24
+ /** Text */
25
+ text: string;
26
+ /** Color, gray by default */
27
+ color?: TSinchColorName;
28
+ /** Small */
29
+ small?: boolean;
30
+ /** Click event handler */
31
+ 'on-click'?: (e: CustomEvent<void>) => void;
32
+ /** Focus event handler */
33
+ 'on-focus'?: (e: CustomEvent<void>) => void;
34
+ /** Blur event handler */
35
+ 'on-blur'?: (e: CustomEvent<void>) => void;
36
+ /** Label that is used for a11y` */
37
+ 'aria-label': string;
38
+ };
@@ -0,0 +1,13 @@
1
+ import '../color-swatch';
2
+ import '../icons/check';
3
+ import type { TSinchSelectMenuElement, TSinchSelectMenuReact } from './types';
4
+ declare global {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ 'sinch-color-menu': TSinchSelectMenuReact;
8
+ }
9
+ }
10
+ interface HTMLElementTagNameMap {
11
+ 'sinch-color-menu': TSinchSelectMenuElement;
12
+ }
13
+ }
@@ -0,0 +1,464 @@
1
+ import '../color-swatch';
2
+ import '../icons/check';
3
+ import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getCsvSet, getIntegerAttribute, getLiteralAttribute, getReactEventHandler, getRect, NectaryElement, setClass, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from '../utils';
4
+ import { assertColorNameValue, colorMap, colorNameValues, NO_COLOR } from '../utils/colors';
5
+ const optionTemplateHTML = '<div class="option" role="option"><sinch-color-swatch></sinch-color-swatch></div>';
6
+ const templateHTML = '<style>:host{display:block;outline:0}#listbox{display:flex;flex-direction:row;flex-wrap:wrap;padding:4px 10px;overflow-y:auto}#listbox:empty{display:none}#check{position:absolute;left:10px;top:16px;--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:24px}#check.inverted{--sinch-color-icon:var(--sinch-color-snow-100)}.option{position:relative;cursor:pointer;width:32px;height:32px;padding:12px 6px}.option::after{content:"";position:absolute;width:34px;height:34px;inset:9px 3px;border:2px solid transparent;border-radius:50%;pointer-events:none}.option[data-selected]:not([data-checked])::after{border-color:var(--sinch-color-aqua-400)}.option *{pointer-events:none}</style><sinch-icon-check id="check"></sinch-icon-check><div id="listbox" role="presentation"></div>';
7
+ const NUM_COLS_DEFAULT = 5;
8
+ const ITEM_WIDTH = 44;
9
+ const ITEM_HEIGHT = 56;
10
+ const template = document.createElement('template');
11
+ const optionTemplate = document.createElement('template');
12
+ template.innerHTML = templateHTML;
13
+ optionTemplate.innerHTML = optionTemplateHTML;
14
+ defineCustomElement('sinch-color-menu', class extends NectaryElement {
15
+ #$listbox;
16
+ #$checkIcon;
17
+ #controller = new AbortController();
18
+ #prevColorsValue = '';
19
+ #isConnected = false;
20
+
21
+ constructor() {
22
+ super();
23
+ const shadowRoot = this.attachShadow();
24
+ shadowRoot.appendChild(template.content.cloneNode(true));
25
+ this.#$listbox = shadowRoot.querySelector('#listbox');
26
+ this.#$checkIcon = shadowRoot.querySelector('#check');
27
+ }
28
+
29
+ connectedCallback() {
30
+ const {
31
+ signal
32
+ } = this.#controller;
33
+ this.setAttribute('role', 'listbox');
34
+ this.setAttribute('tabindex', '0');
35
+ this.addEventListener('keydown', this.#onListboxKeyDown, {
36
+ signal
37
+ });
38
+ this.addEventListener('-keydown', this.#onContexKeydown, {
39
+ signal
40
+ });
41
+ this.addEventListener('blur', this.#onListboxBlur, {
42
+ signal
43
+ });
44
+ this.#$listbox.addEventListener('click', this.#onListboxClick, {
45
+ signal
46
+ });
47
+ this.addEventListener('-change', this.#onChangeReactHandler, {
48
+ signal
49
+ });
50
+ this.addEventListener('-visibility', this.#onContextVisibility, {
51
+ signal
52
+ });
53
+ this.dispatchEvent(new CustomEvent('-context-connect-keydown', {
54
+ bubbles: true
55
+ }));
56
+ this.dispatchEvent(new CustomEvent('-context-connect-visibility', {
57
+ bubbles: true
58
+ }));
59
+ requestAnimationFrame(this.#onMount);
60
+ }
61
+
62
+ disconnectedCallback() {
63
+ this.#isConnected = false;
64
+ this.#prevColorsValue = null;
65
+ this.#controller.abort();
66
+ this.dispatchEvent(new CustomEvent('-context-disconnect-keydown', {
67
+ bubbles: true
68
+ }));
69
+ this.dispatchEvent(new CustomEvent('-context-disconnect-visibility', {
70
+ bubbles: true
71
+ }));
72
+ }
73
+
74
+ static get observedAttributes() {
75
+ return ['value', 'rows', 'cols', 'colors'];
76
+ }
77
+
78
+ set value(value) {
79
+ updateLiteralAttribute(this, colorNameValues, 'value', value);
80
+ }
81
+
82
+ get value() {
83
+ return getLiteralAttribute(this, colorNameValues, 'value', NO_COLOR);
84
+ }
85
+
86
+ set colors(value) {
87
+ updateAttribute(this, 'colors', value);
88
+ }
89
+
90
+ get colors() {
91
+ return getAttribute(this, 'colors');
92
+ }
93
+
94
+ set rows(value) {
95
+ updateIntegerAttribute(this, 'rows', value);
96
+ }
97
+
98
+ get rows() {
99
+ return getIntegerAttribute(this, 'rows', null);
100
+ }
101
+
102
+ set cols(value) {
103
+ updateIntegerAttribute(this, 'cols', value);
104
+ }
105
+
106
+ get cols() {
107
+ return getIntegerAttribute(this, 'cols', null);
108
+ }
109
+
110
+ nthItemRect(index) {
111
+ if (index < 0 || index >= colorNameValues.length) {
112
+ return null;
113
+ }
114
+
115
+ const $item = this.#$listbox.children[index];
116
+
117
+ if ($item != null) {
118
+ return getRect($item);
119
+ }
120
+
121
+ return null;
122
+ }
123
+
124
+ attributeChangedCallback(name, oldVal, newVal) {
125
+ if (oldVal === newVal) {
126
+ return;
127
+ }
128
+
129
+ switch (name) {
130
+ case 'value':
131
+ {
132
+ if (this.#isConnected) {
133
+ assertColorNameValue(newVal);
134
+ this.#onValueChange();
135
+ }
136
+
137
+ break;
138
+ }
139
+
140
+ case 'colors':
141
+ {
142
+ if (this.#isConnected) {
143
+ this.#updateColors();
144
+ }
145
+
146
+ break;
147
+ }
148
+
149
+ case 'rows':
150
+ {
151
+ this.#updateRows();
152
+ break;
153
+ }
154
+
155
+ case 'cols':
156
+ {
157
+ if (this.#isConnected) {
158
+ this.#updateColumns();
159
+ }
160
+
161
+ break;
162
+ }
163
+ }
164
+ }
165
+
166
+ #updateColors() {
167
+ const colorsValue = this.colors;
168
+
169
+ if (colorsValue === this.#prevColorsValue) {
170
+ return;
171
+ }
172
+
173
+ this.#prevColorsValue = colorsValue;
174
+ const colorNames = colorsValue !== null ? getCsvSet(colorsValue) : colorNameValues;
175
+ const fragment = document.createDocumentFragment();
176
+
177
+ for (const col of colorNames) {
178
+ if (col === NO_COLOR) {
179
+ continue;
180
+ }
181
+
182
+ const optFrag = optionTemplate.content.cloneNode(true);
183
+ const $opt = optFrag.querySelector('.option');
184
+ const $swatch = optFrag.querySelector('sinch-color-swatch');
185
+ updateAttribute($opt, 'data-value', col);
186
+ updateAttribute($opt, 'title', col);
187
+ updateAttribute($swatch, 'name', col);
188
+ fragment.appendChild(optFrag);
189
+ }
190
+
191
+ this.#$listbox.replaceChildren(fragment);
192
+ this.#updateColumns();
193
+ this.#onValueChange();
194
+ }
195
+
196
+ #updateRows() {
197
+ const rowsValue = getAttribute(this, 'rows');
198
+ this.#$listbox.style.maxHeight = attrValueToPixels(rowsValue, {
199
+ min: 2,
200
+ itemSizeMultiplier: ITEM_HEIGHT
201
+ });
202
+ }
203
+
204
+ #updateColumns() {
205
+ const colsValue = getAttribute(this, 'cols');
206
+ const numItems = this.#$listbox.children.length;
207
+ this.#$listbox.style.width = attrValueToPixels(colsValue, {
208
+ min: 1,
209
+ max: numItems,
210
+ defaultValue: Math.min(numItems, NUM_COLS_DEFAULT),
211
+ itemSizeMultiplier: ITEM_WIDTH
212
+ });
213
+ }
214
+
215
+ #onMount = () => {
216
+ this.#updateColors();
217
+ this.#isConnected = true;
218
+ };
219
+ #onListboxBlur = () => {
220
+ this.#selectOption(null);
221
+ };
222
+ #onListboxClick = e => {
223
+ const $elem = e.target;
224
+
225
+ if ($elem === this.#$listbox) {
226
+ return;
227
+ }
228
+
229
+ this.#dispatchChangeEvent($elem);
230
+ this.#selectOption($elem);
231
+ };
232
+ #onContextVisibility = e => {
233
+ if (e.detail) {
234
+ this.#selectOption(this.#findCheckedOption());
235
+ } else {
236
+ this.#selectOption(null);
237
+ }
238
+ };
239
+ #onContexKeydown = e => {
240
+ this.#handleKeydown(e.detail);
241
+ };
242
+ #onListboxKeyDown = e => {
243
+ this.#handleKeydown(e);
244
+ };
245
+
246
+ #handleKeydown(e) {
247
+ switch (e.code) {
248
+ case 'Space':
249
+ case 'Enter':
250
+ {
251
+ const $option = this.#findSelectedOption();
252
+
253
+ if ($option !== null) {
254
+ e.preventDefault();
255
+ this.#dispatchChangeEvent($option);
256
+ }
257
+
258
+ break;
259
+ }
260
+
261
+ case 'ArrowLeft':
262
+ {
263
+ e.preventDefault();
264
+ this.#selectOption(this.#getPrevOption());
265
+ break;
266
+ }
267
+
268
+ case 'ArrowRight':
269
+ {
270
+ e.preventDefault();
271
+ this.#selectOption(this.#getNextOption());
272
+ break;
273
+ }
274
+
275
+ case 'ArrowDown':
276
+ {
277
+ e.preventDefault();
278
+ this.#selectOption(this.#getNextRowOption());
279
+ break;
280
+ }
281
+
282
+ case 'ArrowUp':
283
+ {
284
+ e.preventDefault();
285
+ this.#selectOption(this.#getPrevRowOption());
286
+ break;
287
+ }
288
+ }
289
+ }
290
+
291
+ #onValueChange() {
292
+ if (!this.hasAttribute('value')) {
293
+ this.#$checkIcon.remove();
294
+ return;
295
+ }
296
+
297
+ const value = this.value;
298
+ this.#$checkIcon.remove();
299
+
300
+ for (const $option of this.#getOptionElements()) {
301
+ const isChecked = value === getAttribute($option, 'data-value', '');
302
+
303
+ if (isChecked) {
304
+ $option.appendChild(this.#$checkIcon);
305
+ setClass(this.#$checkIcon, 'inverted', colorMap[value].isInverted);
306
+ }
307
+
308
+ updateBooleanAttribute($option, 'data-checked', isChecked);
309
+ updateExplicitBooleanAttribute($option, 'aria-selected', isChecked);
310
+ }
311
+ }
312
+
313
+ #getFirstOption() {
314
+ const $options = this.#getOptionElements();
315
+ return $options[0] ?? null;
316
+ }
317
+
318
+ #getLastOption() {
319
+ const $options = this.#getOptionElements();
320
+ return $options[$options.length - 1] ?? null;
321
+ }
322
+
323
+ #getNextOption() {
324
+ const index = this.#getSelectedOptionIndex();
325
+
326
+ if (index !== null) {
327
+ const $options = this.#getOptionElements();
328
+ return $options[(1 + index) % $options.length];
329
+ }
330
+
331
+ return this.#getFirstOption();
332
+ }
333
+
334
+ #getPrevOption() {
335
+ const index = this.#getSelectedOptionIndex();
336
+
337
+ if (index !== null) {
338
+ const $options = this.#getOptionElements();
339
+ return $options[(index - 1 + $options.length) % $options.length];
340
+ }
341
+
342
+ return this.#getLastOption();
343
+ }
344
+
345
+ #getNextRowOption() {
346
+ const selectedIndex = this.#getSelectedOptionIndex();
347
+
348
+ if (selectedIndex !== null) {
349
+ const $options = this.#getOptionElements();
350
+ const numCols = Math.min(this.cols ?? NUM_COLS_DEFAULT, $options.length);
351
+ const numColsInLastRow = $options.length % numCols;
352
+
353
+ if (numColsInLastRow > 0) {
354
+ if (selectedIndex < $options.length - numCols) {
355
+ return $options[selectedIndex + numCols];
356
+ }
357
+
358
+ if (numColsInLastRow > 0 && selectedIndex < $options.length - numColsInLastRow) {
359
+ return $options[$options.length - 1];
360
+ }
361
+
362
+ return $options[selectedIndex + numColsInLastRow - $options.length];
363
+ }
364
+
365
+ return $options[(selectedIndex + numCols) % $options.length];
366
+ }
367
+
368
+ return this.#getFirstOption();
369
+ }
370
+
371
+ #getPrevRowOption() {
372
+ const selectedIndex = this.#getSelectedOptionIndex();
373
+
374
+ if (selectedIndex !== null) {
375
+ const $options = this.#getOptionElements();
376
+ const numCols = Math.min(this.cols ?? NUM_COLS_DEFAULT, $options.length);
377
+ const numColsInLastRow = $options.length % numCols;
378
+
379
+ if (selectedIndex < numColsInLastRow) {
380
+ return $options[(selectedIndex - numColsInLastRow + $options.length) % $options.length];
381
+ }
382
+
383
+ if (selectedIndex < numCols) {
384
+ return $options[(selectedIndex - numCols - numColsInLastRow + $options.length) % $options.length];
385
+ }
386
+
387
+ return $options[(selectedIndex - numCols + $options.length) % $options.length];
388
+ }
389
+
390
+ return this.#getFirstOption();
391
+ }
392
+
393
+ #selectOption($option) {
394
+ const hasRows = this.hasAttribute('rows');
395
+
396
+ for (const $op of this.#getOptionElements()) {
397
+ const isSelected = $op === $option;
398
+ updateBooleanAttribute($op, 'data-selected', isSelected);
399
+
400
+ if (isSelected && hasRows) {
401
+ $op.scrollIntoView?.({
402
+ block: 'nearest'
403
+ });
404
+ }
405
+ }
406
+ }
407
+
408
+ #getOptionElements() {
409
+ return Array.from(this.#$listbox.children);
410
+ }
411
+
412
+ #getSelectedOptionIndex() {
413
+ const elements = this.#getOptionElements();
414
+
415
+ for (let i = 0; i < elements.length; i++) {
416
+ const el = elements[i];
417
+
418
+ if (getBooleanAttribute(el, 'data-selected')) {
419
+ return i;
420
+ }
421
+ }
422
+
423
+ return null;
424
+ }
425
+
426
+ #findSelectedOption() {
427
+ const elements = this.#getOptionElements();
428
+
429
+ for (const el of elements) {
430
+ if (getBooleanAttribute(el, 'data-selected')) {
431
+ return el;
432
+ }
433
+ }
434
+
435
+ return null;
436
+ }
437
+
438
+ #findCheckedOption() {
439
+ const elements = this.#getOptionElements();
440
+ const value = this.value;
441
+
442
+ for (const $el of elements) {
443
+ if (getAttribute($el, 'data-value') === value) {
444
+ return $el;
445
+ }
446
+ }
447
+
448
+ return null;
449
+ }
450
+
451
+ #dispatchChangeEvent($opt) {
452
+ if ($opt === null) {
453
+ return;
454
+ }
455
+
456
+ this.dispatchEvent(new CustomEvent('-change', {
457
+ detail: getAttribute($opt, 'data-value')
458
+ }));
459
+ }
460
+
461
+ #onChangeReactHandler = e => {
462
+ getReactEventHandler(this, 'on-change')?.(e);
463
+ };
464
+ });
@@ -0,0 +1,37 @@
1
+ import type { TRect, TSinchElementReact } from '../types';
2
+ import type { TSinchColorName } from '../utils/colors';
3
+ export declare type TSinchSelectMenuElement = HTMLElement & {
4
+ /** Value */
5
+ value: TSinchColorName;
6
+ /** How many rows to show and scroll the rest */
7
+ rows: number | null;
8
+ /** How many cols to show and scroll the rest */
9
+ cols: number | null;
10
+ /** Comma-separated color names, all colors by default */
11
+ colors: string | null;
12
+ nthItemRect(index: number): TRect | null;
13
+ /** Change event */
14
+ addEventListener(type: '-change', listener: (e: CustomEvent<TSinchColorName>) => void): void;
15
+ /** Comma-separated color names, all colors by default */
16
+ setAttribute(name: 'colors', value: string): void;
17
+ /** Value */
18
+ setAttribute(name: 'value', value: TSinchColorName): void;
19
+ /** How many rows to show and scroll the rest */
20
+ setAttribute(name: 'rows', value: string): void;
21
+ /** How many cols to show and scroll the rest */
22
+ setAttribute(name: 'cols', value: string): void;
23
+ };
24
+ export declare type TSinchSelectMenuReact = TSinchElementReact<TSinchSelectMenuElement> & {
25
+ /** Value */
26
+ value: TSinchColorName;
27
+ /** How many rows to show and scroll the rest */
28
+ rows?: number;
29
+ /** How many cols to show and scroll the rest */
30
+ cols?: number;
31
+ /** Comma-separated color names, all colors by default */
32
+ colors?: string;
33
+ /** Label that is used for a11y */
34
+ 'aria-label': string;
35
+ /** Change event handler */
36
+ 'on-change'?: (e: CustomEvent<TSinchColorName>) => void;
37
+ };
@@ -0,0 +1,13 @@
1
+ import '../icons/cancel';
2
+ import '../text';
3
+ import type { TSinchColorSwatchElement, TSinchColorSwatchReact } from './types';
4
+ declare global {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ 'sinch-color-swatch': TSinchColorSwatchReact;
8
+ }
9
+ }
10
+ interface HTMLElementTagNameMap {
11
+ 'sinch-color-swatch': TSinchColorSwatchElement;
12
+ }
13
+ }
@@ -0,0 +1,59 @@
1
+ import '../icons/cancel';
2
+ import '../text';
3
+ import { defineCustomElement, getLiteralAttribute, updateLiteralAttribute, NectaryElement, setClass } from '../utils';
4
+ import { assertColorNameValue, colorMap, colorNameValues, NO_COLOR } from '../utils/colors';
5
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle}#wrapper{width:var(--sinch-size-icon,32px);height:var(--sinch-size-icon,32px);border-radius:50%}#wrapper.no-color{background:linear-gradient(45deg,var(--sinch-color-berry-200),var(--sinch-color-orange-200),var(--sinch-color-bolt-200),var(--sinch-color-grass-200),var(--sinch-color-aqua-200),var(--sinch-color-night-200),var(--sinch-color-violet-200))}</style><div id="wrapper"></div>';
6
+ const template = document.createElement('template');
7
+ template.innerHTML = templateHTML;
8
+ defineCustomElement('sinch-color-swatch', class extends NectaryElement {
9
+ #$wrapper;
10
+
11
+ constructor() {
12
+ super();
13
+ const shadowRoot = this.attachShadow();
14
+ shadowRoot.appendChild(template.content.cloneNode(true));
15
+ this.#$wrapper = shadowRoot.querySelector('#wrapper');
16
+ }
17
+
18
+ connectedCallback() {
19
+ this.#updateColor();
20
+ }
21
+
22
+ get name() {
23
+ return getLiteralAttribute(this, colorNameValues, 'name', NO_COLOR);
24
+ }
25
+
26
+ set name(value) {
27
+ updateLiteralAttribute(this, colorNameValues, 'name', value);
28
+ }
29
+
30
+ static get observedAttributes() {
31
+ return ['name'];
32
+ }
33
+
34
+ attributeChangedCallback(name, oldValue, newVal) {
35
+ if (oldValue === newVal) {
36
+ return;
37
+ }
38
+
39
+ switch (name) {
40
+ case 'name':
41
+ {
42
+ assertColorNameValue(newVal);
43
+ this.#updateColor();
44
+ break;
45
+ }
46
+ }
47
+ }
48
+
49
+ #updateColor() {
50
+ const colorName = this.name;
51
+
52
+ if (colorName !== NO_COLOR) {
53
+ this.#$wrapper.style.backgroundColor = `var(--sinch-color-${colorMap[colorName].value})`;
54
+ }
55
+
56
+ setClass(this.#$wrapper, 'no-color', colorName === NO_COLOR);
57
+ }
58
+
59
+ });
@@ -0,0 +1,12 @@
1
+ import type { TSinchElementReact } from '../types';
2
+ import type { TSinchColorName } from '../utils/colors';
3
+ export declare type TSinchColorSwatchElement = HTMLElement & {
4
+ /** Color name */
5
+ name: TSinchColorName;
6
+ /** Color name */
7
+ setAttribute(name: 'name', value: TSinchColorName): void;
8
+ };
9
+ export declare type TSinchColorSwatchReact = TSinchElementReact<TSinchColorSwatchElement> & {
10
+ /** Color name */
11
+ name: TSinchColorName;
12
+ };