@nectary/components 0.20.0 → 0.22.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.
@@ -0,0 +1,13 @@
1
+ import type { TSinchElementReact } from '../types';
2
+ export declare type TSinchCardContainerElement = HTMLElement & {};
3
+ export declare type TSinchCardContainerReact = TSinchElementReact<TSinchCardContainerElement> & {};
4
+ declare global {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ 'sinch-card-container': TSinchCardContainerReact;
8
+ }
9
+ }
10
+ interface HTMLElementTagNameMap {
11
+ 'sinch-card-container': TSinchCardContainerElement;
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ import { defineCustomElement } from '../utils';
2
+ const templateHTML = '<style>:host{display:block}#wrapper{position:relative;padding:24px;box-sizing:border-box;background-color:var(--sinch-color-snow-100);border-radius:8px;border:1px solid var(--sinch-color-snow-700)}</style><div id="wrapper"><slot></slot></div>';
3
+ const template = document.createElement('template');
4
+ template.innerHTML = templateHTML;
5
+ defineCustomElement('sinch-card-container', class extends HTMLElement {
6
+ constructor() {
7
+ super();
8
+ const shadowRoot = this.attachShadow({
9
+ mode: 'closed',
10
+ delegatesFocus: true
11
+ });
12
+ shadowRoot.appendChild(template.content.cloneNode(true));
13
+ }
14
+
15
+ });
package/dialog/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
2
2
  import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
3
3
 
4
- var _$dialog, _$closeButton, _$caption, _isConected, _onCancel, _onCloseClick, _onBackdropClick, _onCloseReactHandler, _dispatchCloseEvent, _setOpen;
4
+ var _$dialog, _$closeButton, _$caption, _isConnected, _onCancel, _onCloseClick, _onBackdropClick, _onCloseReactHandler, _dispatchCloseEvent, _setOpen;
5
5
 
6
6
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
7
 
@@ -12,24 +12,13 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
12
12
  function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
13
13
 
14
14
  import dialogPolyfill from 'dialog-polyfill';
15
- import { defineCustomElement, getAttribute, getBooleanAttribute, getRect, isAttrTrue, updateAttribute } from '../utils';
15
+ import { defineCustomElement, getAttribute, getBooleanAttribute, getRect, isAttrTrue, updateAttribute, getReactEventHandler } from '../utils';
16
16
  import '../icon-button';
17
17
  import '../icon/close';
18
- const templateHTML = '<style>dialog{position:absolute;left:0;right:0;margin:auto;display:flex;flex-direction:column;padding:24px;width:100%;max-width:512px;border-radius:4px;box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);border:none;box-shadow:1px 2px 8px rgb(0 0 0 / 10%)}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000;opacity:.55}dialog::backdrop{background-color:#000;opacity:.55}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translate(0,-50%)}#header{display:flex;flex-direction:row;justify-content:space-between;align-content:center;margin-bottom:16px}#caption{font:var(--sinch-font-title-m);color:var(--sinch-color-text-default)}#content-wrapper{max-height:50vh;overflow-y:auto}#close{all:initial;cursor:pointer;--sinch-size-icon:24px}#buttons{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;margin-top:24px}</style><dialog><div id="header"><span id="caption"></span> <button id="close"><sinch-icon-close></sinch-icon-close></button></div><div id="content-wrapper"><slot name="content"></slot></div><div id="buttons"><slot name="buttons"></slot></div></dialog>';
18
+ const templateHTML = '<style>dialog{position:absolute;left:0;right:0;margin:auto;display:flex;flex-direction:column;padding:24px;width:100%;max-width:512px;border-radius:4px;box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);border:none;box-shadow:1px 2px 8px rgba(0,0,0,.1)}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000;opacity:.55}dialog::backdrop{background-color:#000;opacity:.55}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translate(0,-50%)}#header{display:flex;flex-direction:row;justify-content:space-between;align-content:center;margin-bottom:16px}#caption{font:var(--sinch-font-title-m);color:var(--sinch-color-text-default)}#content-wrapper{max-height:50vh;overflow-y:auto}#close{all:initial;cursor:pointer;--sinch-size-icon:24px}#buttons{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;margin-top:24px}</style><dialog><div id="header"><span id="caption"></span> <button id="close"><sinch-icon-close></sinch-icon-close></button></div><div id="content-wrapper"><slot name="content"></slot></div><div id="buttons"><slot name="buttons"></slot></div></dialog>';
19
19
  const template = document.createElement('template');
20
20
  template.innerHTML = templateHTML;
21
-
22
- const getReactEventHandler = ($element, handlerName) => {
23
- for (const key in $element) {
24
- if (key.startsWith('__reactProps$')) {
25
- return $element[key][handlerName];
26
- }
27
- }
28
-
29
- return null;
30
- };
31
-
32
- defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = new WeakMap(), _$caption = new WeakMap(), _isConected = new WeakMap(), _onCancel = new WeakMap(), _onCloseClick = new WeakMap(), _onBackdropClick = new WeakMap(), _onCloseReactHandler = new WeakMap(), _dispatchCloseEvent = new WeakSet(), _setOpen = new WeakSet(), class extends HTMLElement {
21
+ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = new WeakMap(), _$caption = new WeakMap(), _isConnected = new WeakMap(), _onCancel = new WeakMap(), _onCloseClick = new WeakMap(), _onBackdropClick = new WeakMap(), _onCloseReactHandler = new WeakMap(), _dispatchCloseEvent = new WeakSet(), _setOpen = new WeakSet(), class extends HTMLElement {
33
22
  constructor() {
34
23
  super();
35
24
 
@@ -52,7 +41,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
52
41
  value: void 0
53
42
  });
54
43
 
55
- _classPrivateFieldInitSpec(this, _isConected, {
44
+ _classPrivateFieldInitSpec(this, _isConnected, {
56
45
  writable: true,
57
46
  value: false
58
47
  });
@@ -123,7 +112,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
123
112
 
124
113
  case 'open':
125
114
  {
126
- if (_classPrivateFieldGet(this, _isConected)) {
115
+ if (_classPrivateFieldGet(this, _isConnected)) {
127
116
  _classPrivateMethodGet(this, _setOpen, _setOpen2).call(this, isAttrTrue(newVal));
128
117
  }
129
118
 
@@ -150,7 +139,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
150
139
 
151
140
  _classPrivateFieldGet(this, _$dialog).addEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
152
141
 
153
- _classPrivateFieldSet(this, _isConected, true);
142
+ _classPrivateFieldSet(this, _isConnected, true);
154
143
 
155
144
  if (getBooleanAttribute(this, 'open')) {
156
145
  _classPrivateMethodGet(this, _setOpen, _setOpen2).call(this, true);
@@ -165,7 +154,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
165
154
 
166
155
  _classPrivateFieldGet(this, _$dialog).removeEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
167
156
 
168
- _classPrivateFieldSet(this, _isConected, false);
157
+ _classPrivateFieldSet(this, _isConnected, false);
169
158
  }
170
159
 
171
160
  get dialogRect() {
@@ -190,6 +179,6 @@ function _setOpen2(isOpen) {
190
179
  _classPrivateFieldGet(this, _$dialog).showModal();
191
180
  }
192
181
  } else {
193
- _classPrivateFieldGet(this, _$dialog).close();
182
+ _classPrivateFieldGet(this, _$dialog).close?.();
194
183
  }
195
184
  }
@@ -3,20 +3,21 @@ import type { FocusEvent, SyntheticEvent } from 'react';
3
3
  declare const orientationValues: readonly ["top-left", "top-right", "bottom-left", "bottom-right"];
4
4
  export declare type TSinchDropdownOrientation = typeof orientationValues[number];
5
5
  export declare type TSinchDropdownElement = HTMLElement & {
6
+ open: boolean;
6
7
  orientation: TSinchDropdownOrientation;
7
8
  value: string;
8
- disabled: boolean;
9
9
  maxVisibleItems: number | null;
10
10
  readonly dropdownRect: TRect;
11
11
  focus(): void;
12
12
  blur(): void;
13
13
  };
14
14
  export declare type TSinchDropdownReact = TSinchElementReact<TSinchDropdownElement> & {
15
+ open: boolean;
15
16
  orientation?: TSinchDropdownOrientation;
16
17
  value: string;
17
- disabled?: boolean;
18
18
  maxVisibleItems?: number;
19
19
  'aria-label': string;
20
+ onClose: (event: SyntheticEvent<TSinchDropdownElement, CustomEvent<void>>) => void;
20
21
  onChange: (e: SyntheticEvent<TSinchDropdownElement, CustomEvent<string>>) => void;
21
22
  onFocus?: (e: FocusEvent<TSinchDropdownElement>) => void;
22
23
  onBlur?: (e: FocusEvent<TSinchDropdownElement>) => void;
package/dropdown/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
2
2
  import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
3
3
 
4
- var _$button, _$optionSlot, _$listbox, _onButtonClick, _onListboxClick, _onListboxKeyPress, _onListboxKeyDown, _onOptionSlotChange, _setOpen, _onExpand, _onCollapse, _onValueChange, _getFirstOption, _getLastOption, _getNextOption, _getPrevOption, _selectOption, _getOptionWithValue, _getOptionElements, _getEnabledOptionElements, _dispatchChangeEvent;
4
+ var _$target, _$optionSlot, _$listbox, _isConnected, _onListboxClick, _onListboxKeyPress, _onListboxKeyDown, _onOptionSlotChange, _onExpand, _onCollapse, _isOpen, _updateOrientation, _onValueChange, _getFirstOption, _getLastOption, _getNextOption, _getPrevOption, _selectOption, _getOptionWithValue, _getOptionElements, _getEnabledOptionElements, _dispatchChangeEvent, _dispatchCloseEvent, _onCancel, _onCloseReactHandler;
5
5
 
6
6
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
7
 
@@ -11,9 +11,10 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
11
11
 
12
12
  function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
13
13
 
14
+ import dialogPolyfill from 'dialog-polyfill';
14
15
  import { isDropdownOptionElement } from '../dropdown-option';
15
- import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getLiteralAttribute, getRect, updateAttribute, updateBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from '../utils';
16
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative;width:100%;box-sizing:border-box}dialog{outline:0;border:none;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:1px 2px 4px rgb(0 0 0 / 15%);overflow-y:auto;contain:content;padding:0;border-radius:4px;cursor:pointer}dialog::backdrop{background-color:transparent}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:transparent}dialog.fixed{position:fixed;top:50%;transform:translate(0,-50%)}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}::slotted(*){display:block}</style><div id="wrapper"><div id="button" aria-haspopup="listbox" aria-expanded="false"><slot name="target"></slot></div><dialog id="listbox" tabindex="-1"><slot name="option"></slot></dialog></div>';
16
+ import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getLiteralAttribute, getReactEventHandler, getRect, isAttrTrue, updateAttribute, updateBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from '../utils';
17
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative;width:100%;box-sizing:border-box}dialog{outline:0;border:none;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:1px 2px 4px rgba(0,0,0,.15);overflow-y:auto;contain:content;padding:0;border-radius:4px;cursor:pointer}dialog::backdrop{background-color:transparent}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:transparent}dialog.fixed{position:fixed;top:50%;transform:translate(0,-50%)}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}::slotted(*){display:block}</style><div id="wrapper"><div id="target" aria-haspopup="listbox" aria-expanded="false"><slot name="target"></slot></div><dialog id="listbox" tabindex="-1"><slot name="option"></slot></dialog></div>';
17
18
  const orientationValues = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
