@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
package/input/index.js CHANGED
@@ -1,16 +1,11 @@
1
- import '../icon-button';
2
- import '../icon';
3
- import '../stop-events';
4
- import { Context, defineCustomElement, getAttribute, getBooleanAttribute, getCssVar, getLiteralAttribute, getReactEventHandler, getRect, isAttrTrue, NectaryElement, setClass, subscribeContext, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateLiteralAttribute } from '../utils';
5
- import { assertSize, DEFAULT_SIZE, sizeValues } from '../utils/size';
6
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle}:host([data-size="l"]){--sinch-size:var(--sinch-size-l);--sinch-size-icon:var(--sinch-input-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-input-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-input-icon-size-s);--sinch-shape-radius:var(--sinch-shape-radius-s)}#wrapper{position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;border-radius:var(--sinch-shape-radius);width:100%;height:var(--sinch-size);background-color:var(--sinch-color-bg-primary-light)}#input{all:initial;flex:1;min-width:0;height:100%;padding:0 12px 0 40px;font:var(--sinch-font-text-m);color:var(--sinch-color-text-default)}#input::placeholder{font:var(--sinch-font-text-m);color:var(--sinch-color-text-muted);opacity:1}#border{position:absolute;border:1px solid var(--sinch-color-border-dark);border-radius:var(--sinch-shape-radius);inset:0;pointer-events:none}#input:disabled{color:var(--sinch-color-text-disabled);-webkit-text-fill-color:var(--sinch-color-text-disabled)}:host([data-size="s"]) #input{padding-left:32px}:host([invalid]:not([invalid=false]):not([disabled])) #border{border-color:var(--sinch-color-text-invalid)}#input:disabled::placeholder{color:var(--sinch-color-text-disabled)}#input:disabled+#border{border-color:var(--sinch-color-border-disabled)}#input:focus+#border{border-color:var(--sinch-color-border-focus);border-width:2px}#input[type=password]{font-size:1.5em;letter-spacing:.1em}#icon-wrapper{position:relative;height:100%}#icon{position:absolute;display:flex;align-items:center;left:10px;top:0;bottom:0;pointer-events:none;--sinch-color-icon:var(--sinch-color-stormy-500)}:host([disabled]:not([disabled=false])) #icon{--sinch-color-icon:var(--sinch-color-text-disabled)}#icon-wrapper.empty{display:none}#icon-wrapper.empty~#input{padding-left:12px}#clear-wrapper{margin-left:-10px;margin-right:4px}#clear{display:none;--sinch-icon-button-color-icon:var(--sinch-color-stormy-500)}:host([value]:not([value=""])) #clear[data-focus],:host([value]:not([value=""])) #clear[data-tooltip]{display:block}#right{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;padding-right:4px}#right.empty{display:none}#left{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;padding-left:4px}#left.empty{display:none}</style><div id="wrapper"><div id="left"><slot name="left"></slot></div><div id="icon-wrapper"><div id="icon"><slot name="icon"></slot></div></div><input id="input" type="text"/><div id="border"></div><div id="clear-wrapper"><sinch-stop-events events="keydown"><sinch-icon-button id="clear" aria-label="Clear input value"><sinch-icon id="icon-clear" slot="icon"></sinch-icon></sinch-icon-button></sinch-stop-events></div><div id="right"><slot name="right"></slot></div></div>';
7
- import { assertType, inputTypes } from './utils';
1
+ import { Context, defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, getReactEventHandler, isAttrTrue, NectaryElement, setClass, subscribeContext, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateLiteralAttribute } from '../utils';
2
+ import { DEFAULT_SIZE, sizeValues } from '../utils/size';
3
+ const templateHTML = '<style>:host{all:initial;display:inline-block;vertical-align:middle}#wrapper{position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;border-radius:var(--sinch-local-shape-radius);width:100%;height:var(--sinch-local-size);background-color:var(--sinch-comp-input-color-default-background-initial);--sinch-local-size:var(--sinch-comp-input-size-container-m);--sinch-global-size-icon:var(--sinch-comp-input-size-icon-m);--sinch-local-shape-radius:var(--sinch-comp-input-shape-radius-size-m)}:host([data-size="l"])>#wrapper{--sinch-local-size:var(--sinch-comp-input-size-container-l);--sinch-global-size-icon:var(--sinch-comp-input-size-icon-l);--sinch-local-shape-radius:var(--sinch-comp-input-shape-radius-size-l)}:host([data-size="m"])>#wrapper{--sinch-local-size:var(--sinch-comp-input-size-container-m);--sinch-global-size-icon:var(--sinch-comp-input-size-icon-m);--sinch-local-shape-radius:var(--sinch-comp-input-shape-radius-size-m)}:host([data-size="s"])>#wrapper{--sinch-local-size:var(--sinch-comp-input-size-container-s);--sinch-global-size-icon:var(--sinch-comp-input-size-icon-s);--sinch-local-shape-radius:var(--sinch-comp-input-shape-radius-size-s)}#input{all:initial;flex:1;flex-basis:0;min-width:0;height:100%;padding:0 12px;font:var(--sinch-comp-input-font-input);color:var(--sinch-comp-input-color-default-text-initial)}#input::placeholder{font:var(--sinch-comp-input-font-placeholder);color:var(--sinch-comp-input-color-default-text-placeholder);opacity:1}#border{position:absolute;border:1px solid var(--sinch-comp-input-color-default-border-initial);border-radius:var(--sinch-local-shape-radius);inset:0;pointer-events:none}#input:disabled{color:var(--sinch-comp-input-color-disabled-text-initial);-webkit-text-fill-color:var(--sinch-comp-input-color-disabled-text-initial)}#input:disabled+#border{border-color:var(--sinch-comp-input-color-disabled-border-initial)}#input:focus+#border{border-color:var(--sinch-comp-input-color-default-border-focus);border-width:2px}:host([invalid]:not(:focus-within)) #input:enabled+#border{border-color:var(--sinch-comp-input-color-invalid-border-initial)}#input[type=password]{font-size:1.5em;letter-spacing:.1em}#icon-wrapper{position:relative;height:100%}#icon{position:absolute;display:flex;align-items:center;left:12px;top:0;bottom:0;pointer-events:none;--sinch-global-color-icon:var(--sinch-comp-input-color-default-icon-initial)}:host([disabled]) #icon{--sinch-global-color-icon:var(--sinch-comp-input-color-disabled-icon-initial)}#icon-wrapper.empty{display:none}#icon-wrapper.empty~#input{padding-left:12px}#icon-wrapper:not(.empty)~#input{padding-left:calc(var(--sinch-global-size-icon) + 20px)}#right{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;padding-right:4px}#right.empty{display:none}#left{display:flex;flex-direction:row;align-self:stretch;align-items:center;gap:4px;padding-left:4px}#left.empty{display:none}</style><div id="wrapper"><div id="left"><slot name="left"></slot></div><div id="icon-wrapper"><div id="icon"><slot name="icon"></slot></div></div><input id="input" type="text"/><div id="border"></div><div id="right"><slot name="right"></slot></div></div>';
4
+ import { inputTypes } from './utils';
8
5
  const template = document.createElement('template');
