@nectary/components 0.36.0 → 0.37.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.
package/link/index.js CHANGED
@@ -8,8 +8,9 @@ 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 '../icons/open-in-new';
11
+ import '../icons/arrow-forward';
11
12
  import { defineCustomElement, getBooleanAttribute, getAttribute, updateBooleanAttribute, updateAttribute, NectaryElement, isAttrTrue, getReactEventHandler } from '../utils';
12
- const templateHTML = '<style>:host{display:inline;outline:0}a{font:var(--sinch-font-body);font-size:inherit;line-height:inherit;color:var(--sinch-color-text-link);fill:var(--sinch-color-text-link);--sinch-size-icon:1em}#icon{display:none;margin-left:.2em;vertical-align:-.25em}a:hover{color:var(--sinch-color-tropical-600);fill:var(--sinch-color-tropical-600)}:host([disabled]:not([disabled=false])) a{color:var(--sinch-color-tropical-200);pointer-events:none;cursor:initial;fill:var(--sinch-color-tropical-200)}:host([external]:not([external=false])) #icon{display:inline-block}</style><a><span id="content"></span><sinch-icon-open-in-new id="icon"></sinch-icon-open-in-new></a>';
13
+ 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;--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-aqua-400);outline-offset:2px}@supports not selector(:focus-visible){a:focus{outline:2px solid var(--sinch-color-aqua-400);outline-offset:2px}}#external-icon{display:none;margin-right:.2em;vertical-align:-.2em}#standalone-icon{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]):is([external=false],:not([external]))) #standalone-icon{display:inline-block;vertical-align:-7px;margin-left:8px}: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)}</style><a referrerpolicy="no-referer" aria-hidden="true"><sinch-icon-open-in-new id="external-icon"></sinch-icon-open-in-new><span id="content"></span><sinch-icon-arrow-forward id="standalone-icon"></sinch-icon-arrow-forward></a>';
13
14
  const template = document.createElement('template');
14
15
  template.innerHTML = templateHTML;
15
16
  defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMap(), _onAnchorClick = new WeakMap(), _onAnchorFocus = new WeakMap(), _onAnchorBlur = new WeakMap(), _onFocusReactHandler = new WeakMap(), _onBlurReactHandler = new WeakMap(), _onClickReactHandler = new WeakMap(), class extends NectaryElement {
@@ -81,6 +82,8 @@ defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMa
81
82
  }
82
83
 
83
84
  connectedCallback() {
85
+ this.setAttribute('role', 'link');
86
+
84
87
  _classPrivateFieldGet(this, _$anchor).addEventListener('click', _classPrivateFieldGet(this, _onAnchorClick));
85
88
 
86
89
  _classPrivateFieldGet(this, _$anchor).addEventListener('focus', _classPrivateFieldGet(this, _onAnchorFocus));
@@ -136,6 +139,14 @@ defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMa
136
139
  return getBooleanAttribute(this, 'external');
137
140
  }
138
141
 
142
+ set standalone(isstandalone) {
143
+ updateBooleanAttribute(this, 'standalone', isstandalone);
144
+ }
145
+
146
+ get standalone() {
147
+ return getBooleanAttribute(this, 'standalone');
148
+ }
149
+
139
150
  set preventDefault(isPrevented) {
140
151
  updateBooleanAttribute(this, 'preventdefault', isPrevented);
141
152
  }
@@ -145,10 +156,14 @@ defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMa
145
156
  }
146
157
 
147
158
  static get observedAttributes() {
148
- return ['text', 'href', 'external', 'disabled'];
159
+ return ['text', 'href', 'external'];
149
160
  }
150
161
 