18
19
  const ITEM_HEIGHT = 40;
19
20
 
@@ -29,10 +30,12 @@ const findSelectedOption = elements => {
29
30
 
30
31
  const template = document.createElement('template');
31
32
  template.innerHTML = templateHTML;
32
- defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot = new WeakMap(), _$listbox = new WeakMap(), _onButtonClick = new WeakMap(), _onListboxClick = new WeakMap(), _onListboxKeyPress = new WeakMap(), _onListboxKeyDown = new WeakMap(), _onOptionSlotChange = new WeakMap(), _setOpen = new WeakSet(), _onExpand = new WeakSet(), _onCollapse = new WeakSet(), _onValueChange = new WeakSet(), _getFirstOption = new WeakSet(), _getLastOption = new WeakSet(), _getNextOption = new WeakSet(), _getPrevOption = new WeakSet(), _selectOption = new WeakSet(), _getOptionWithValue = new WeakSet(), _getOptionElements = new WeakSet(), _getEnabledOptionElements = new WeakSet(), _dispatchChangeEvent = new WeakSet(), class extends HTMLElement {
33
+ defineCustomElement('sinch-dropdown', (_$target = new WeakMap(), _$optionSlot = new WeakMap(), _$listbox = new WeakMap(), _isConnected = new WeakMap(), _onListboxClick = new WeakMap(), _onListboxKeyPress = new WeakMap(), _onListboxKeyDown = new WeakMap(), _onOptionSlotChange = new WeakMap(), _onExpand = new WeakSet(), _onCollapse = new WeakSet(), _isOpen = new WeakSet(), _updateOrientation = new WeakSet(), _onValueChange = new WeakSet(), _getFirstOption = new WeakSet(), _getLastOption = new WeakSet(), _getNextOption = new WeakSet(), _getPrevOption = new WeakSet(), _selectOption = new WeakSet(), _getOptionWithValue = new WeakSet(), _getOptionElements = new WeakSet(), _getEnabledOptionElements = new WeakSet(), _dispatchChangeEvent = new WeakSet(), _dispatchCloseEvent = new WeakSet(), _onCancel = new WeakMap(), _onCloseReactHandler = new WeakMap(), class extends HTMLElement {
33
34
  constructor() {
34
35
  super();
35
36
 
37
+ _classPrivateMethodInitSpec(this, _dispatchCloseEvent);
38
+
36
39
  _classPrivateMethodInitSpec(this, _dispatchChangeEvent);
37
40
 
38
41
  _classPrivateMethodInitSpec(this, _getEnabledOptionElements);
@@ -53,13 +56,15 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
53
56
 
54
57
  _classPrivateMethodInitSpec(this, _onValueChange);
55
58
 
59
+ _classPrivateMethodInitSpec(this, _updateOrientation);
60
+
61
+ _classPrivateMethodInitSpec(this, _isOpen);
62
+
56
63
  _classPrivateMethodInitSpec(this, _onCollapse);
57
64
 
58
65
  _classPrivateMethodInitSpec(this, _onExpand);
59
66
 
60
- _classPrivateMethodInitSpec(this, _setOpen);
61
-
62
- _classPrivateFieldInitSpec(this, _$button, {
67
+ _classPrivateFieldInitSpec(this, _$target, {
63
68
  writable: true,
64
69
  value: void 0
65
70
  });
@@ -74,32 +79,30 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
74
79
  value: void 0
75
80
  });
76
81
 
77
- _classPrivateFieldInitSpec(this, _onButtonClick, {
82
+ _classPrivateFieldInitSpec(this, _isConnected, {
78
83
  writable: true,
79
- value: e => {
80
- e.stopPropagation();
81
-
82
- if (this.disabled) {
83
- return;
84
- }
85
-
86
- if (_classPrivateFieldGet(this, _$button).getAttribute('aria-expanded') !== 'true') {
87
- _classPrivateMethodGet(this, _onExpand, _onExpand2).call(this);
88
- }
89
- }
84
+ value: false
90
85
  });
91
86
 
92
87
  _classPrivateFieldInitSpec(this, _onListboxClick, {
93
88
  writable: true,
94
89
  value: e => {
95
- e.stopPropagation();
90
+ const rect = this.dropdownRect;
91
+ const isInside = e.x >= rect.x && e.x < rect.x + rect.width && e.y >= rect.y && e.y < rect.y + rect.height;
92
+
93
+ if (!isInside) {
94
+ _classPrivateMethodGet(this, _dispatchCloseEvent, _dispatchCloseEvent2).call(this);
95
+
96
+ return;
97
+ }
98
+
96
99
  const $elem = e.target;
97
100
 
98
- if ($elem !== _classPrivateFieldGet(this, _$listbox) && isDropdownOptionElement($elem) && $elem.disabled !== true) {
101
+ if ($elem !== _classPrivateFieldGet(this, _$listbox) && isDropdownOptionElement($elem)) {
102
+ e.stopPropagation();
103
+
99
104
  _classPrivateMethodGet(this, _dispatchChangeEvent, _dispatchChangeEvent2).call(this, $elem);
100
105
  }
101
-
102
- _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
103
106
  }
104
107
  });
105
108
 
@@ -114,8 +117,6 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
114
117
 
115
118
  _classPrivateMethodGet(this, _dispatchChangeEvent, _dispatchChangeEvent2).call(this, findSelectedOption(_classPrivateMethodGet(this, _getEnabledOptionElements, _getEnabledOptionElements2).call(this)));
116
119
 
117
- _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
118
-
119
120
  break;
120
121
  }
121
122
  }
@@ -143,15 +144,6 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
143
144
 
144
145
  _classPrivateMethodGet(this, _selectOption, _selectOption2).call(this, _classPrivateMethodGet(this, _getNextOption, _getNextOption2).call(this));
145
146
 
146
- break;
147
- }
148
-
149
- case 'Escape':
150
- {
151
- e.preventDefault();
152
-
153
- _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
154
-
155
147
  break;
156
148
  }
157
149
  }
@@ -161,29 +153,47 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
161
153
  _classPrivateFieldInitSpec(this, _onOptionSlotChange, {
162
154
  writable: true,
163
155
  value: () => {
164
- _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
165
-
166
156
  _classPrivateMethodGet(this, _onValueChange, _onValueChange2).call(this, this.value);
167
157
  }
168
158
  });
169
159
 
160
+ _classPrivateFieldInitSpec(this, _onCancel, {
161
+ writable: true,
162
+ value: e => {
163
+ e.preventDefault();
164
+
165
+ _classPrivateMethodGet(this, _dispatchCloseEvent, _dispatchCloseEvent2).call(this);
166
+ }
167
+ });
168
+
169
+ _classPrivateFieldInitSpec(this, _onCloseReactHandler, {
170
+ writable: true,
171
+ value: () => {
172
+ getReactEventHandler(this, 'onClose')?.();
173
+ }
174
+ });
175
+
170
176
  const shadowRoot = this.attachShadow({
171
177
  mode: 'closed',
172
178
  delegatesFocus: true
173
179
  });
174
180
  shadowRoot.appendChild(template.content.cloneNode(true));
175
181
 
176
- _classPrivateFieldSet(this, _$button, shadowRoot.querySelector('#button'));
182
+ _classPrivateFieldSet(this, _$target, shadowRoot.querySelector('#target'));
177
183
 
178
184
  _classPrivateFieldSet(this, _$listbox, shadowRoot.querySelector('#listbox'));
179
185
 
180
186
  _classPrivateFieldSet(this, _$optionSlot, shadowRoot.querySelector('slot[name="option"]'));
187
+
188
+ dialogPolyfill.registerDialog(_classPrivateFieldGet(this, _$listbox));
181
189
  }
182
190
 
183
191
  connectedCallback() {
192
+ _classPrivateFieldSet(this, _isConnected, true);
193
+
184
194
  this.setAttribute('role', 'listbox');
185
195
 
186
- _classPrivateFieldGet(this, _$button).addEventListener('click', _classPrivateFieldGet(this, _onButtonClick));
196
+ _classPrivateFieldGet(this, _$listbox).addEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
187
197
 
188
198
  _classPrivateFieldGet(this, _$listbox).addEventListener('click', _classPrivateFieldGet(this, _onListboxClick));
189
199
 
@@ -192,10 +202,20 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
192
202
  _classPrivateFieldGet(this, _$listbox).addEventListener('keypress', _classPrivateFieldGet(this, _onListboxKeyPress));
193
203
 
194
204
  _classPrivateFieldGet(this, _$optionSlot).addEventListener('slotchange', _classPrivateFieldGet(this, _onOptionSlotChange));
205
+
206
+ this.addEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
207
+
208
+ if (getBooleanAttribute(this, 'open')) {
209
+ _classPrivateMethodGet(this, _onExpand, _onExpand2).call(this);
210
+ } else {
211
+ _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
212
+ }
195
213
  }
196
214
 
197
215
  disconnectedCallback() {
198
- _classPrivateFieldGet(this, _$button).removeEventListener('click', _classPrivateFieldGet(this, _onButtonClick));
216
+ _classPrivateFieldSet(this, _isConnected, false);
217
+
218
+ _classPrivateFieldGet(this, _$listbox).removeEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
199
219
 
200
220
  _classPrivateFieldGet(this, _$listbox).removeEventListener('click', _classPrivateFieldGet(this, _onListboxClick));
201
221
 
@@ -204,10 +224,12 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
204
224
  _classPrivateFieldGet(this, _$listbox).removeEventListener('keypress', _classPrivateFieldGet(this, _onListboxKeyPress));
205
225
 
206
226
  _classPrivateFieldGet(this, _$optionSlot).removeEventListener('slotchange', _classPrivateFieldGet(this, _onOptionSlotChange));
227
+
228
+ this.removeEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
207
229
  }
208
230
 
209
231
  static get observedAttributes() {
210
- return ['value', 'maxvisibleitems'];
232
+ return ['value', 'maxvisibleitems', 'open', 'orientation'];
211
233
  }
212
234
 
213
235
  get nodeName() {
@@ -238,12 +260,12 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
238
260
  updateLiteralAttribute(this, orientationValues, 'orientation', value);
239
261
  }
240
262
 
241
- set disabled(isDisabled) {
242
- updateBooleanAttribute(this, 'disabled', isDisabled);
263
+ set open(isOpen) {
264
+ updateBooleanAttribute(this, 'open', isOpen);
243
265
  }
244
266
 
245
- get disabled() {
246
- return getBooleanAttribute(this, 'disabled');
267
+ get open() {
268
+ return getBooleanAttribute(this, 'open');
247
269
  }
248
270
 
249
271
  get dropdownRect() {
@@ -252,6 +274,28 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
252
274
 
253
275
  attributeChangedCallback(name, oldVal, newVal) {
254
276
  switch (name) {
277
+ case 'open':
278
+ {
279
+ if (_classPrivateFieldGet(this, _isConnected)) {
280
+ if (isAttrTrue(newVal)) {
281
+ _classPrivateMethodGet(this, _onExpand, _onExpand2).call(this);
282
+ } else {
283
+ _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
284
+ }
285
+ }
286
+
287
+ break;
288
+ }
289
+
290
+ case 'orientation':
291
+ {
292
+ if (_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
293
+ _classPrivateMethodGet(this, _updateOrientation, _updateOrientation2).call(this);
294
+ }
295
+
296
+ break;
297
+ }
298
+
255
299
  case 'value':
256
300
  {
257
301
  _classPrivateMethodGet(this, _onValueChange, _onValueChange2).call(this, newVal ?? '');
@@ -283,22 +327,35 @@ defineCustomElement('sinch-dropdown', (_$button = new WeakMap(), _$optionSlot =
283
327
 
284
328
  }));
285
329
 
286
- function _setOpen2(isOpen) {
287
- if (isOpen) {
288
- if (!getBooleanAttribute(_classPrivateFieldGet(this, _$listbox), 'open')) {
289
- _classPrivateFieldGet(this, _$listbox).showModal();
290
- }
291
- } else {
292
- _classPrivateFieldGet(this, _$listbox).close();
330
+ function _onExpand2() {
331
+ _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'true');
332
+
333
+ if (!_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
334
+ _classPrivateFieldGet(this, _$listbox).showModal();
293
335
  }
336
+
337
+ _classPrivateMethodGet(this, _updateOrientation, _updateOrientation2).call(this);
338
+
339
+ _classPrivateMethodGet(this, _selectOption, _selectOption2).call(this, _classPrivateMethodGet(this, _getOptionWithValue, _getOptionWithValue2).call(this, this.value) ?? _classPrivateMethodGet(this, _getFirstOption, _getFirstOption2).call(this));
294
340
  }
295
341
 
296
- function _onExpand2() {
297
- _classPrivateFieldGet(this, _$button).setAttribute('aria-expanded', 'true');
342
+ function _onCollapse2() {
343
+ _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'false');
298
344
 
299
- _classPrivateMethodGet(this, _setOpen, _setOpen2).call(this, true);
345
+ if (_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
346
+ _classPrivateFieldGet(this, _$listbox).close?.();
347
+ }
348
+ }
300
349
 
301
- const buttonRect = _classPrivateFieldGet(this, _$button).getBoundingClientRect();
350
+ function _isOpen2() {
351
+ return _classPrivateFieldGet(this, _isConnected) && getBooleanAttribute(_classPrivateFieldGet(this, _$listbox), 'open');
352
+ }
353
+
354
+ function _updateOrientation2() {
355
+ _classPrivateFieldGet(this, _$listbox).style.transform = `initial`;
356
+ _classPrivateFieldGet(this, _$listbox).style.width = `max-content`;
357
+
358
+ const buttonRect = _classPrivateFieldGet(this, _$target).getBoundingClientRect();
302
359
 
303
360
  const modalRect = _classPrivateFieldGet(this, _$listbox).getBoundingClientRect();
304
361
 
@@ -326,17 +383,6 @@ function _onExpand2() {
326
383
 
327
384
  _classPrivateFieldGet(this, _$listbox).style.transform = `translateX(${leftOffset}px) translateY(${topOffset}px)`;
328
385
  _classPrivateFieldGet(this, _$listbox).style.width = `${width}px`;
329
-
330
- _classPrivateMethodGet(this, _selectOption, _selectOption2).call(this, _classPrivateMethodGet(this, _getOptionWithValue, _getOptionWithValue2).call(this, this.value) ?? _classPrivateMethodGet(this, _getFirstOption, _getFirstOption2).call(this));
331
- }
332
-
333
- function _onCollapse2() {
334
- _classPrivateFieldGet(this, _$button).setAttribute('aria-expanded', 'false');
335
-
336
- _classPrivateMethodGet(this, _setOpen, _setOpen2).call(this, false);
337
-
338
- _classPrivateFieldGet(this, _$listbox).style.transform = `initial`;
339
- _classPrivateFieldGet(this, _$listbox).style.width = `max-content`;
340
386
  }
341
387
 
342
388
  function _onValueChange2(value) {
@@ -430,4 +476,10 @@ function _dispatchChangeEvent2($opt) {
430
476
  bubbles: true
431
477
  }));
432
478
  }
479
+ }
480
+
481
+ function _dispatchCloseEvent2() {
482
+ this.dispatchEvent(new CustomEvent('close', {
483
+ bubbles: true
484
+ }));
433
485
  }
@@ -0,0 +1,11 @@
1
+ import type { TSinchIconElement, TSinchIconReact } from '../types';
2
+ declare global {
3
+ namespace JSX {
4
+ interface IntrinsicElements {
5
+ 'sinch-icon-filter-list': TSinchIconReact;
6
+ }
7
+ }
8
+ interface HTMLElementTagNameMap {
9
+ 'sinch-icon-filter-list': TSinchIconElement;
10
+ }
11
+ }
@@ -0,0 +1,4 @@
1
+ import { defineCustomElement } from '../../utils';
2
+ import { createIconClass } from '../create-icon-class';
3
+ const templateHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M11 18h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1ZM3 7c0 .55.45 1 1 1h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1Zm4 6h10c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1Z"/></svg>';
4
+ defineCustomElement('sinch-icon-filter-list', createIconClass(templateHTML));
@@ -8,7 +8,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
8
8
  function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
9
9
 
10
10
  import { defineCustomElement, getBooleanAttribute, isAttrTrue, updateBooleanAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}button{all:initial;display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:48px;height:48px;border-radius:4px;background-color:transparent;box-shadow:0 0 0 1px transparent inset;cursor:pointer;--sinch-size-icon:24px;--sinch-color-icon:var(--sinch-color-stormy-500)}button:focus{box-shadow:0 0 0 1px var(--sinch-color-stormy-500) inset}button:hover{background-color:var(--sinch-color-snow-500)}button:active{background-color:var(--sinch-color-snow-600)}button:disabled{background-color:transparent;cursor:initial;--sinch-color-spinner-bg:var(--sinch-color-snow-200);--sinch-color-spinner-fg:var(--sinch-color-stormy-200);--sinch-color-icon:var(--sinch-color-stormy-100)}:host([small]:not([small=false]))>button{width:32px;height:32px}button>*{pointer-events:none}</style><button><slot name="icon"></slot></button>';
11
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}button{all:initial;display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:48px;height:48px;border-radius:4px;background-color:transparent;box-shadow:0 0 0 1px transparent inset;cursor:pointer;--sinch-size-icon:24px;--sinch-color-icon:var(--sinch-icon-button-color, var(--sinch-color-stormy-500))}button:focus{box-shadow:0 0 0 1px var(--sinch-color-stormy-500) inset}button:hover{background-color:var(--sinch-color-snow-500)}button:active{background-color:var(--sinch-color-snow-600)}button:disabled{background-color:transparent;cursor:initial;--sinch-color-spinner-bg:var(--sinch-color-snow-200);--sinch-color-spinner-fg:var(--sinch-color-stormy-200);--sinch-color-icon:var(--sinch-color-stormy-100)}:host([small]:not([small=false]))>button{width:32px;height:32px}button>*{pointer-events:none}</style><button><slot name="icon"></slot></button>';
12
12
  const template = document.createElement('template');
13
13
  template.innerHTML = templateHTML;
14
14
  defineCustomElement('sinch-icon-button', (_$button = new WeakMap(), class extends HTMLElement {
package/index.d.ts CHANGED
@@ -8,6 +8,7 @@ import './button';
8
8
  import './card';
9
9
  import './card-button';
10
10
  import './card-link';
11
+ import './card-container';
11
12
  import './checkbox';
12
13
  import './input';
13
14
  import './help-tooltip';
@@ -89,6 +90,7 @@ import './icon/arrow-right';
89
90
  import './icon/campaign';
90
91
  import './icon/check';
91
92
  import './icon/double-arrow';
93
+ import './icon/filter-list';
92
94
  import './icon/first-page';
93
95
  import './icon/fullscreen';
94
96
  import './icon/fullscreen-exit';
@@ -113,7 +115,6 @@ import './table';
113
115
  import './table-cell';
114
116
  import './table-head';
115
117
  import './table-head-cell';
116
- import './table-head-sort';
117
118
  import './table-body';
118
119
  import './table-row';
119
120
  import './spinner';
@@ -146,3 +147,4 @@ import './chat-bubble';
146
147
  import './chat-block';
147
148
  import './chat';
148
149
  import './title';
150
+ import './popover';
package/index.js CHANGED
@@ -8,6 +8,7 @@ import './button';
8
8
  import './card';
9
9
  import './card-button';
10
10
  import './card-link';
11
+ import './card-container';
11
12
  import './checkbox';
12
13
  import './input';
13
14
  import './help-tooltip';
@@ -89,6 +90,7 @@ import './icon/arrow-right';
89
90
  import './icon/campaign';
90
91
  import './icon/check';
91
92
  import './icon/double-arrow';
93
+ import './icon/filter-list';
92
94
  import './icon/first-page';
93
95
  import './icon/fullscreen';
94
96
  import './icon/fullscreen-exit';
@@ -113,7 +115,6 @@ import './table';
113
115
  import './table-cell';
114
116
  import './table-head';
115
117
  import './table-head-cell';
116
- import './table-head-sort';
117
118
  import './table-body';
118
119
  import './table-row';
119
120
  import './spinner';
@@ -145,4 +146,5 @@ import './chat-avatar';
145
146
  import './chat-bubble';
146
147
  import './chat-block';
147
148
  import './chat';
148
- import './title';
149
+ import './title';
150
+ import './popover';
package/input/index.js CHANGED
@@ -8,7 +8,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
8
8
  function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
9
9
 
10
10
  import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, isAttrTrue, updateAttribute, updateBooleanAttribute, updateLiteralAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{width:100%;box-sizing:border-box}#input{all:initial;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;height:48px;margin:2px 0;padding:0 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto)}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100)}#input:disabled::placeholder{color:var(--sinch-color-snow-500)}#input:focus{border-color:var(--sinch-color-stormy-600)}#input[type=password]{font-size:1.5em;letter-spacing:.1em}:host([invalidtext]:not([invalidtext=""])) #input:not(:disabled){border-color:var(--sinch-color-text-invalid)}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><div id="top"><label id="label" for="input"></label><slot name="tooltip"></slot><span id="optional"></span></div><input id="input" type="text"/><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
11
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{width:100%;box-sizing:border-box}#input{all:initial;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;height:48px;margin:2px 0;padding:0 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto);background-color:var(--sinch-color-snow-100)}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100)}#input:disabled::placeholder{color:var(--sinch-color-snow-500)}#input:focus{border-color:var(--sinch-color-stormy-600)}#input[type=password]{font-size:1.5em;letter-spacing:.1em}:host([invalidtext]:not([invalidtext=""])) #input:not(:disabled){border-color:var(--sinch-color-text-invalid)}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><div id="top"><label id="label" for="input"></label><slot name="tooltip"></slot><span id="optional"></span></div><input id="input" type="text"/><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
12
12
  const inputTypes = ['text', 'password'];
13
13
  const template = document.createElement('template');
14
14
  template.innerHTML = templateHTML;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "files": [
5
5
  "theme.css",
6
6
  "**/*/*.js",
@@ -0,0 +1,26 @@
1
+ import type { TRect, TSinchElementReact } from '../types';
2
+ import type { SyntheticEvent } from 'react';
3
+ declare const orientationValues: readonly ["top-left", "top-right", "bottom-left", "bottom-right"];
4
+ export declare type TSinchPopoverOrientation = typeof orientationValues[number];
5
+ export declare type TSinchPopoverElement = HTMLElement & {
6
+ open: boolean;
7
+ orientation: TSinchPopoverOrientation;
8
+ readonly popoverRect: TRect;
9
+ };
10
+ export declare type TSinchPopoverReact = TSinchElementReact<TSinchPopoverElement> & {
11
+ open: boolean;
12
+ orientation?: TSinchPopoverOrientation;
13
+ 'aria-label': string;
14
+ onClose: (event: SyntheticEvent<TSinchPopoverElement, CustomEvent<void>>) => void;
15
+ };
16
+ declare global {
17
+ namespace JSX {
18
+ interface IntrinsicElements {
19
+ 'sinch-popover': TSinchPopoverReact;
20
+ }
21
+ }
22
+ interface HTMLElementTagNameMap {
23
+ 'sinch-popover': TSinchPopoverElement;
24
+ }
25
+ }
26
+ export {};
@@ -0,0 +1,230 @@
1
+ import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
2
+ import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
3
+
4
+ var _$target, _$dialog, _isConnected, _onExpand, _onCollapse, _isOpen, _updateOrientation, _onBackdropClick, _onCancel, _onCloseReactHandler, _dispatchCloseEvent;
5
+
6
+ function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
+
8
+ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
9
+
10
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
11
+
12
+ function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
13
+
14
+ import dialogPolyfill from 'dialog-polyfill';
15
+ import { defineCustomElement, getBooleanAttribute, getLiteralAttribute, getRect, isAttrTrue, updateLiteralAttribute, getReactEventHandler, updateBooleanAttribute } from '../utils';
16
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative}dialog{outline:0;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:1px 2px 6px rgba(0,0,0,.15);border:1px solid var(--sinch-color-snow-500);border-radius:4px;overflow-y:auto;contain:content;padding:12px;box-sizing:border-box}dialog:not([open]){display:none}dialog::backdrop{background-color:transparent}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:transparent}dialog.fixed{position:fixed;top:50%;transform:translate(0,-50%)}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}</style><div id="wrapper"><div id="target" aria-haspopup="dialog" aria-expanded="false"><slot name="target"></slot></div><dialog id="dialog" tabindex="-1"><slot name="content"></slot></dialog></div>';
17
+ const orientationValues = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
18
+ const template = document.createElement('template');
19
+ template.innerHTML = templateHTML;
20
+ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new WeakMap(), _isConnected = new WeakMap(), _onExpand = new WeakSet(), _onCollapse = new WeakSet(), _isOpen = new WeakSet(), _updateOrientation = new WeakSet(), _onBackdropClick = new WeakMap(), _onCancel = new WeakMap(), _onCloseReactHandler = new WeakMap(), _dispatchCloseEvent = new WeakSet(), class extends HTMLElement {
21
+ constructor() {
22
+ super();
23
+
24
+ _classPrivateMethodInitSpec(this, _dispatchCloseEvent);
25
+
26
+ _classPrivateMethodInitSpec(this, _updateOrientation);
27
+
28
+ _classPrivateMethodInitSpec(this, _isOpen);
29
+
30
+ _classPrivateMethodInitSpec(this, _onCollapse);
31
+
32
+ _classPrivateMethodInitSpec(this, _onExpand);
33
+
34
+ _classPrivateFieldInitSpec(this, _$target, {
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+
39
+ _classPrivateFieldInitSpec(this, _$dialog, {
40
+ writable: true,
41
+ value: void 0
42
+ });
43
+
44
+ _classPrivateFieldInitSpec(this, _isConnected, {
45
+ writable: true,
46
+ value: false
47
+ });
48
+
49
+ _classPrivateFieldInitSpec(this, _onBackdropClick, {
50
+ writable: true,
51
+ value: e => {
52
+ const rect = this.popoverRect;
53
+ const isInside = e.x >= rect.x && e.x < rect.x + rect.width && e.y >= rect.y && e.y < rect.y + rect.height;
54
+
55
+ if (!isInside) {
56
+ _classPrivateMethodGet(this, _dispatchCloseEvent, _dispatchCloseEvent2).call(this);
57
+ }
58
+ }
59
+ });
60
+
61
+ _classPrivateFieldInitSpec(this, _onCancel, {
62
+ writable: true,
63
+ value: e => {
64
+ e.preventDefault();
65
+
66
+ _classPrivateMethodGet(this, _dispatchCloseEvent, _dispatchCloseEvent2).call(this);
67
+ }
68
+ });
69
+
70
+ _classPrivateFieldInitSpec(this, _onCloseReactHandler, {
71
+ writable: true,
72
+ value: () => {
73
+ getReactEventHandler(this, 'onClose')?.();
74
+ }
75
+ });
76
+
77
+ const shadowRoot = this.attachShadow({
78
+ mode: 'closed',
79
+ delegatesFocus: true
80
+ });
81
+ shadowRoot.appendChild(template.content.cloneNode(true));
82
+
83
+ _classPrivateFieldSet(this, _$target, shadowRoot.querySelector('#target'));
84
+
85
+ _classPrivateFieldSet(this, _$dialog, shadowRoot.querySelector('#dialog'));
86
+
87
+ dialogPolyfill.registerDialog(_classPrivateFieldGet(this, _$dialog));
88
+ }
89
+
90
+ connectedCallback() {
91
+ this.setAttribute('role', 'dialog');
92
+
93
+ _classPrivateFieldGet(this, _$dialog).addEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
94
+
95
+ _classPrivateFieldGet(this, _$dialog).addEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
96
+
97
+ this.addEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
98
+
99
+ _classPrivateFieldSet(this, _isConnected, true);
100
+
101
+ if (getBooleanAttribute(this, 'open')) {
102
+ _classPrivateMethodGet(this, _onExpand, _onExpand2).call(this);
103
+ } else {
104
+ _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
105
+ }
106
+ }
107
+
108
+ disconnectedCallback() {
109
+ _classPrivateFieldGet(this, _$dialog).removeEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
110
+
111
+ _classPrivateFieldGet(this, _$dialog).removeEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
112
+
113
+ this.removeEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
114
+
115
+ _classPrivateFieldSet(this, _isConnected, false);
116
+ }
117
+
118
+ static get observedAttributes() {
119
+ return ['open', 'orientation'];
120
+ }
121
+
122
+ set open(isOpen) {
123
+ updateBooleanAttribute(this, 'open', isOpen);
124
+ }
125
+
126
+ get open() {
127
+ return getBooleanAttribute(this, 'open');
128
+ }
129
+
130
+ get orientation() {
131
+ return getLiteralAttribute(this, orientationValues, 'orientation', 'bottom-right');
132
+ }
133
+
134
+ set orientation(value) {
135
+ updateLiteralAttribute(this, orientationValues, 'orientation', value);
136
+ }
137
+
138
+ get popoverRect() {
139
+ return getRect(_classPrivateFieldGet(this, _$dialog));
140
+ }
141
+
142
+ attributeChangedCallback(name, oldVal, newVal) {
143
+ switch (name) {
144
+ case 'open':
145
+ {
146
+ if (_classPrivateFieldGet(this, _isConnected)) {
147
+ if (isAttrTrue(newVal)) {
148
+ _classPrivateMethodGet(this, _onExpand, _onExpand2).call(this);
149
+ } else {
150
+ _classPrivateMethodGet(this, _onCollapse, _onCollapse2).call(this);
151
+ }
152
+ }
153
+
154
+ break;
155
+ }
156
+
157
+ case 'orientation':
158
+ {
159
+ if (_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
160
+ _classPrivateMethodGet(this, _updateOrientation, _updateOrientation2).call(this);
161
+ }
162
+
163
+ break;
164
+ }
165
+ }
166
+ }
167
+
168
+ }));
169
+
170
+ function _onExpand2() {
171
+ _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'true');
172
+
173
+ if (!_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
174
+ _classPrivateFieldGet(this, _$dialog).showModal();
175
+ }
176
+
177
+ _classPrivateMethodGet(this, _updateOrientation, _updateOrientation2).call(this);
178
+ }
179
+
180
+ function _onCollapse2() {
181
+ _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'false');
182
+
183
+ if (_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
184
+ _classPrivateFieldGet(this, _$dialog).close?.();
185
+ }
186
+ }
187
+
188
+ function _isOpen2() {
189
+ return _classPrivateFieldGet(this, _isConnected) && getBooleanAttribute(_classPrivateFieldGet(this, _$dialog), 'open');
190
+ }
191
+
192
+ function _updateOrientation2() {
193
+ _classPrivateFieldGet(this, _$dialog).style.transform = `initial`;
194
+ _classPrivateFieldGet(this, _$dialog).style.width = `max-content`;
195
+
196
+ const buttonRect = _classPrivateFieldGet(this, _$target).getBoundingClientRect();
197
+
198
+ const modalRect = _classPrivateFieldGet(this, _$dialog).getBoundingClientRect();
199
+
200
+ const width = Math.max(modalRect.width, buttonRect.width);
201
+ const widthDiff = Math.max(buttonRect.width - modalRect.width, 0);
202
+ let leftOffset = 0;
203
+ let topOffset = 0;
204
+ const orient = this.orientation;
205
+
206
+ if (orient === 'bottom-right' || orient === 'top-right') {
207
+ leftOffset = Math.min(modalRect.x, Math.max(-modalRect.x, buttonRect.x - modalRect.x + widthDiff * 0.5));
208
+ }
209
+
210
+ if (orient === 'bottom-left' || orient === 'top-left') {
211
+ leftOffset = Math.min(modalRect.x, Math.max(-modalRect.x, buttonRect.x + buttonRect.width - modalRect.x - modalRect.width - widthDiff * 0.5));
212
+ }
213
+
214
+ if (orient === 'bottom-left' || orient === 'bottom-right') {
215
+ topOffset = Math.min(modalRect.y, Math.max(-modalRect.y, buttonRect.y + buttonRect.height - modalRect.y + 8));
216
+ }
217
+
218
+ if (orient === 'top-left' || orient === 'top-right') {
219
+ topOffset = Math.min(modalRect.y, Math.max(-modalRect.y, buttonRect.y - modalRect.y - modalRect.height - 8));
220
+ }
221
+
222
+ _classPrivateFieldGet(this, _$dialog).style.transform = `translateX(${leftOffset}px) translateY(${topOffset}px)`;
223
+ _classPrivateFieldGet(this, _$dialog).style.width = `${width}px`;
224
+ }
225
+
226
+ function _dispatchCloseEvent2() {
227
+ this.dispatchEvent(new CustomEvent('close', {
228
+ bubbles: true
229
+ }));
230
+ }
package/search/index.js CHANGED
@@ -13,7 +13,7 @@ function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(
13
13
 
14
14
  import { isSearchOptionElement } from '../search-option';
15
15
  import { attrValueToPixels, defineCustomElement, getAttribute, getIntegerAttribute, getRect, updateAttribute, updateIntegerAttribute } from '../utils';
16
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative;width:100%;box-sizing:border-box;--sinch-size-icon:24px}#label{display:none;font:var(--sinch-font-title-s);color:var(--sinch-color-text-default);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%;height:24px;margin-bottom:2px}#input{all:initial;display:block;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;height:48px;padding:0 44px;padding-right:12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto)}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:focus{border-color:var(--sinch-color-stormy-600)}#icon-search{position:absolute;left:12px;top:12px;pointer-events:none;--sinch-color-icon:var(--sinch-color-stormy-500)}#clear{position:absolute;right:8px;top:8px;display:none;--sinch-color-icon:red}#clear:focus{--sinch-color-icon:var(--sinch-color-stormy-500)}:host([value]:not([value=""])) #clear{display:flex}:host([value]:not([value=""])) #input{padding-right:44px}#listbox{display:none;position:absolute;z-index:1;left:0;top:calc(100% + 8px);width:100%;box-sizing:border-box;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:1px 2px 4px rgb(0 0 0 / 15%);overflow-y:auto;contain:content}:host([aria-expanded=true]) #listbox{display:block}:host([label]:not([label=""])) #label{display:block}</style><label id="label" for="input"></label><div id="wrapper"><input id="input" type="text"/><sinch-icon-search id="icon-search"></sinch-icon-search><sinch-icon-button id="clear" small><sinch-icon-close id="icon-close" slot="icon"></sinch-icon-close></sinch-icon-button><div id="listbox"><slot name="option"></slot></div></div>';
16
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative;width:100%;box-sizing:border-box;--sinch-size-icon:24px}#label{display:none;font:var(--sinch-font-title-s);color:var(--sinch-color-text-default);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%;height:24px;margin-bottom:2px}#input{all:initial;display:block;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;height:48px;padding:0 44px;padding-right:12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto);background-color:var(--sinch-color-snow-100)}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:focus{border-color:var(--sinch-color-stormy-600)}#icon-search{position:absolute;left:12px;top:12px;pointer-events:none;--sinch-color-icon:var(--sinch-color-stormy-500)}#clear{position:absolute;right:8px;top:8px;display:none;--sinch-color-icon:red}#clear:focus{--sinch-color-icon:var(--sinch-color-stormy-500)}:host([value]:not([value=""])) #clear{display:flex}:host([value]:not([value=""])) #input{padding-right:44px}#listbox{display:none;position:absolute;z-index:1;left:0;top:calc(100% + 8px);width:100%;box-sizing:border-box;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:1px 2px 4px rgba(0,0,0,.15);overflow-y:auto;contain:content}:host([aria-expanded=true]) #listbox{display:block}:host([label]:not([label=""])) #label{display:block}</style><label id="label" for="input"></label><div id="wrapper"><input id="input" type="text"/><sinch-icon-search id="icon-search"></sinch-icon-search><sinch-icon-button id="clear" small><sinch-icon-close id="icon-close" slot="icon"></sinch-icon-close></sinch-icon-button><div id="listbox"><slot name="option"></slot></div></div>';
17
17
  import '../icon/search';
18
18
  import '../icon/close';
19
19
  import '../icon-button';
package/segment/index.js CHANGED
@@ -8,7 +8,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
8
8
  function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
9
9
 
10
10
  import { defineCustomElement, getAttribute, getBooleanAttribute, updateAttribute, updateBooleanAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;width:100%;border-radius:4px;box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);border:none;box-shadow:1px 2px 8px rgb(0 0 0 / 10%)}#header{position:relative;display:flex;flex-direction:row;align-items:center;gap:16px;height:32px;padding:24px 32px 16px;--sinch-size-icon:32px}#caption{font:var(--sinch-font-title-l);color:var(--sinch-color-text-default);flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}#content-wrapper{padding:0 32px}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;padding:16px 32px 24px}#info{position:relative;display:flex;flex-direction:row;align-items:center;gap:16px;z-index:1}:host([collapsed]:not([collapsed=false])) :is(#content-wrapper,#action){display:none}:host([collapsed]:not([collapsed=false])) #header{padding-bottom:24px}</style><div id="wrapper"><div id="header"><slot name="icon"></slot><span id="caption"></span><div id="info"><slot name="info"></slot></div><slot name="collapse"></slot></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
11
+ const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;width:100%;height:100%;border-radius:4px;box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);border:none;box-shadow:1px 2px 8px rgba(0,0,0,.1)}#header{position:relative;display:flex;flex-direction:row;align-items:center;gap:16px;height:32px;padding:24px 32px 16px;--sinch-size-icon:32px}#caption{font:var(--sinch-font-title-l);color:var(--sinch-color-text-default);flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}#content-wrapper{padding:0 32px;flex:1;min-height:0;overflow:auto}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;padding:16px 32px 24px}#info{position:relative;display:flex;flex-direction:row;align-items:center;gap:16px;z-index:1}:host([collapsed]:not([collapsed=false])) :is(#content-wrapper,#action){display:none}:host([collapsed]:not([collapsed=false])) #header{padding-bottom:24px}</style><div id="wrapper"><div id="header"><slot name="icon"></slot><span id="caption"></span><div id="info"><slot name="info"></slot></div><slot name="collapse"></slot></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
12
12
  const template = document.createElement('template');
13
13
  template.innerHTML = templateHTML;
14
14
  defineCustomElement('sinch-segment', (_$caption = new WeakMap(), class extends HTMLElement {
package/select/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
2
2
  import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
3
3
 
4
- var _$button, _$buttonContent, _$label, _$optionalText, _$additionalText, _$invalidText, _$dropdown, _$optionSlot, _updateButtonContent, _onValueChange, _getOptionWithValue, _onLabelClick;
4
+ var _$button, _$buttonContent, _$label, _$optionalText, _$additionalText, _$invalidText, _$dropdown, _$optionSlot, _updateButtonContent, _onValueChange, _getOptionWithValue, _onLabelClick, _onDropdownClick, _onDropdownClose;
5
5
 
6
6
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
7
 
@@ -15,10 +15,10 @@ import { isDropdownOptionElement } from '../dropdown-option';
15
15
  import '../select-option';
16
16
  import '../dropdown';
17
17
  import { defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, isAttrTrue, updateAttribute, updateBooleanAttribute, updateIntegerAttribute } from '../utils';
18
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{position:relative}sinch-dropdown{display:block}#button{all:initial;display:flex;align-items:center;gap:8px;border:1px solid var(--sinch-color-stormy-200);border-radius:4px;box-sizing:border-box;width:100%;height:48px;margin:2px 0;padding:8px 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);cursor:pointer}#button:focus{border-color:var(--sinch-color-stormy-600)}#dropdown-icon{fill:var(--sinch-color-stormy-500)}#button>*{pointer-events:none}#button[data-unselected]{color:var(--sinch-color-text-muted)}#button:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100);cursor:initial}#button:disabled #dropdown-icon{fill:var(--sinch-color-stormy-100)}:host([invalidtext]:not([invalidtext=""])) #button:not(:disabled){border-color:var(--sinch-color-text-invalid)}#content{flex:1;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}#listbox{position:absolute;left:0;top:0;padding-top:74px;width:100%;display:none;list-style:none;outline:0;z-index:1}#listbox-body{font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);border:1px solid var(--sinch-color-stormy-500);border-top-width:0;border-bottom-left-radius:2px;border-bottom-right-radius:2px;width:100%;box-sizing:border-box;box-shadow:1px 2px 4px rgb(0 0 0 / 15%);overflow-y:auto}#button[aria-expanded=true]~#listbox{display:block}</style><div id="wrapper"><div id="top"><label id="label" for="dropdown"></label><slot name="tooltip"></slot><span id="optional"></span></div><sinch-dropdown id="dropdown"><button slot="target" id="button"><span id="content"></span> <svg id="dropdown-icon" width="12" height="8" aria-hidden="true"><path d="M1.41.59 6 5.17 10.59.59 12 2 6 8 0 2 1.41.59Z"/></svg></button><slot name="option" slot="option"></slot></sinch-dropdown><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
18
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{position:relative}sinch-dropdown{display:block}#button{all:initial;display:flex;align-items:center;gap:8px;border:1px solid var(--sinch-color-stormy-200);border-radius:4px;box-sizing:border-box;width:100%;height:48px;margin:2px 0;padding:8px 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);cursor:pointer}#button:focus{border-color:var(--sinch-color-stormy-600)}#dropdown-icon{fill:var(--sinch-color-stormy-500)}#button>*{pointer-events:none}#button[data-unselected]{color:var(--sinch-color-text-muted)}#button:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100);cursor:initial}#button:disabled #dropdown-icon{fill:var(--sinch-color-stormy-100)}:host([invalidtext]:not([invalidtext=""])) #button:not(:disabled){border-color:var(--sinch-color-text-invalid)}#content{flex:1;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}#listbox{position:absolute;left:0;top:0;padding-top:74px;width:100%;display:none;list-style:none;outline:0;z-index:1}#listbox-body{font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);border:1px solid var(--sinch-color-stormy-500);border-top-width:0;border-bottom-left-radius:2px;border-bottom-right-radius:2px;width:100%;box-sizing:border-box;box-shadow:1px 2px 4px rgba(0,0,0,.15);overflow-y:auto}#button[aria-expanded=true]~#listbox{display:block}</style><div id="wrapper"><div id="top"><label id="label" for="dropdown"></label><slot name="tooltip"></slot><span id="optional"></span></div><sinch-dropdown id="dropdown"><button slot="target" id="button"><span id="content"></span> <svg id="dropdown-icon" width="12" height="8" aria-hidden="true"><path d="M1.41.59 6 5.17 10.59.59 12 2 6 8 0 2 1.41.59Z"/></svg></button><slot name="option" slot="option"></slot></sinch-dropdown><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
19
19
  const template = document.createElement('template');
20
20
  template.innerHTML = templateHTML;
21
- defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent = new WeakMap(), _$label = new WeakMap(), _$optionalText = new WeakMap(), _$additionalText = new WeakMap(), _$invalidText = new WeakMap(), _$dropdown = new WeakMap(), _$optionSlot = new WeakMap(), _updateButtonContent = new WeakSet(), _onValueChange = new WeakMap(), _getOptionWithValue = new WeakSet(), _onLabelClick = new WeakMap(), class extends HTMLElement {
21
+ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent = new WeakMap(), _$label = new WeakMap(), _$optionalText = new WeakMap(), _$additionalText = new WeakMap(), _$invalidText = new WeakMap(), _$dropdown = new WeakMap(), _$optionSlot = new WeakMap(), _updateButtonContent = new WeakSet(), _onValueChange = new WeakMap(), _getOptionWithValue = new WeakSet(), _onLabelClick = new WeakMap(), _onDropdownClick = new WeakMap(), _onDropdownClose = new WeakMap(), class extends HTMLElement {
22
22
  constructor() {
23
23
  super();
24
24
 
@@ -69,6 +69,7 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
69
69
  _classPrivateFieldInitSpec(this, _onValueChange, {
70
70
  writable: true,
71
71
  value: e => {
72
+ _classPrivateFieldGet(this, _$dropdown).open = false;
72
73
  this.dispatchEvent(new CustomEvent('change', {
73
74
  detail: e.detail,
74
75
  bubbles: true
@@ -83,6 +84,20 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
83
84
  }
84
85
  });
85
86
 
87
+ _classPrivateFieldInitSpec(this, _onDropdownClick, {
88
+ writable: true,
89
+ value: () => {
90
+ _classPrivateFieldGet(this, _$dropdown).open = true;
91
+ }
92
+ });
93
+
94
+ _classPrivateFieldInitSpec(this, _onDropdownClose, {
95
+ writable: true,
96
+ value: () => {
97
+ _classPrivateFieldGet(this, _$dropdown).open = false;
98
+ }
99
+ });
100
+
86
101
  const shadowRoot = this.attachShadow({
87
102
  mode: 'closed',
88
103
  delegatesFocus: true
@@ -111,12 +126,20 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
111
126
 
112
127
  _classPrivateFieldGet(this, _$dropdown).addEventListener('change', _classPrivateFieldGet(this, _onValueChange));
113
128
 
129
+ _classPrivateFieldGet(this, _$dropdown).addEventListener('close', _classPrivateFieldGet(this, _onDropdownClose));
130
+
131
+ _classPrivateFieldGet(this, _$button).addEventListener('click', _classPrivateFieldGet(this, _onDropdownClick));
132
+
114
133
  _classPrivateFieldGet(this, _$label).addEventListener('click', _classPrivateFieldGet(this, _onLabelClick));
115
134
  }
116
135
 
117
136
  disconnectedCallback() {
118
137
  _classPrivateFieldGet(this, _$dropdown).removeEventListener('change', _classPrivateFieldGet(this, _onValueChange));
119
138
 
139
+ _classPrivateFieldGet(this, _$dropdown).removeEventListener('close', _classPrivateFieldGet(this, _onDropdownClose));
140
+
141
+ _classPrivateFieldGet(this, _$button).removeEventListener('click', _classPrivateFieldGet(this, _onDropdownClick));
142
+
120
143
  _classPrivateFieldGet(this, _$label).removeEventListener('click', _classPrivateFieldGet(this, _onLabelClick));
121
144
  }
122
145
 
@@ -1,5 +1,5 @@
1
1
  import { defineCustomElement } from '../utils';
2
- const templateHTML = '<style>:host{display:table-row-group}</style><slot></slot>';
2
+ const templateHTML = '<style>:host{display:table-row-group}::slotted(sinch-table-row:hover){background-color:var(--sinch-color-tropical-50)}::slotted(sinch-table-row[selected]:not([selected=false])){background-color:var(--sinch-color-tropical-100)}</style><slot></slot>';
3
3
  const template = document.createElement('template');
4
4
  template.innerHTML = templateHTML;
5
5
  defineCustomElement('sinch-table-body', class extends HTMLElement {
@@ -8,7 +8,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
8
8
  function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
9
9
 
10
10
  import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, updateAttribute, updateBooleanAttribute, updateLiteralAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:table-cell;border-bottom:1px solid var(--sinch-color-stormy-200);height:48px;vertical-align:middle;padding:0 6px;--sinch-color-icon:var(--sinch-color-stormy-200)}:host(:first-child){padding-left:8px}:host(:last-child){padding-right:8px}#wrapper{position:relative;width:100%;height:100%;box-sizing:border-box;font:var(--sinch-font-title-s);color:var(--sinch-color-stormy-300);display:flex;align-items:center;gap:4px}#text{flex-shrink:1;min-width:0;font:var(--sinch-font-title-s);color:var(--sinch-color-stormy-200);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host([align=center])>#wrapper{justify-content:center}:host([align=end]) #text{margin-left:auto}:host(:is([text=""],:not([text])))>#wrapper{display:none}:host([fit]:not([fit=false])){width:1px}::slotted(sinch-help-tooltip){position:relative;z-index:1}</style><slot name="checkbox"></slot><div id="wrapper"><span id="text"></span><slot name="tooltip"></slot><slot name="sort"></slot></div>';
11
+ const templateHTML = '<style>:host{display:table-cell;border-bottom:1px solid var(--sinch-color-stormy-200);height:48px;vertical-align:middle;padding:0 6px;--sinch-color-icon:var(--sinch-color-stormy-200)}:host(:first-child){padding-left:8px}:host(:last-child){padding-right:8px}#wrapper{position:relative;display:flex;align-items:center;gap:8px;width:100%;height:100%;box-sizing:border-box;font:var(--sinch-font-title-s);color:var(--sinch-color-stormy-300);--sinch-icon-button-color:var(--sinch-color-stormy-100)}#text{flex-shrink:1;min-width:0;font:var(--sinch-font-title-s);color:var(--sinch-color-stormy-200);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host([align=center])>#wrapper{justify-content:center}:host([align=end])>#wrapper{justify-content:flex-end}:host(:is([text=""],:not([text])))>#wrapper{display:none}:host([fit]:not([fit=false])){width:1px}</style><slot name="checkbox"></slot><div id="wrapper"><slot name="left"></slot><span id="text"></span><slot name="tooltip"></slot><slot name="right"></slot></div>';
12
12
  const template = document.createElement('template');
13
13
  template.innerHTML = templateHTML;
14
14
  const alignValues = ['start', 'center', 'end'];
@@ -1,9 +1,11 @@
1
1
  import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchTableRowElement = HTMLElement & {
3
3
  sticky: boolean;
4
+ selected: boolean;
4
5
  };
5
6
  export declare type TSinchTableRowReact = TSinchElementReact<TSinchTableRowElement> & {
6
7
  sticky?: boolean;
8
+ selected?: boolean;
7
9
  };
8
10
  declare global {
9
11
  namespace JSX {
@@ -23,4 +23,12 @@ defineCustomElement('sinch-table-row', class extends HTMLElement {
23
23
  return getBooleanAttribute(this, 'sticky');
24
24
  }
25
25
 
26
+ set selected(isSelected) {
27
+ updateBooleanAttribute(this, 'selected', isSelected);
28
+ }
29
+
30
+ get selected() {
31
+ return getBooleanAttribute(this, 'selected');
32
+ }
33
+
26
34
  });
package/textarea/index.js CHANGED
@@ -8,7 +8,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
8
8
  function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
9
9
 
10
10
  import { defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, isAttrTrue, updateAttribute, updateBooleanAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{width:100%;box-sizing:border-box}#input{all:initial;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;margin:2px 0;padding:8px 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto);resize:none}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100)}#input:disabled::placeholder{color:var(--sinch-color-snow-500)}#input:focus{border-color:var(--sinch-color-stormy-600)}:host([resizable]:not([resizable=false])) #input{resize:vertical}:host([invalidtext]:not([invalidtext=""])) #input:not(:disabled){border-color:var(--sinch-color-text-invalid)}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><div id="top"><label id="label" for="input"></label><slot name="tooltip"></slot><span id="optional"></span></div><textarea id="input"></textarea><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
11
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0;--sinch-color-icon:var(--sinch-color-stormy-500)}#wrapper{width:100%;box-sizing:border-box}#input{all:initial;border:1px solid var(--sinch-color-stormy-200);box-sizing:border-box;border-radius:4px;width:100%;margin:2px 0;padding:8px 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);caret-color:var(--sinch-caret-color,auto);background-color:var(--sinch-color-snow-100);resize:none}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted)}#input:disabled{border-color:var(--sinch-color-snow-500);color:var(--sinch-color-stormy-100)}#input:disabled::placeholder{color:var(--sinch-color-snow-500)}#input:focus{border-color:var(--sinch-color-stormy-600)}:host([resizable]:not([resizable=false])) #input{resize:vertical}:host([invalidtext]:not([invalidtext=""])) #input:not(:disabled){border-color:var(--sinch-color-text-invalid)}#bottom,#top{display:flex;align-items:baseline}#top{height:24px}#bottom{height:20px}#additional,#invalid,#label,#optional{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#label{font:var(--sinch-font-title-s);color:var(--sinch-color-text-default)}#optional{flex:1;text-align:right;font:var(--sinch-font-small-text);color:var(--sinch-color-text-muted)}#additional{flex:1;text-align:right;font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-muted)}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid)}::slotted(sinch-help-tooltip){align-self:center;margin:0 8px}:host([disabled]:not([disabled=false])) :is(#label,#additional,#optional,#invalid){color:var(--sinch-color-stormy-100)}:host([disabled]:not([disabled=false])){--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><div id="top"><label id="label" for="input"></label><slot name="tooltip"></slot><span id="optional"></span></div><textarea id="input"></textarea><div id="bottom"><span id="invalid"></span> <span id="additional"></span></div></div>';
12
12
  const template = document.createElement('template');
13
13
  template.innerHTML = templateHTML;
14
14
  defineCustomElement('sinch-textarea', (_$input = new WeakMap(), _$label = new WeakMap(), _$optionalText = new WeakMap(), _$additionalText = new WeakMap(), _$invalidText = new WeakMap(), _selectionStart = new WeakMap(), _selectionEnd = new WeakMap(), _isPendingDk = new WeakMap(), _onCompositionStart = new WeakMap(), _onInput = new WeakMap(), class extends HTMLElement {
package/theme.css CHANGED
@@ -15,6 +15,7 @@
15
15
  --sinch-color-tropical-300: #66AAAA;
16
16
  --sinch-color-tropical-200: #99C6C6;
17
17
  --sinch-color-tropical-100: #CCE3E3;
18
+ --sinch-color-tropical-50: #E5F1F1;
18
19
  --sinch-color-stormy-600: #061927;
19
20
  --sinch-color-stormy-500: #0A273D;
20
21
  --sinch-color-stormy-400: #3B5264;
@@ -33,6 +34,7 @@
33
34
  --sinch-color-raspberry-300: #EE778B;
34
35
  --sinch-color-raspberry-200: #F4A4B1;
35
36
  --sinch-color-raspberry-100: #F9D2D8;
37
+ --sinch-color-raspberry-50: #FCE8EB;
36
38
  --sinch-color-text-default: #0A273D;
37
39
  --sinch-color-text-inverted: #FFFFFF;
38
40
  --sinch-color-text-muted: #677784;
package/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { TRect } from './types';
2
+ export declare const getReactEventHandler: ($element: HTMLElement, handlerName: string) => ((arg?: any) => void) | null;
2
3
  export declare const defineCustomElement: (name: string, constructor: CustomElementConstructor) => void;
3
4
  export declare const defineNectaryElements: (registry: CustomElementRegistry) => void;
4
5
  export declare type TEventHandler = (arg?: any) => void;
package/utils.js CHANGED
@@ -1,5 +1,14 @@
1
1
  const nectaryDefinitions = new Map();
2
2
  let nectaryRegistry = null;
3
+ export const getReactEventHandler = ($element, handlerName) => {
4
+ for (const key in $element) {
5
+ if (key.startsWith('__reactProps$')) {
6
+ return $element[key][handlerName];
7
+ }
8
+ }
9
+
10
+ return null;
11
+ };
3
12
  export const defineCustomElement = (name, constructor) => {
4
13
  if (nectaryRegistry !== null) {
5
14
  if (nectaryRegistry.get(name) == null) {
@@ -1,26 +0,0 @@
1
- import '../icon/north';
2
- import '../icon/south';
3
- import type { TSinchElementReact } from '../types';
4
- import type { FocusEvent, SyntheticEvent } from 'react';
5
- export declare type TSinchTableHeaderSortElement = HTMLElement & {
6
- value: boolean;
7
- focus(): void;
8
- blur(): void;
9
- };
10
- export declare type TSinchTableHeaderSortReact = TSinchElementReact<TSinchTableHeaderSortElement> & {
11
- value: boolean;
12
- 'aria-label': string;
13
- onChange: (e: SyntheticEvent<TSinchTableHeaderSortElement, CustomEvent<boolean>>) => void;
14
- onFocus?: (e: FocusEvent<TSinchTableHeaderSortElement>) => void;
15
- onBlur?: (e: FocusEvent<TSinchTableHeaderSortElement>) => void;
16
- };
17
- declare global {
18
- namespace JSX {
19
- interface IntrinsicElements {
20
- 'sinch-table-head-sort': TSinchTableHeaderSortReact;
21
- }
22
- }
23
- interface HTMLElementTagNameMap {
24
- 'sinch-table-head-sort': TSinchTableHeaderSortElement;
25
- }
26
- }
@@ -1,94 +0,0 @@
1
- import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
- import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
3
- import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
4
-
5
- var _$input;
6
-
7
- function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
8
-
9
- function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
10
-
11
- import '../icon/north';
12
- import '../icon/south';
13
- import { defineCustomElement, getBooleanAttribute, isAttrTrue, updateBooleanAttribute } from '../utils';
14
- const templateHTML = '<style>:host{display:contents;--sinch-size-icon:16px}input{all:initial;position:absolute;width:100%;height:100%;box-sizing:border-box;cursor:pointer}#up{display:none}#down{display:block}:host([value]:not([value=false])) #up{display:block}:host([value]:not([value=false])) #down{display:none}</style><sinch-icon-north id="up"></sinch-icon-north><sinch-icon-south id="down"></sinch-icon-south><input type="checkbox"/>';
15
- const template = document.createElement('template');
16
- template.innerHTML = templateHTML;
17
- defineCustomElement('sinch-table-head-sort', (_$input = new WeakMap(), class extends HTMLElement {
18
- constructor() {
19
- super();
20
-
21
- _classPrivateFieldInitSpec(this, _$input, {
22
- writable: true,
23
- value: void 0
24
- });
25
-
26
- _defineProperty(this, 'onCheckboxInput', e => {
27
- e.stopPropagation();
28
-
29
- const isChecked = _classPrivateFieldGet(this, _$input).checked;
30
-
31
- _classPrivateFieldGet(this, _$input).checked = this.value;
32
- this.dispatchEvent(new CustomEvent('change', {
33
- detail: isChecked,
34
- bubbles: true
35
- }));
36
- });
37
-
38
- const shadowRoot = this.attachShadow({
39
- mode: 'closed'
40
- });
41
- shadowRoot.appendChild(template.content.cloneNode(true));
42
-
43
- _classPrivateFieldSet(this, _$input, shadowRoot.querySelector('input'));
44
- }
45
-
46
- connectedCallback() {
47
- this.setAttribute('role', 'checkbox');
48
-
49
- _classPrivateFieldGet(this, _$input).addEventListener('input', this.onCheckboxInput);
50
- }
51
-
52
- disconnectedCallback() {
53
- _classPrivateFieldGet(this, _$input).removeEventListener('input', this.onCheckboxInput);
54
- }
55
-
56
- get type() {
57
- return 'text';
58
- }
59
-
60
- get nodeName() {
61
- return 'input';
62
- }
63
-
64
- static get observedAttributes() {
65
- return ['value'];
66
- }
67
-
68
- attributeChangedCallback(name, _, newVal) {
69
- switch (name) {
70
- case 'value':
71
- {
72
- _classPrivateFieldGet(this, _$input).checked = isAttrTrue(newVal);
73
- break;
74
- }
75
- }
76
- }
77
-
78
- set value(isChecked) {
79
- updateBooleanAttribute(this, 'value', isChecked);
80
- }
81
-
82
- get value() {
83
- return getBooleanAttribute(this, 'value');
84
- }
85
-
86
- focus() {
87
- _classPrivateFieldGet(this, _$input).focus();
88
- }
89
-
90
- blur() {
91
- _classPrivateFieldGet(this, _$input).blur();
92
- }
93
-
94
- }));