9
6
  template.innerHTML = templateHTML;
10
7
  defineCustomElement('sinch-input', class extends NectaryElement {
11
8
  #$input;
12
- #$clear;
13
- #$iconClear;
14
9
  #$iconSlot;
15
10
  #$iconWrapper;
16
11
  #$rightSlot;
@@ -24,9 +19,7 @@ defineCustomElement('sinch-input', class extends NectaryElement {
24
19
  #sizeContext;
25
20
  constructor() {
26
21
  super();
27
- const shadowRoot = this.attachShadow({
28
- delegatesFocus: true
29
- });
22
+ const shadowRoot = this.attachShadow();
30
23
  shadowRoot.appendChild(template.content.cloneNode(true));
31
24
  this.#$input = shadowRoot.querySelector('#input');
32
25
  this.#$iconSlot = shadowRoot.querySelector('slot[name="icon"]');
@@ -35,8 +28,6 @@ defineCustomElement('sinch-input', class extends NectaryElement {
35
28
  this.#$rightWrapper = shadowRoot.querySelector('#right');
36
29
  this.#$leftSlot = shadowRoot.querySelector('slot[name="left"]');
37
30
  this.#$leftWrapper = shadowRoot.querySelector('#left');
38
- this.#$clear = shadowRoot.querySelector('#clear');
39
- this.#$iconClear = shadowRoot.querySelector('#icon-clear');
40
31
  this.#$wrapper = shadowRoot.querySelector('#wrapper');
41
32
  this.#sizeContext = new Context(this.#$wrapper, 'size');
42
33
  }
@@ -53,17 +44,12 @@ defineCustomElement('sinch-input', class extends NectaryElement {
53
44
  this.#$input.addEventListener('keydown', this.#onSelectionChange, options);
54
45
  this.#$input.addEventListener('focus', this.#onInputFocus, options);
55
46
  this.#$input.addEventListener('blur', this.#onInputBlur, options);
56
- this.#$clear.addEventListener('click', this.#onClearButtonClick, options);
57
- this.#$clear.addEventListener('blur', this.#onClearButtonBlur, options);
58
- this.#$clear.addEventListener('-tooltip-show', this.#onClearButtonTooltipShow, options);
59
- this.#$clear.addEventListener('-tooltip-hide', this.#onClearButtonTooltipHide, options);
60
47
  this.#$iconSlot.addEventListener('slotchange', this.#onIconSlotChange, options);
61
48
  this.#$leftSlot.addEventListener('slotchange', this.#onLeftSlotChange, options);
62
49
  this.#$rightSlot.addEventListener('slotchange', this.#onRightSlotChange, options);
63
50
  this.addEventListener('-change', this.#onChangeReactHandler, options);
64
51
  this.addEventListener('-focus', this.#onFocusReactHandler, options);
65
52
  this.addEventListener('-blur', this.#onBlurReactHandler, options);
66
- updateAttribute(this.#$iconClear, 'name', getCssVar(this, '--sinch-input-icon-clear'));
67
53
  this.#sizeContext.listen(this.#controller.signal);
68
54
  subscribeContext(this, 'size', this.#onContextSize, this.#controller.signal);
69
55
  this.#onIconSlotChange();
@@ -76,15 +62,15 @@ defineCustomElement('sinch-input', class extends NectaryElement {
76
62
  this.#controller.abort();
77
63
  }
78
64
  static get observedAttributes() {
79
- return ['type', 'value', 'placeholder', 'invalid', 'disabled', 'size', 'autocomplete', 'data-size'];
65
+ return ['type', 'value', 'placeholder', 'invalid', 'disabled', 'size', 'autocomplete', 'data-size', 'aria-label'];
80
66
  }
81
- attributeChangedCallback(name, _, newVal) {
67
+ attributeChangedCallback(name, oldVal, newVal) {
68
+ if (oldVal === newVal) {
69
+ return;
70
+ }
82
71
  switch (name) {
83
72
  case 'type':
84
73
  {
85
- if ('production' !== 'production') {
86
- assertType(newVal);
87
- }
88
74
  updateLiteralAttribute(this.#$input, inputTypes, 'type', newVal);
89
75
  updateAttribute(this.#$input, 'spellcheck', newVal === 'password' ? 'false' : null);
90
76
  break;
@@ -112,14 +98,16 @@ defineCustomElement('sinch-input', class extends NectaryElement {
112
98
  }
113
99
  case 'invalid':
114
100
  {
115
- updateExplicitBooleanAttribute(this, 'aria-invalid', isAttrTrue(newVal));
101
+ const isInvalid = isAttrTrue(newVal);
102
+ updateExplicitBooleanAttribute(this, 'aria-invalid', isInvalid);
103
+ updateBooleanAttribute(this, name, isInvalid);
116
104
  break;
117
105
  }
118
106
  case 'disabled':
119
107
  {
120
108
  const isDisabled = isAttrTrue(newVal);
121
109
  this.#$input.disabled = isDisabled;
122
- updateBooleanAttribute(this, 'disabled', isDisabled);
110
+ updateBooleanAttribute(this, name, isDisabled);
123
111
  break;
124
112
  }
125
113
  case 'size':
@@ -129,21 +117,21 @@ defineCustomElement('sinch-input', class extends NectaryElement {
129
117
  }
130
118
  case 'data-size':
131
119
  {
132
- if ('production' !== 'production') {
133
- assertSize(newVal, 'sinch-input');
134
- }
135
120
  this.#onSizeUpdate();
136
121
  break;
137
122
  }
138
123
  case 'autocomplete':
139
124
  {
140
- updateAttribute(this.#$input, 'autocomplete', newVal);
125
+ updateAttribute(this.#$input, name, newVal);
126
+ break;
127
+ }
128
+ case 'aria-label':
129
+ {
130
+ this.#$input.ariaLabel = newVal;
131
+ break;
141
132
  }
142
133
  }
143
134
  }
144
- get nodeName() {
145
- return 'input';
146
- }
147
135
  set type(value) {
148
136
  updateAttribute(this, 'type', value);
149
137
  }
@@ -204,9 +192,6 @@ defineCustomElement('sinch-input', class extends NectaryElement {
204
192
  set selectionDirection(value) {
205
193
  this.#$input.selectionDirection = value;
206
194
  }
207
- get clearButtonRect() {
208
- return getRect(this.#$clear);
209
- }
210
195
  get focusable() {
211
196
  return true;
212
197
  }
@@ -279,14 +264,10 @@ defineCustomElement('sinch-input', class extends NectaryElement {
279
264
  setClass(this.#$rightWrapper, 'empty', isEmpty);
280
265
  };
281
266
  #onInputFocus = () => {
282
- this.#$clear.setAttribute('data-focus', '');
283
267
  this.dispatchEvent(new CustomEvent('-focus'));
284
268
  };
285
- #onInputBlur = e => {
269
+ #onInputBlur = () => {
286
270
  this.dispatchEvent(new CustomEvent('-blur'));
287
- if (e.relatedTarget !== this.#$clear) {
288
- this.#$clear.removeAttribute('data-focus');
289
- }
290
271
  };
291
272
  #onSizeUpdate() {
292
273
  if (!this.isConnected) {
@@ -295,23 +276,6 @@ defineCustomElement('sinch-input', class extends NectaryElement {
295
276
  const size = this.getAttribute('data-size') ?? DEFAULT_SIZE;
296
277
  this.#sizeContext.dispatch(size);
297
278
  }
298
- #onClearButtonClick = () => {
299
- this.#$input.value = '';
300
- this.#$input.focus();
301
- this.#handleInput();
302
- };
303
- #onClearButtonBlur = e => {
304
- if (e.relatedTarget !== this.#$input) {
305
- this.#$clear.removeAttribute('data-focus');
306
- }
307
- };
308
- #onClearButtonTooltipShow = () => {
309
- this.#$clear.setAttribute('data-tooltip', '');
310
- };
311
- #onClearButtonTooltipHide = () => {
312
- this.#$input.focus();
313
- this.#$clear.removeAttribute('data-tooltip');
314
- };
315
279
  #onChangeReactHandler = e => {
316
280
  getReactEventHandler(this, 'on-change')?.(e);
317
281
  };
package/input/types.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import type { TRect, TSinchElementReact } from '../types';
1
+ import type { TSinchElementReact } from '../types';
2
2
  import type { TSinchSize } from '../utils/size';
3
- import type { SyntheticEvent } from 'react';
4
3
  export type TSinchInputType = 'text' | 'password';
5
4
  export type TSinchInputElement = HTMLElement & {
6
5
  /** Text field type, `text` by default */
@@ -20,7 +19,6 @@ export type TSinchInputElement = HTMLElement & {
20
19
  selectionStart: number | null;
21
20
  selectionEnd: number | null;
22
21
  selectionDirection: 'forward' | 'backward' | 'none' | null;
23
- readonly clearButtonRect: TRect;
24
22
  /** Change value event */
25
23
  addEventListener(type: '-change', listener: (e: CustomEvent<string>) => void): void;
26
24
  /** Focus event */
@@ -59,8 +57,6 @@ export type TSinchInputReact = TSinchElementReact<TSinchInputElement> & {
59
57
  disabled?: boolean;
60
58
  /** Size, `m` by default */
61
59
  size?: TSinchSize;
62
- /** @deprecated Change value handler */
63
- onChange?: (e: SyntheticEvent<TSinchInputElement, CustomEvent<string>>) => void;
64
60
  /** Change value handler */
65
61
  'on-change'?: (e: CustomEvent<string>) => void;
66
62
  /** Focus handler */
package/input/utils.d.ts CHANGED
@@ -1,5 +1,2 @@
1
1
  import type { TSinchInputType } from './types';
2
2
  export declare const inputTypes: readonly TSinchInputType[];
3
- type TAssertType = (value: string | null) => asserts value is TSinchInputType | null;
4
- export declare const assertType: TAssertType;
5
- export {};
package/input/utils.js CHANGED
@@ -1,6 +1 @@
1
- export const inputTypes = ['text', 'password'];
2
- export const assertType = value => {
3
- if (value !== null && !inputTypes.includes(value)) {
4
- throw new Error(`sinch-input: invalid type attribute: ${value}`);
5
- }
6
- };
1
+ export const inputTypes = ['text', 'password'];
package/link/index.js CHANGED
@@ -1,21 +1,17 @@
1
1
  import '../icon';
2
- import { defineCustomElement, getBooleanAttribute, getAttribute, updateBooleanAttribute, updateAttribute, NectaryElement, isAttrTrue, getReactEventHandler, getCssVars } from '../utils';
3
- const templateHTML = '<style>:host{display:inline}a{font:var(--sinch-font-text-m);font-size:inherit;line-height:inherit;color:var(--sinch-color-tropical-500);border-radius:.5em;white-space:nowrap;--sinch-size-icon:1em;--sinch-color-icon:var(--sinch-color-tropical-500)}a:hover{color:var(--sinch-color-tropical-600);--sinch-color-icon:var(--sinch-color-tropical-600)}a:focus-visible{outline:2px solid var(--sinch-color-border-focus);outline-offset:2px}#external-icon{display:none;margin-right:.2em;vertical-align:-.2em}#standalone-icon,#standalone-icon-prefix{display:none}:host([external]:not([external=false])) #external-icon{display:inline-block}:host([standalone]:not([standalone=false])){display:block}:host([standalone]:not([standalone=false])) a{display:block;font:var(--sinch-font-text-m);font-weight:var(--sinch-font-weight-emphasized);text-decoration:none;border-radius:var(--sinch-shape-radius-m);width:fit-content;--sinch-size-icon:24px}:host([standalone]:not([standalone=false])) #external-icon{margin-right:8px;vertical-align:-7px}:host([standalone]:not([standalone=false])) #standalone-icon-prefix{display:inline}:host([standalone]:not([standalone=false]):is([external=false],:not([external]))) #standalone-icon{display:inline-block;vertical-align:-7px}:host([disabled]:not([disabled=false])) a{color:var(--sinch-color-tropical-200);pointer-events:none;cursor:initial;--sinch-color-icon:var(--sinch-color-tropical-200)}#content{white-space:var(--sinch-text-white-space,normal)}</style><a referrerpolicy="no-referer" aria-hidden="true"><sinch-icon id="external-icon"></sinch-icon><span id="content"></span><span id="standalone-icon-prefix">&nbsp;</span><sinch-icon id="standalone-icon"></sinch-icon></a>';
2
+ import { defineCustomElement, getBooleanAttribute, getAttribute, updateBooleanAttribute, updateAttribute, NectaryElement, isAttrTrue, getReactEventHandler } from '../utils';
3
+ const templateHTML = '<style>:host{display:inline}a{font:var(--sinch-comp-link-default-font-initial);font-size:inherit;line-height:inherit;text-decoration:var(--sinch-comp-link-default-text-decoration-initial);color:var(--sinch-comp-link-color-default-text-initial);border-radius:.5em;white-space:nowrap;--sinch-global-color-icon:var(--sinch-comp-link-color-default-icon-initial)}a:hover{text-decoration:var(--sinch-comp-link-default-text-decoration-hover);color:var(--sinch-comp-link-color-default-text-hover);--sinch-global-color-icon:var(--sinch-comp-link-color-default-icon-hover)}a:focus-visible{outline:2px solid var(--sinch-comp-link-color-default-outline-focus);outline-offset:2px}:host([standalone]){display:block}:host([standalone]) a{display:block;font:var(--sinch-comp-link-standalone-font-initial);font-size:inherit;line-height:inherit;text-decoration:none;width:fit-content}#external-icon,#standalone-icon{display:none;height:1em}#standalone-icon-prefix{display:none}:host([external]:not([standalone])) #external-icon{display:inline-block;margin-right:.2em;vertical-align:-.2em;--sinch-global-size-icon:1em}:host([standalone][external]) #external-icon{display:inline-block;vertical-align:-.4em;margin-right:-.4em;--sinch-global-size-icon:1.5em}:host([standalone]) #standalone-icon-prefix{display:inline}:host([standalone]:not([external])) #standalone-icon{display:inline-block;vertical-align:-.4em;--sinch-global-size-icon:1.5em}:host([disabled]) a{color:var(--sinch-comp-link-color-disabled-text-initial);pointer-events:none;cursor:initial;text-decoration:var(--sinch-comp-link-default-text-decoration-disabled);--sinch-global-color-icon:var(--sinch-comp-link-color-disabled-icon-initial)}#content{white-space:var(--sinch-global-text-white-space,normal)}</style><a referrerpolicy="no-referer" aria-hidden="true"><sinch-icon id="external-icon" name="open_in_new"></sinch-icon><span id="content"></span><span id="standalone-icon-prefix">&nbsp;</span><sinch-icon id="standalone-icon" name="arrow_forward"></sinch-icon></a>';
4
4
  const template = document.createElement('template');
5
5
  template.innerHTML = templateHTML;
6
6
  defineCustomElement('sinch-link', class extends NectaryElement {
7
7
  #$anchor;
8
8
  #$text;
9
- #$iconStandalone;
10
- #$iconExternal;
11
9
  constructor() {
12
10
  super();
13
11
  const shadowRoot = this.attachShadow();
14
12
  shadowRoot.appendChild(template.content.cloneNode(true));
15
13
  this.#$anchor = shadowRoot.querySelector('a');
16
14
  this.#$text = shadowRoot.querySelector('#content');
17
- this.#$iconExternal = shadowRoot.querySelector('#external-icon');
18
- this.#$iconStandalone = shadowRoot.querySelector('#standalone-icon');
19
15
  }
20
16
  connectedCallback() {
21
17
  this.setAttribute('role', 'link');
@@ -25,7 +21,6 @@ defineCustomElement('sinch-link', class extends NectaryElement {
25
21
  this.addEventListener('-click', this.#onClickReactHandler);
26
22
  this.addEventListener('-focus', this.#onFocusReactHandler);
27
23
  this.addEventListener('-blur', this.#onBlurReactHandler);
28
- this.#updateIcons();
29
24
  }
30
25
  disconnectedCallback() {
31
26
  this.#$anchor.removeEventListener('click', this.#onAnchorClick);
@@ -35,6 +30,39 @@ defineCustomElement('sinch-link', class extends NectaryElement {
35
30
  this.removeEventListener('-focus', this.#onFocusReactHandler);
36
31
  this.removeEventListener('-blur', this.#onBlurReactHandler);
37
32
  }
33
+ static get observedAttributes() {
34
+ return ['text', 'href', 'external', 'standalone', 'disabled'];
35
+ }
36
+ attributeChangedCallback(name, oldVal, newVal) {
37
+ if (oldVal === newVal) {
38
+ return;
39
+ }
40
+ switch (name) {
41
+ case 'text':
42
+ {
43
+ this.#$text.textContent = newVal;
44
+ break;
45
+ }
46
+ case 'href':
47
+ {
48
+ updateAttribute(this.#$anchor, 'href', newVal);
49
+ break;
50
+ }
51
+ case 'standalone':
52
+ case 'disabled':
53
+ {
54
+ updateBooleanAttribute(this, name, isAttrTrue(newVal));
55
+ break;
56
+ }
57
+ case 'external':
58
+ {
59
+ const isExternal = isAttrTrue(newVal);
60
+ updateAttribute(this.#$anchor, 'target', isExternal ? '_blank' : null);
61
+ updateBooleanAttribute(this, name, isExternal);
62
+ break;
63
+ }
64
+ }
65
+ }
38
66
  get text() {
39
67
  return getAttribute(this, 'text', '');
40
68
  }
@@ -71,31 +99,6 @@ defineCustomElement('sinch-link', class extends NectaryElement {
71
99
  get preventDefault() {
72
100
  return getBooleanAttribute(this, 'preventdefault');
73
101
  }
74
- static get observedAttributes() {
75
- return ['text', 'href', 'external'];
76
- }
77
- attributeChangedCallback(name, oldVal, newVal) {
78
- if (oldVal === newVal) {
79
- return;
80
- }
81
- switch (name) {
82
- case 'text':
83
- {
84
- this.#$text.textContent = newVal;
85
- break;
86
- }
87
- case 'href':
88
- {
89
- updateAttribute(this.#$anchor, 'href', newVal);
90
- break;
91
- }
92
- case 'external':
93
- {
94
- updateAttribute(this.#$anchor, 'target', isAttrTrue(newVal) ? '_blank' : null);
95
- break;
96
- }
97
- }
98
- }
99
102
  get focusable() {
100
103
  return true;
101
104
  }
@@ -105,11 +108,6 @@ defineCustomElement('sinch-link', class extends NectaryElement {
105
108
  blur() {
106
109
  this.#$anchor.blur();
107
110
  }
108
- #updateIcons() {
109
- const [externalName, standaloneName] = getCssVars(this, ['--sinch-link-icon-external', '--sinch-link-icon-standalone']);
110
- updateAttribute(this.#$iconExternal, 'name', externalName);
111
- updateAttribute(this.#$iconStandalone, 'name', standaloneName);
112
- }
113
111
  #onAnchorClick = e => {
114
112
  if (this.preventDefault) {
115
113
  e.preventDefault();
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement, NectaryElement } from '../utils';
2
- const templateHTML = '<style>:host{display:block;outline:0}#wrapper{width:100%;height:100%;box-sizing:border-box;overflow:hidden;padding:8px 0;border-bottom:1px solid var(--sinch-color-snow-500)}:host(:last-child)>#wrapper{border-bottom:none}:host(:hover)>#wrapper{background-color:var(--sinch-color-snow-400)}</style><div id="wrapper"><slot name="content"></slot></div>';
2
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{width:100%;height:100%;box-sizing:border-box;overflow:hidden;padding:8px 0;background-color:var(--sinch-comp-list-color-default-background-initial);border-bottom:1px solid var(--sinch-comp-list-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}:host(:hover)>#wrapper{background-color:var(--sinch-comp-list-color-default-background-hover)}</style><div id="wrapper"><slot name="content"></slot></div>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-list-item', class extends NectaryElement {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "1.4.0",
3
+ "version": "2.1.0",
4
4
  "files": [
5
5
  "**/*/*.css",
6
6
  "**/*/*.json",
@@ -13,18 +13,18 @@
13
13
  "build": "NODE_ENV=production babel . --extensions '.ts' --out-dir . && tsc --declaration --emitDeclarationOnly"
14
14
  },
15
15
  "dependencies": {
16
- "@babel/runtime": "^7.20.13",
16
+ "@babel/runtime": "^7.21.0",
17
17
  "xss": "^1.0.14"
18
18
  },
19
19
  "devDependencies": {
20
- "@babel/cli": "^7.20.7",
21
- "@babel/core": "^7.20.12",
22
- "@babel/plugin-transform-runtime": "^7.19.6",
23
- "@babel/preset-env": "^7.20.2",
24
- "@babel/preset-typescript": "^7.18.6",
25
- "@types/react": "^18.0.27",
26
- "babel-plugin-html-inline-minifier": "workspace:^0.0.0",
27
- "babel-plugin-transform-inline-environment-variables": "^0.4.4",
28
- "typescript": "^4.9.5"
20
+ "@babel/cli": "^7.21.0",
21
+ "@babel/core": "^7.21.4",
22
+ "@babel/plugin-transform-runtime": "^7.21.4",
23
+ "@babel/preset-env": "^7.21.4",
24
+ "@babel/preset-typescript": "^7.21.4",
25
+ "@types/node": "^18.16.0",
26
+ "@types/react": "^18.0.38",
27
+ "babel-plugin-html-inline-minifier": "workspace:*",
28
+ "typescript": "^5.0.4"
29
29
  }
30
30
  }
@@ -1,6 +1,6 @@
1
1
  import '../icon';
2
- import { defineCustomElement, updateAttribute, getIntegerAttribute, setClass, NectaryElement, getRect, getReactEventHandler, getCssVars, isTargetEqual, getTargetIndexInParent } from '../utils';
3
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{display:flex;justify-content:center;gap:8px;width:100%;box-sizing:border-box}button{all:initial;width:28px;height:28px;box-sizing:border-box;cursor:pointer;text-align:center;contain:strict;--sinch-color-icon:var(--sinch-color-stormy-500)}button:disabled{--sinch-color-icon:var(--sinch-color-stormy-100);cursor:initial}button>*{pointer-events:none}.page{border-radius:50%;font:var(--sinch-font-text-m);color:var(--sinch-color-stormy-500)}.page.dots>span{display:none}.page.dots::after{content:"..."}.page.active{font-weight:var(--sinch-font-weight-emphasized);background-color:var(--sinch-color-snow-600);pointer-events:none;cursor:initial}.page.hidden{display:none}#left,#right{display:flex;padding:2px;--sinch-icon-size:24px}</style><div id="wrapper"><button id="left"><sinch-icon id="icon-left"></sinch-icon></button><button class="page"><span>1</span></button><button class="page active"><span>2</span></button><button class="page"><span>3</span></button><button class="page"><span>4</span></button><button class="page"><span>5</span></button><button class="page dots"><span>6</span></button><button class="page"><span>20</span></button><button id="right"><sinch-icon id="icon-right"></sinch-icon></button></div>';
2
+ import { defineCustomElement, updateAttribute, getIntegerAttribute, setClass, NectaryElement, getRect, getReactEventHandler, isTargetEqual, getTargetIndexInParent } from '../utils';
3
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{display:flex;justify-content:center;gap:8px;width:100%;height:var(--sinch-local-size);--sinch-local-size:24px}button{all:initial;position:relative;display:flex;justify-content:center;align-items:center;width:var(--sinch-local-size);height:var(--sinch-local-size);cursor:pointer;border-radius:var(--sinch-comp-pagination-shape-radius);--sinch-global-color-icon:var(--sinch-comp-pagination-color-default-icon-default)}button:focus-visible::before{content:"";position:absolute;inset:-4px;border:2px solid var(--sinch-comp-pagination-color-default-outline-focus);border-radius:calc(var(--sinch-comp-pagination-shape-radius) + 4px);pointer-events:none}button:disabled{--sinch-global-color-icon:var(--sinch-comp-pagination-color-disabled-icon-initial);cursor:initial}button:enabled:hover{background-color:var(--sinch-comp-pagination-color-default-background-hover)}button>*{display:block;overflow:hidden;pointer-events:none}.page{font:var(--sinch-comp-pagination-font-default-page-number);color:var(--sinch-comp-pagination-color-default-text-initial);background-color:var(--sinch-comp-pagination-color-default-background-initial)}.page.dots>span{display:none}.page.dots::after{content:"..."}.page.active{font:var(--sinch-comp-pagination-font-checked-page-number);background-color:var(--sinch-comp-pagination-color-checked-background-initial);pointer-events:none;cursor:initial}.page.active:hover{background-color:var(--sinch-comp-pagination-color-checked-background-hover)}.page.hidden{display:none}#left,#right{--sinch-icon-size:24px}</style><div id="wrapper"><button id="left"><sinch-icon id="icon-left" name="keyboard_arrow_left"></sinch-icon></button><button class="page"><span>1</span></button><button class="page active"><span>2</span></button><button class="page"><span>3</span></button><button class="page"><span>4</span></button><button class="page"><span>5</span></button><button class="page dots"><span>6</span></button><button class="page"><span>20</span></button><button id="right"><sinch-icon id="icon-right" name="keyboard_arrow_right"></sinch-icon></button></div>';
4
4
  const NUM_BUTTONS = 7;
5
5
  const MIDDLE_BTN_INDEX = Math.floor(NUM_BUTTONS / 2);
6
6
  const FIRST_BTN_INDEX = 0;
@@ -11,9 +11,7 @@ const template = document.createElement('template');
11
11
  template.innerHTML = templateHTML;
12
12
  defineCustomElement('sinch-pagination', class extends NectaryElement {
13
13
  #$left;
14
- #$iconLeft;
15
14
  #$right;
16
- #$iconRight;
17
15
  #$buttons;
18
16
  #$wrapper;
19
17
  constructor() {
@@ -21,9 +19,7 @@ defineCustomElement('sinch-pagination', class extends NectaryElement {
21
19
  const shadowRoot = this.attachShadow();
22
20
  shadowRoot.appendChild(template.content.cloneNode(true));
23
21
  this.#$left = shadowRoot.querySelector('#left');
24
- this.#$iconLeft = shadowRoot.querySelector('#icon-left');
25
22
  this.#$right = shadowRoot.querySelector('#right');
26
- this.#$iconRight = shadowRoot.querySelector('#icon-right');
27
23
  this.#$buttons = shadowRoot.querySelectorAll('.page');
28
24
  this.#$wrapper = shadowRoot.querySelector('#wrapper');
29
25
  }
@@ -31,7 +27,6 @@ defineCustomElement('sinch-pagination', class extends NectaryElement {
31
27
  this.#onValueChange();
32
28
  this.#$wrapper.addEventListener('click', this.#onButtonClick);
33
29
  this.addEventListener('-change', this.#onChangeReactHandler);
34
- this.#updateIcons();
35
30
  }
36
31
  disconnectedCallback() {
37
32
  this.#$wrapper.removeEventListener('click', this.#onButtonClick);
@@ -54,9 +49,6 @@ defineCustomElement('sinch-pagination', class extends NectaryElement {
54
49
  }
55
50
  }
56
51
  }
57
- get nodeName() {
58
- return 'select';
59
- }
60
52
  set value(val) {
61
53
  updateAttribute(this, 'value', val);
62
54
  }
@@ -97,21 +89,21 @@ defineCustomElement('sinch-pagination', class extends NectaryElement {
97
89
  }
98
90
  #onButtonClick = e => {
99
91
  e.stopPropagation();
100
- const value = getIntegerAttribute(this, 'value', 0) - 1;
92
+ const value = Math.max(getIntegerAttribute(this, 'value', 0) - 1);
101
93
  const max = Math.max(0, getIntegerAttribute(this, 'max', 0));
102
94
  if (isTargetEqual(e, this.#$left)) {
103
- return this.#dispatchChangeEvent(value - 1);
95
+ return this.#dispatchChangeEvent(Math.max(value - 1, 0));
104
96
  }
105
97
  if (isTargetEqual(e, this.#$right)) {
106
- return this.#dispatchChangeEvent(value + 1);
98
+ return this.#dispatchChangeEvent(Math.min(value + 1, max));
107
99
  }
108
100
  const btnIndex = getTargetIndexInParent(e, this.#$wrapper) - 1;
109
- if (btnIndex >= 0 && btnIndex < this.#$buttons.length) {
101
+ if (btnIndex >= FIRST_BTN_INDEX && btnIndex <= LAST_BTN_INDEX) {
110
102
  if (btnIndex === FIRST_BTN_INDEX) {
111
103
  return this.#dispatchChangeEvent(0);
112
104
  }
113
- if (btnIndex === this.#$buttons.length - 1) {
114
- return this.#dispatchChangeEvent(max - 1);
105
+ if (btnIndex === LAST_BTN_INDEX) {
106
+ return this.#dispatchChangeEvent(max);
115
107
  }
116
108
  if (btnIndex === DOTS_LEFT_INDEX && max > NUM_BUTTONS && value > MIDDLE_BTN_INDEX) {
117
109
  return this.#dispatchChangeEvent(Math.floor(value / 2));
@@ -126,11 +118,6 @@ defineCustomElement('sinch-pagination', class extends NectaryElement {
126
118
  const max = getIntegerAttribute(this, 'max', 0);
127
119
  return Math.max(0, Math.min(max - 1, value)) + 1;
128
120
  }
129
- #updateIcons() {
130
- const [leftName, rightName] = getCssVars(this, ['--sinch-pagination-icon-prev', '--sinch-pagination-icon-next']);
131
- updateAttribute(this.#$iconLeft, 'name', leftName);
132
- updateAttribute(this.#$iconRight, 'name', rightName);
133
- }
134
121
  #dispatchChangeEvent(value) {
135
122
  const detail = this.#clamp(value);
136
123
  this.dispatchEvent(new CustomEvent('change', {
@@ -1,5 +1,4 @@
1
1
  import type { TRect, TSinchElementReact } from '../types';
2
- import type { SyntheticEvent } from 'react';
3
2
  export type TSinchPaginationElement = HTMLElement & {
4
3
  value: number;
5
4
  max: number;
@@ -14,7 +13,5 @@ export type TSinchPaginationElement = HTMLElement & {
14
13
  export type TSinchPaginationReact = TSinchElementReact<TSinchPaginationElement> & {
15
14
  value: number;
16
15
  max: number;
17
- /** @deprecated */
18
- onChange?: (event: SyntheticEvent<TSinchPaginationElement, CustomEvent<number>>) => void;
19
16
  'on-change': (e: CustomEvent<number>) => void;
20
17
  };