151
- attributeChangedCallback(name, _, newVal) {
162
+ attributeChangedCallback(name, oldVal, newVal) {
163
+ if (oldVal === newVal) {
164
+ return;
165
+ }
166
+
152
167
  switch (name) {
153
168
  case 'text':
154
169
  {
@@ -156,12 +171,6 @@ defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMa
156
171
  break;
157
172
  }
158
173
 
159
- case 'disabled':
160
- {
161
- updateBooleanAttribute(this, 'disabled', isAttrTrue(newVal));
162
- break;
163
- }
164
-
165
174
  case 'href':
166
175
  {
167
176
  updateAttribute(_classPrivateFieldGet(this, _$anchor), 'href', newVal);
@@ -170,9 +179,7 @@ defineCustomElement('sinch-link', (_$anchor = new WeakMap(), _$text = new WeakMa
170
179
 
171
180
  case 'external':
172
181
  {
173
- const isExternal = isAttrTrue(newVal);
174
- updateAttribute(_classPrivateFieldGet(this, _$anchor), 'target', isExternal ? '_blank' : null);
175
- updateBooleanAttribute(this, 'external', isExternal);
182
+ updateAttribute(_classPrivateFieldGet(this, _$anchor), 'target', isAttrTrue(newVal) ? '_blank' : null);
176
183
  break;
177
184
  }
178
185
  }
package/link/types.d.ts CHANGED
@@ -1,26 +1,55 @@
1
1
  import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchLinkElement = HTMLElement & {
3
+ /** Text content of hyperlink */
3
4
  text: string;
5
+ /** URL that hyperlink point to */
4
6
  href: string;
7
+ /** Disabled */
5
8
  disabled: boolean;
9
+ /** Sets `target="_blank" and a special external icon on the left side */
6
10
  external: boolean;
11
+ /** Special standalone (`display: block`) mode with an arrow icon on the right side */
12
+ standalone: boolean;
13
+ /** Prevents default behaviour on hyperlink click */
7
14
  preventDefault: boolean;
15
+ /** Click event */
8
16
  addEventListener(type: '-click', listener: (e: CustomEvent<void>) => void): void;
17
+ /** Focus event */
9
18
  addEventListener(type: '-focus', listener: (e: CustomEvent<void>) => void): void;
19
+ /** Blur event */
10
20
  addEventListener(type: '-blur', listener: (e: CustomEvent<void>) => void): void;
21
+ /** Text content of hyperlink */
11
22
  setAttribute(name: 'text', value: string): void;
23
+ /** URL that hyperlink point to */
12
24
  setAttribute(name: 'href', value: string): void;
25
+ /** Disabled */
13
26
  setAttribute(name: 'disabled', value: ''): void;
27
+ /** Sets `target="_blank" and a special external icon on the left side */
14
28
  setAttribute(name: 'external', value: ''): void;
29
+ /** Special standalone (`display: block`) mode with an arrow icon on the right side */
30
+ setAttribute(name: 'standalone', value: ''): void;
31
+ /** Prevents default behaviour on hyperlink click */
15
32
  setAttribute(name: 'preventdefault', value: ''): void;
16
33
  };
17
34
  export declare type TSinchLinkReact = TSinchElementReact<TSinchLinkElement> & {
35
+ /** Text content of hyperlink */
18
36
  text: string;
37
+ /** URL that hyperlink point to */
19
38
  href: string;
39
+ /** Disabled */
20
40
  disabled?: boolean;
41
+ /** Sets `target="_blank" and a special external icon on the left side */
21
42
  external?: boolean;
43
+ /** Special standalone (`display: block`) mode with an arrow icon on the right side */
44
+ standalone?: boolean;
45
+ /** Prevents default behaviour on hyperlink click */
22
46
  preventDefault?: boolean;
47
+ /** Label that is used for a11y – might be different from `text` */
48
+ 'aria-label': string;
49
+ /** Click even handler */
23
50
  'on-click'?: (e: CustomEvent<void>) => void;
51
+ /** Focus even handler */
24
52
  'on-focus'?: (e: CustomEvent<void>) => void;
53
+ /** Blur even handler */
25
54
  'on-blur'?: (e: CustomEvent<void>) => void;
26
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "files": [
5
5
  "theme.css",
6
6
  "**/*/*.js",
@@ -11,7 +11,7 @@
11
11
  "colors.json"
12
12
  ],
13
13
  "scripts": {
14
- "build": "NODE_ENV=production babel . --extensions '.ts' --out-dir . && tsc"
14
+ "build": "NODE_ENV=production babel . --extensions '.ts' --out-dir . && tsc --declaration --emitDeclarationOnly"
15
15
  },
16
16
  "dependencies": {
17
17
  "@babel/runtime": "^7.17.0",
package/popover/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 _$target, _$dialog, _isConnected, _resizeThrottle, _prevOverflowValue, _onExpand, _onCollapse, _isOpen, _onResize, _updateOrientation, _updateOrientationModal, _onBackdropMouseDown, _onCancel, _onCloseReactHandler, _onTargetKeydown, _dispatchCloseEvent;
4
+ var _$target, _$dialog, _isConnected, _resizeThrottle, _originalOverflowValue, _$targetSlot, _$targetOpenSlot, _$targetOpenWrapper, _targetActiveElement, _onExpand, _onCollapse, _isOpen, _onResize, _updateOrientation, _onBackdropMouseDown, _onCancel, _onCloseReactHandler, _dispatchCloseEvent, _captureActiveElement, _stopPropagation;
5
5
 
6
6
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
7
 
@@ -13,12 +13,12 @@ function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(
13
13
 
14
14
  import dialogPolyfill from 'dialog-polyfill';
15
15
  import { defineCustomElement, getBooleanAttribute, getLiteralAttribute, getRect, isAttrTrue, updateLiteralAttribute, getReactEventHandler, updateBooleanAttribute, NectaryElement, throttleAnimationFrame } from '../utils';
16
- const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative}dialog{position:fixed;top:0;left:0;margin:0;outline:0;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:var(--sinch-elevation-level-2);border:1px solid var(--sinch-color-snow-500);border-radius:var(--sinch-popover-shape-radius,var(--sinch-shape-radius-l));contain:content;padding:0;box-sizing:border-box;max-width:unset;max-height:unset;z-index:1}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}#target{display:flex;flex-direction:column}</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>';
16
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle;outline:0}#wrapper{position:relative}dialog{position:fixed;top:0;left:0;margin:0;outline:0;padding:0;border:none;box-sizing:border-box;max-width:unset;max-height:unset;z-index:1;background:0 0;overflow:visible}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}#target{display:flex;flex-direction:column}#content{position:relative;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);box-shadow:var(--sinch-elevation-level-2);border:1px solid var(--sinch-color-snow-500);border-radius:var(--sinch-popover-shape-radius,var(--sinch-shape-radius-l));outline:0}#target-open{display:flex;flex-direction:column;position:absolute;left:0;top:0}</style><div id="wrapper"><div id="target" aria-haspopup="dialog" aria-expanded="false"><slot name="target"></slot></div><dialog id="dialog"><div id="target-open"><slot name="target-open"></slot></div><div id="content" tabindex="-1"><slot name="content"></slot></div></dialog></div>';
17
17
  import { orientationValues } from './utils';
18
18
  const template = document.createElement('template');
19
19
  template.innerHTML = templateHTML;
20
20
  const POPOVER_OFFSET = 4;
21
- defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new WeakMap(), _isConnected = new WeakMap(), _resizeThrottle = new WeakMap(), _prevOverflowValue = new WeakMap(), _onExpand = new WeakSet(), _onCollapse = new WeakSet(), _isOpen = new WeakSet(), _onResize = new WeakMap(), _updateOrientation = new WeakMap(), _updateOrientationModal = new WeakMap(), _onBackdropMouseDown = new WeakMap(), _onCancel = new WeakMap(), _onCloseReactHandler = new WeakMap(), _onTargetKeydown = new WeakMap(), _dispatchCloseEvent = new WeakSet(), class extends NectaryElement {
21
+ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new WeakMap(), _isConnected = new WeakMap(), _resizeThrottle = new WeakMap(), _originalOverflowValue = new WeakMap(), _$targetSlot = new WeakMap(), _$targetOpenSlot = new WeakMap(), _$targetOpenWrapper = new WeakMap(), _targetActiveElement = new WeakMap(), _onExpand = new WeakSet(), _onCollapse = new WeakSet(), _isOpen = new WeakSet(), _onResize = new WeakMap(), _updateOrientation = new WeakMap(), _onBackdropMouseDown = new WeakMap(), _onCancel = new WeakMap(), _onCloseReactHandler = new WeakMap(), _dispatchCloseEvent = new WeakSet(), _captureActiveElement = new WeakMap(), _stopPropagation = new WeakMap(), class extends NectaryElement {
22
22
  constructor() {
23
23
  super();
24
24
 
@@ -50,52 +50,39 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
50
50
  value: void 0
51
51
  });
52
52
 
53
- _classPrivateFieldInitSpec(this, _prevOverflowValue, {
53
+ _classPrivateFieldInitSpec(this, _originalOverflowValue, {
54
54
  writable: true,
55
55
  value: ''
56
56
  });
57
57
 
58
- _classPrivateFieldInitSpec(this, _onResize, {
58
+ _classPrivateFieldInitSpec(this, _$targetSlot, {
59
59
  writable: true,
60
- value: () => {
61
- _classPrivateFieldGet(this, _resizeThrottle).fn();
62
- }
60
+ value: void 0
63
61
  });
64
62
 
65
- _classPrivateFieldInitSpec(this, _updateOrientation, {
63
+ _classPrivateFieldInitSpec(this, _$targetOpenSlot, {
66
64
  writable: true,
67
- value: () => {
68
- _classPrivateFieldGet(this, _$dialog).style.width = 'max-content';
69
-
70
- const targetRect = _classPrivateFieldGet(this, _$target).getBoundingClientRect();
71
-
72
- const modalRect = _classPrivateFieldGet(this, _$dialog).getBoundingClientRect();
73
-
74
- let leftPos = 0;
75
- let topPos = 0;
76
- const orient = this.orientation;
77
- const shouldExpandWidthToTarget = orient === 'top' || orient === 'bottom';
78
- const resultWidth = shouldExpandWidthToTarget ? Math.max(modalRect.width, targetRect.width) : modalRect.width;
79
-
80
- if (orient === 'bottom-left' || orient === 'top-left') {
81
- leftPos = targetRect.width - resultWidth;
82
- }
65
+ value: void 0
66
+ });
83
67
 
84
- if (orient === 'bottom-left' || orient === 'bottom-right' || orient === 'bottom') {
85
- topPos = targetRect.height + POPOVER_OFFSET;
86
- }
68
+ _classPrivateFieldInitSpec(this, _$targetOpenWrapper, {
69
+ writable: true,
70
+ value: void 0
71
+ });
87
72
 
88
- if (orient === 'top-left' || orient === 'top-right' || orient === 'top') {
89
- topPos = -(modalRect.height + POPOVER_OFFSET);
90
- }
73
+ _classPrivateFieldInitSpec(this, _targetActiveElement, {
74
+ writable: true,
75
+ value: null
76
+ });
91
77
 
92
- _classPrivateFieldGet(this, _$dialog).style.left = `${leftPos}px`;
93
- _classPrivateFieldGet(this, _$dialog).style.top = `${topPos}px`;
94
- _classPrivateFieldGet(this, _$dialog).style.width = `${resultWidth}px`;
78
+ _classPrivateFieldInitSpec(this, _onResize, {
79
+ writable: true,
80
+ value: () => {
81
+ _classPrivateFieldGet(this, _resizeThrottle).fn();
95
82
  }
96
83
  });
97
84
 
98
- _classPrivateFieldInitSpec(this, _updateOrientationModal, {
85
+ _classPrivateFieldInitSpec(this, _updateOrientation, {
99
86
  writable: true,
100
87
  value: () => {
101
88
  _classPrivateFieldGet(this, _$dialog).style.width = 'max-content';
@@ -129,6 +116,13 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
129
116
  _classPrivateFieldGet(this, _$dialog).style.left = `${leftPos}px`;
130
117
  _classPrivateFieldGet(this, _$dialog).style.top = `${topPos}px`;
131
118
  _classPrivateFieldGet(this, _$dialog).style.width = `${resultWidth}px`;
119
+
120
+ if (!this.modal) {
121
+ const targetLeftPos = targetRect.left - leftPos;
122
+ const targetTopPos = targetRect.top - topPos;
123
+ _classPrivateFieldGet(this, _$targetOpenWrapper).style.left = `${targetLeftPos}px`;
124
+ _classPrivateFieldGet(this, _$targetOpenWrapper).style.top = `${targetTopPos}px`;
125
+ }
132
126
  }
133
127
  });
134
128
 
@@ -165,19 +159,19 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
165
159
  }
166
160
  });
167
161
 
168
- _classPrivateFieldInitSpec(this, _onTargetKeydown, {
162
+ _classPrivateFieldInitSpec(this, _captureActiveElement, {
169
163
  writable: true,
170
164
  value: e => {
171
- switch (e.key) {
172
- case 'Escape':
173
- {
174
- e.preventDefault();
165
+ e.stopPropagation();
175
166
 
176
- _classPrivateMethodGet(this, _dispatchCloseEvent, _dispatchCloseEvent2).call(this);
167
+ _classPrivateFieldSet(this, _targetActiveElement, e.target);
168
+ }
169
+ });
177
170
 
178
- break;
179
- }
180
- }
171
+ _classPrivateFieldInitSpec(this, _stopPropagation, {
172
+ writable: true,
173
+ value: e => {
174
+ e.stopPropagation();
181
175
  }
182
176
  });
183
177
 
@@ -188,11 +182,19 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
188
182
 
189
183
  _classPrivateFieldSet(this, _$dialog, shadowRoot.querySelector('#dialog'));
190
184
 
185
+ _classPrivateFieldSet(this, _$targetSlot, shadowRoot.querySelector('slot[name="target"]'));
186
+
187
+ _classPrivateFieldSet(this, _$targetOpenSlot, shadowRoot.querySelector('slot[name="target-open"]'));
188
+
189
+ _classPrivateFieldSet(this, _$targetOpenWrapper, shadowRoot.querySelector('#target-open'));
190
+
191
191
  _classPrivateFieldSet(this, _isConnected, false);
192
192
 
193
- _classPrivateFieldSet(this, _resizeThrottle, throttleAnimationFrame(_classPrivateFieldGet(this, _updateOrientationModal)));
193
+ _classPrivateFieldSet(this, _resizeThrottle, throttleAnimationFrame(_classPrivateFieldGet(this, _updateOrientation)));
194
194
 
195
195
  dialogPolyfill.registerDialog(_classPrivateFieldGet(this, _$dialog));
196
+
197
+ dialogPolyfill.dm.handleFocus_ = function () {};
196
198
  }
197
199
 
198
200
  connectedCallback() {
@@ -278,11 +280,7 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
278
280
  case 'orientation':
279
281
  {
280
282
  if (_classPrivateMethodGet(this, _isOpen, _isOpen2).call(this)) {
281
- if (this.modal) {
282
- _classPrivateFieldGet(this, _updateOrientationModal).call(this);
283
- } else {
284
- _classPrivateFieldGet(this, _updateOrientation).call(this);
285
- }
283
+ _classPrivateFieldGet(this, _updateOrientation).call(this);
286
284
  }
287
285
 
288
286
  break;
@@ -306,29 +304,50 @@ function _onExpand2() {
306
304
  return;
307
305
  }
308
306
 
309
- if (this.modal) {
310
- _classPrivateFieldGet(this, _$dialog).style.position = 'fixed';
307
+ const isNonModal = !this.modal;
308
+
309
+ _classPrivateFieldGet(this, _$targetSlot).addEventListener('blur', _classPrivateFieldGet(this, _stopPropagation), true);
310
+
311
+ if (isNonModal) {
312
+ _classPrivateFieldGet(this, _$targetOpenSlot).addEventListener('blur', _classPrivateFieldGet(this, _captureActiveElement), true);
313
+
314
+ const targetRect = _classPrivateFieldGet(this, _$target).getBoundingClientRect();
311
315
 
312
- _classPrivateFieldGet(this, _$dialog).showModal();
316
+ const widthPx = `${targetRect.width}px`;
317
+ const heightPx = `${targetRect.height}px`;
318
+ _classPrivateFieldGet(this, _$target).style.width = widthPx;
319
+ _classPrivateFieldGet(this, _$target).style.height = heightPx;
320
+ _classPrivateFieldGet(this, _$targetOpenWrapper).style.width = widthPx;
321
+ _classPrivateFieldGet(this, _$targetOpenWrapper).style.height = heightPx;
322
+ _classPrivateFieldGet(this, _$targetSlot).assignedElements()[0]?.setAttribute('slot', 'target-open');
323
+ }
324
+
325
+ _classPrivateFieldGet(this, _$dialog).showModal();
313
326
 
314
- _classPrivateFieldGet(this, _updateOrientationModal).call(this);
327
+ _classPrivateFieldGet(this, _updateOrientation).call(this);
315
328
 
316
- _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'true');
329
+ _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'true');
317
330
 
318
- _classPrivateFieldSet(this, _prevOverflowValue, document.body.style.overflow);
331
+ _classPrivateFieldGet(this, _$targetSlot).removeEventListener('blur', _classPrivateFieldGet(this, _stopPropagation), true);
319
332
 
320
- document.body.style.overflow = 'hidden';
321
- window.addEventListener('resize', _classPrivateFieldGet(this, _onResize));
322
- } else {
323
- this.addEventListener('keydown', _classPrivateFieldGet(this, _onTargetKeydown));
324
- _classPrivateFieldGet(this, _$dialog).style.position = 'absolute';
333
+ if (isNonModal) {
334
+ _classPrivateFieldGet(this, _$targetOpenSlot).removeEventListener('blur', _classPrivateFieldGet(this, _captureActiveElement), true);
325
335
 
326
- _classPrivateFieldGet(this, _$dialog).setAttribute('open', '');
336
+ if (_classPrivateFieldGet(this, _targetActiveElement) !== null) {
337
+ requestAnimationFrame(() => {
338
+ _classPrivateFieldGet(this, _$targetOpenSlot).addEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
327
339
 
328
- _classPrivateFieldGet(this, _updateOrientation).call(this);
340
+ _classPrivateFieldGet(this, _targetActiveElement)?.focus();
329
341
 
330
- _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'true');
342
+ _classPrivateFieldGet(this, _$targetOpenSlot).removeEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
343
+ });
344
+ }
331
345
  }
346
+
347
+ _classPrivateFieldSet(this, _originalOverflowValue, document.body.style.overflow);
348
+
349
+ document.body.style.overflow = 'hidden';
350
+ window.addEventListener('resize', _classPrivateFieldGet(this, _onResize));
332
351
  }
333
352
 
334
353
  function _onCollapse2() {
@@ -336,20 +355,33 @@ function _onCollapse2() {
336
355
  return;
337
356
  }
338
357
 
339
- if (this.modal) {
340
- _classPrivateFieldGet(this, _$dialog).close?.();
341
- } else {
342
- _classPrivateFieldGet(this, _$dialog).removeAttribute('open');
358
+ _classPrivateFieldGet(this, _$targetSlot).addEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
359
+
360
+ if (_classPrivateFieldGet(this, _targetActiveElement) !== null) {
361
+ _classPrivateFieldGet(this, _$targetOpenSlot).addEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
362
+
363
+ _classPrivateFieldGet(this, _targetActiveElement).focus();
364
+
365
+ _classPrivateFieldSet(this, _targetActiveElement, null);
366
+
367
+ _classPrivateFieldGet(this, _$targetOpenSlot).removeEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
343
368
  }
344
369
 
370
+ _classPrivateFieldGet(this, _$targetOpenSlot).assignedElements()[0]?.setAttribute('slot', 'target');
371
+ _classPrivateFieldGet(this, _$target).style.width = 'unset';
372
+ _classPrivateFieldGet(this, _$target).style.height = 'unset';
373
+
374
+ _classPrivateFieldGet(this, _$dialog).close();
375
+
345
376
  _classPrivateFieldGet(this, _$target).setAttribute('aria-expanded', 'false');
346
377
 
347
- document.body.style.overflow = _classPrivateFieldGet(this, _prevOverflowValue);
378
+ _classPrivateFieldGet(this, _$targetSlot).removeEventListener('focus', _classPrivateFieldGet(this, _stopPropagation), true);
379
+
380
+ document.body.style.overflow = _classPrivateFieldGet(this, _originalOverflowValue);
348
381
 
349
382
  _classPrivateFieldGet(this, _resizeThrottle).cancel();
350
383
 
351
384
  window.removeEventListener('resize', _classPrivateFieldGet(this, _onResize));
352
- this.removeEventListener('keydown', _classPrivateFieldGet(this, _onTargetKeydown));
353
385
  }
354
386
 
355
387
  function _isOpen2() {
package/search/index.js CHANGED
@@ -12,7 +12,7 @@ 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 { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getRect, NectaryElement, updateAttribute, updateBooleanAttribute, updateIntegerAttribute } from '../utils';
15
- 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:var(--sinch-shape-radius-s);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:var(--sinch-elevation-level-2);overflow-y:auto}: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>';
15
+ 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:var(--sinch-shape-radius-s);width:100%;height:48px;padding:0 44px;padding-right:12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100)}#input::placeholder{font:var(--sinch-font-body);color:var(--sinch-color-text-muted);opacity:1}#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:var(--sinch-elevation-level-2);overflow-y:auto}: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
16
  import '../icons/search';
17
17
  import '../icons/close';
18
18
  import '../icon-button';
package/select/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import '../dropdown';
2
+ import '../icons/keyboard-arrow-down';
2
3
  import type { TSinchSelectElement, TSinchSelectReact } from './types';
3
4
  declare global {
4
5
  namespace JSX {
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, _$sh, _createElement, _updateButtonContent, _onValueChange, _getOptionWithValue, _onLabelClick, _onDropdownClick, _onDropdownClose, _onButtonFocus, _onButtonBlur, _onChangeReactHandler, _onFocusReactHandler, _onBlurReactHandler;
4
+ var _$button, _$buttonContent, _$dropdown, _$optionSlot, _$sh, _createElement, _updateButtonContent, _onValueChange, _getOptionWithValue, _onDropdownClick, _onDropdownClose, _onButtonFocus, _onButtonBlur, _onChangeReactHandler, _onFocusReactHandler, _onBlurReactHandler;
5
5
 
6
6
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
7
7
 
@@ -12,11 +12,12 @@ 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 '../dropdown';
15
+ import '../icons/keyboard-arrow-down';
15
16
  import { defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute } from '../utils';
16
- 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:var(--sinch-shape-radius-s);box-sizing:border-box;width:100%;height:48px;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;margin-bottom:2px}#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);line-height:20px;margin-top:2px}#additional:empty{display:none}#invalid{font:var(--sinch-font-extra-small-text);color:var(--sinch-color-text-invalid);line-height:20px;margin-top:2px}#invalid:empty{display:none}::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="button"></label><slot name="tooltip"></slot><span id="optional"></span></div><sinch-dropdown id="dropdown" modal orientation="bottom"><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>';
17
+ const templateHTML = '<style>:host{display:inline-block;vertical-align:middle}#dropdown{display:block;width:100%}#button{all:initial;display:flex;align-items:center;gap:8px;border:1px solid var(--sinch-color-stormy-200);border-radius:var(--sinch-shape-radius-s);box-sizing:border-box;width:100%;height:48px;padding:0 12px;font:var(--sinch-font-body);color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-100);cursor:pointer;--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:24px}#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([invalid]:not([invalid=false])) #button:enabled{border-color:var(--sinch-color-text-invalid)}#content{flex:1;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host([disabled]:not([disabled=false])) #button{--sinch-color-icon:var(--sinch-color-stormy-100)}</style><sinch-dropdown id="dropdown" orientation="bottom"><button slot="target" id="button"><span id="content"></span><sinch-icon-keyboard-arrow-down id="dropdown-icon"></sinch-icon-keyboard-arrow-down></button><slot name="option" slot="option"></slot></sinch-dropdown>';
17
18
  const template = document.createElement('template');
18
19
  template.innerHTML = templateHTML;
19
- 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(), _$sh = new WeakMap(), _createElement = new WeakSet(), _updateButtonContent = new WeakSet(), _onValueChange = new WeakMap(), _getOptionWithValue = new WeakSet(), _onLabelClick = new WeakMap(), _onDropdownClick = new WeakMap(), _onDropdownClose = new WeakMap(), _onButtonFocus = new WeakMap(), _onButtonBlur = new WeakMap(), _onChangeReactHandler = new WeakMap(), _onFocusReactHandler = new WeakMap(), _onBlurReactHandler = new WeakMap(), class extends NectaryElement {
20
+ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent = new WeakMap(), _$dropdown = new WeakMap(), _$optionSlot = new WeakMap(), _$sh = new WeakMap(), _createElement = new WeakSet(), _updateButtonContent = new WeakSet(), _onValueChange = new WeakMap(), _getOptionWithValue = new WeakSet(), _onDropdownClick = new WeakMap(), _onDropdownClose = new WeakMap(), _onButtonFocus = new WeakMap(), _onButtonBlur = new WeakMap(), _onChangeReactHandler = new WeakMap(), _onFocusReactHandler = new WeakMap(), _onBlurReactHandler = new WeakMap(), class extends NectaryElement {
20
21
  constructor() {
21
22
  super();
22
23
 
@@ -36,26 +37,6 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
36
37
  value: void 0
37
38
  });
38
39
 
39
- _classPrivateFieldInitSpec(this, _$label, {
40
- writable: true,
41
- value: void 0
42
- });
43
-
44
- _classPrivateFieldInitSpec(this, _$optionalText, {
45
- writable: true,
46
- value: void 0
47
- });
48
-
49
- _classPrivateFieldInitSpec(this, _$additionalText, {
50
- writable: true,
51
- value: void 0
52
- });
53
-
54
- _classPrivateFieldInitSpec(this, _$invalidText, {
55
- writable: true,
56
- value: void 0
57
- });
58
-
59
40
  _classPrivateFieldInitSpec(this, _$dropdown, {
60
41
  writable: true,
61
42
  value: void 0
@@ -86,13 +67,6 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
86
67
  }
87
68
  });
88
69
 
89
- _classPrivateFieldInitSpec(this, _onLabelClick, {
90
- writable: true,
91
- value: () => {
92
- this.focus();
93
- }
94
- });
95
-
96
70
  _classPrivateFieldInitSpec(this, _onDropdownClick, {
97
71
  writable: true,
98
72
  value: () => {
@@ -151,15 +125,7 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
151
125
 
152
126
  _classPrivateFieldSet(this, _$buttonContent, shadowRoot.querySelector('#content'));
153
127
 
154
- _classPrivateFieldSet(this, _$label, shadowRoot.querySelector('#label'));
155
-
156
- _classPrivateFieldSet(this, _$optionalText, shadowRoot.querySelector('#optional'));
157
-
158
- _classPrivateFieldSet(this, _$additionalText, shadowRoot.querySelector('#additional'));
159
-
160
- _classPrivateFieldSet(this, _$invalidText, shadowRoot.querySelector('#invalid'));
161
-
162
- _classPrivateFieldSet(this, _$dropdown, shadowRoot.querySelector('sinch-dropdown'));
128
+ _classPrivateFieldSet(this, _$dropdown, shadowRoot.querySelector('#dropdown'));
163
129
 
164
130
  _classPrivateFieldSet(this, _$optionSlot, shadowRoot.querySelector('slot[name="option"]'));
165
131
  }
@@ -178,8 +144,6 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
178
144
 
179
145
  _classPrivateFieldGet(this, _$button).addEventListener('blur', _classPrivateFieldGet(this, _onButtonBlur));
180
146
 
181
- _classPrivateFieldGet(this, _$label).addEventListener('click', _classPrivateFieldGet(this, _onLabelClick));
182
-
183
147
  this.addEventListener('-change', _classPrivateFieldGet(this, _onChangeReactHandler));
184
148
  this.addEventListener('-focus', _classPrivateFieldGet(this, _onFocusReactHandler));
185
149
  this.addEventListener('-blur', _classPrivateFieldGet(this, _onBlurReactHandler));
@@ -196,15 +160,13 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
196
160
 
197
161
  _classPrivateFieldGet(this, _$button).removeEventListener('blur', _classPrivateFieldGet(this, _onButtonBlur));
198
162
 
199
- _classPrivateFieldGet(this, _$label).removeEventListener('click', _classPrivateFieldGet(this, _onLabelClick));
200
-
201
163
  this.removeEventListener('-change', _classPrivateFieldGet(this, _onChangeReactHandler));
202
164
  this.removeEventListener('-focus', _classPrivateFieldGet(this, _onFocusReactHandler));
203
165
  this.removeEventListener('-blur', _classPrivateFieldGet(this, _onBlurReactHandler));
204
166
  }
205
167
 
206
168
  static get observedAttributes() {
207
- return ['value', 'label', 'placeholder', 'optionaltext', 'additionaltext', 'invalidtext', 'disabled', 'maxvisibleitems'];
169
+ return ['value', 'placeholder', 'invalid', 'disabled', 'maxvisibleitems'];
208
170
  }
209
171
 
210
172
  get nodeName() {
@@ -227,36 +189,12 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
227
189
  return getAttribute(this, 'placeholder', null);
228
190
  }
229
191
 
230
- set label(value) {
231
- updateAttribute(this, 'label', value);
232
- }
233
-
234
- get label() {
235
- return getAttribute(this, 'label', '');
236
- }
237
-
238
- set optionalText(value) {
239
- updateAttribute(this, 'optionaltext', value);
240
- }
241
-
242
- get optionalText() {
243
- return getAttribute(this, 'optionaltext', null);
244
- }
245
-
246
- set additionalText(value) {
247
- updateAttribute(this, 'additionaltext', value);
248
- }
249
-
250
- get additionalText() {
251
- return getAttribute(this, 'additionaltext', null);
252
- }
253
-
254
- set invalidText(value) {
255
- updateAttribute(this, 'invalidtext', value);
192
+ set invalid(value) {
193
+ updateBooleanAttribute(this, 'invalid', value);
256
194
  }
257
195
 
258
- get invalidText() {
259
- return getAttribute(this, 'placeholder', null);
196
+ get invalid() {
197
+ return getBooleanAttribute(this, 'invalid');
260
198
  }
261
199
 
262
200
  set disabled(isDisabled) {
@@ -303,29 +241,9 @@ defineCustomElement('sinch-select', (_$button = new WeakMap(), _$buttonContent =
303
241
  break;
304
242
  }
305
243
 
306
- case 'label':
307
- {
308
- _classPrivateFieldGet(this, _$label).textContent = newVal;
309
- break;
310
- }
311
-
312
- case 'optionaltext':
313
- {
314
- _classPrivateFieldGet(this, _$optionalText).textContent = newVal;
315
- break;
316
- }
317
-
318
- case 'additionaltext':
319
- {
320
- _classPrivateFieldGet(this, _$additionalText).textContent = newVal;
321
- break;
322
- }
323
-
324
- case 'invalidtext':
244
+ case 'invalid':
325
245
  {
326
- const isInvalid = newVal !== null && newVal !== '';
327
- _classPrivateFieldGet(this, _$invalidText).textContent = newVal;
328
- updateExplicitBooleanAttribute(this, 'aria-invalid', isInvalid);
246
+ updateExplicitBooleanAttribute(this, 'aria-invalid', isAttrTrue(newVal));
329
247
  break;
330
248
  }
331
249