@nectary/components 0.31.0 → 0.32.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.
@@ -6,8 +6,6 @@ export declare type TSinchAccordionItemElement = HTMLElement & {
6
6
  optionalText: string | null;
7
7
  disabled: boolean;
8
8
  status: TSinchAccordionStatusType | null;
9
- focus(): void;
10
- blur(): void;
11
9
  setAttribute(name: 'value', value: string): void;
12
10
  setAttribute(name: 'label', value: string): void;
13
11
  setAttribute(name: 'optionaltext', value: string): void;
@@ -2,8 +2,6 @@ import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchActionMenuOptionElement = HTMLElement & {
3
3
  text: string;
4
4
  disabled: boolean;
5
- focus(): void;
6
- blur(): void;
7
5
  setAttribute(name: 'text', value: string): void;
8
6
  setAttribute(name: 'disabled', value: ''): void;
9
7
  };
@@ -1,8 +1,6 @@
1
1
  import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchAlertButtonElement = HTMLElement & {
3
3
  text: string;
4
- focus(): void;
5
- blur(): void;
6
4
  setAttribute(name: 'text', value: string): void;
7
5
  };
8
6
  export declare type TSinchAlertButtonReact = TSinchElementReact<TSinchAlertButtonElement> & {
@@ -1,6 +1,3 @@
1
1
  import type { TSinchElementReact } from '../types';
2
- export declare type TSinchAlertCloseElement = HTMLElement & {
3
- focus(): void;
4
- blur(): void;
5
- };
2
+ export declare type TSinchAlertCloseElement = HTMLElement;
6
3
  export declare type TSinchAlertCloseReact = TSinchElementReact<TSinchAlertCloseElement>;
package/button/types.d.ts CHANGED
@@ -9,8 +9,6 @@ export declare type TSinchButtonElement = HTMLElement & {
9
9
  disabled: boolean;
10
10
  /** Small */
11
11
  small: boolean;
12
- focus(): void;
13
- blur(): void;
14
12
  /** Type */
15
13
  setAttribute(attr: 'type', value: TSinchButtonType): void;
16
14
  /** Text content */
@@ -2,8 +2,6 @@ import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchCardButtonElement = HTMLElement & {
3
3
  text: string;
4
4
  disabled: boolean;
5
- focus(): void;
6
- blur(): void;
7
5
  setAttribute(name: 'text', value: string): void;
8
6
  setAttribute(name: 'disabled', value: ''): void;
9
7
  };
@@ -3,8 +3,6 @@ export declare type TSinchCardLinkElement = HTMLElement & {
3
3
  text: string;
4
4
  href: string;
5
5
  disabled: boolean;
6
- focus(): void;
7
- blur(): void;
8
6
  setAttribute(name: 'text', value: string): void;
9
7
  setAttribute(name: 'href', value: string): void;
10
8
  setAttribute(name: 'disabled', value: ''): void;
@@ -6,8 +6,6 @@ export declare type TSinchCheckboxElement = HTMLElement & {
6
6
  disabled: boolean;
7
7
  invalid: boolean;
8
8
  text: string | null;
9
- focus(): void;
10
- blur(): void;
11
9
  addEventListener(type: 'change', listener: (e: CustomEvent<boolean>) => void): void;
12
10
  setAttribute(name: 'checked', value: ''): void;
13
11
  setAttribute(name: 'indeterminate', value: ''): void;
@@ -20,7 +20,7 @@ import '../icons/delete-outline';
20
20
  import '../icons/today';
21
21
  import '../text';
22
22
  import { defineCustomElement, getAttribute, getRect, NectaryElement, setClass, updateAttribute, updateBooleanAttribute } from '../utils';
23
- const templateHTML = '<style>:host{display:block;outline:0}#content{width:fit-content;box-sizing:border-box;padding:16px;display:flex;flex-direction:column;gap:8px}#month{display:flex;flex-direction:column;row-gap:8px}.week{display:flex;flex-direction:row;column-gap:8px}.week.empty{display:none}.day{all:initial;font:var(--sinch-font-text-xs);color:var(--sinch-color-text-default);text-align:center;border-radius:var(--sinch-shape-radius-m);width:24px;height:24px;line-height:22px;cursor:pointer;border:1px solid transparent;background-color:transparent;box-sizing:border-box;user-select:none}.day.today{border:1px solid var(--sinch-color-stormy-500)}.day:disabled{cursor:initial;color:var(--sinch-color-snow-700)}.day:focus-visible{outline:1px solid var(--sinch-color-aqua-400);outline-offset:1px}@supports not selector(:focus-visible){.day:focus{outline:1px solid var(--sinch-color-aqua-400);outline-offset:1px}}.day.selected{background-color:var(--sinch-color-stormy-500);color:var(--sinch-color-snow-100)}.day:hover:not(:disabled):not(.selected){background-color:var(--sinch-color-snow-600)}#week-day-names{display:flex;flex-direction:row;gap:8px;height:24px}.week-day-name{font:var(--sinch-font-text-xs);font-weight:var(--sinch-font-weight-emphasized);color:var(--sinch-color-text-default);text-align:center;width:24px;height:24px;line-height:24px;user-select:none;text-transform:uppercase}#content-header{display:flex;flex-direction:row;height:32px;align-items:center}#date{flex:1;text-align:center;text-transform:capitalize}#prev-year{margin-left:-4px}#next-year{margin-right:-4px}</style><div id="content" slot="content"><div id="content-header"><sinch-icon-button small id="prev-year"><sinch-icon-keyboard-double-arrow-left slot="icon"></sinch-icon-keyboard-double-arrow-left></sinch-icon-button><sinch-icon-button small id="prev-month"><sinch-icon-keyboard-arrow-left slot="icon"></sinch-icon-keyboard-arrow-left></sinch-icon-button><sinch-text type="m" emphasized id="date"></sinch-text><sinch-icon-button small id="next-month"><sinch-icon-keyboard-arrow-right slot="icon"></sinch-icon-keyboard-arrow-right></sinch-icon-button><sinch-icon-button small id="next-year"><sinch-icon-keyboard-double-arrow-right slot="icon"></sinch-icon-keyboard-double-arrow-right></sinch-icon-button></div><div id="week-day-names"><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div></div><div id="month"><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div></div></div>';
23
+ const templateHTML = '<style>:host{display:block;outline:0}#content{width:fit-content;box-sizing:border-box;padding:16px;display:flex;flex-direction:column;gap:8px}#month{display:flex;flex-direction:column;row-gap:8px}.week{display:flex;flex-direction:row;column-gap:8px}.week.empty{display:none}.day{all:initial;font:var(--sinch-font-text-xs);color:var(--sinch-color-text-default);text-align:center;border-radius:var(--sinch-shape-radius-m);width:24px;height:24px;line-height:22px;cursor:pointer;border:1px solid transparent;background-color:transparent;box-sizing:border-box;user-select:none}.day.today{border:1px solid var(--sinch-color-stormy-500)}.day:disabled{cursor:initial;color:var(--sinch-color-snow-700)}.day:focus-visible{outline:1px solid var(--sinch-color-aqua-400);outline-offset:1px}@supports not selector(:focus-visible){.day:focus{outline:1px solid var(--sinch-color-aqua-400);outline-offset:1px}}.day.selected{background-color:var(--sinch-color-stormy-500);color:var(--sinch-color-snow-100)}.day:hover:not(:disabled):not(.selected){background-color:var(--sinch-color-snow-600)}#week-day-names{display:flex;flex-direction:row;gap:8px;height:24px}.week-day-name{font:var(--sinch-font-text-xs);font-weight:var(--sinch-font-weight-emphasized);color:var(--sinch-color-text-default);text-align:center;width:24px;height:24px;line-height:24px;user-select:none;text-transform:uppercase}#content-header{display:flex;flex-direction:row;height:32px;align-items:center}#date{flex:1;text-align:center;text-transform:capitalize}#prev-year{margin-left:-4px}#next-year{margin-right:-4px}</style><div id="content"><div id="content-header"><sinch-icon-button small id="prev-year"><sinch-icon-keyboard-double-arrow-left slot="icon"></sinch-icon-keyboard-double-arrow-left></sinch-icon-button><sinch-icon-button small id="prev-month"><sinch-icon-keyboard-arrow-left slot="icon"></sinch-icon-keyboard-arrow-left></sinch-icon-button><sinch-text type="m" emphasized id="date"></sinch-text><sinch-icon-button small id="next-month"><sinch-icon-keyboard-arrow-right slot="icon"></sinch-icon-keyboard-arrow-right></sinch-icon-button><sinch-icon-button small id="next-year"><sinch-icon-keyboard-double-arrow-right slot="icon"></sinch-icon-keyboard-double-arrow-right></sinch-icon-button></div><div id="week-day-names"><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div><div class="week-day-name"></div></div><div id="month"><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div><div class="week"><button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button> <button class="day"></button></div></div></div>';
24
24
  import { areDatesEqual, assertDate, assertLocale, assertMinMax, assertValue, canGoNextMonth, canGoNextYear, canGoPrevMonth, canGoPrevYear, clampMaxDate, clampMinDate, dateToIso, decMonth, decYear, getCalendarMonth, getDayNames, getMonthNames, incMonth, incYear, isDateBetween, isoToDate, isValidDate, today } from './utils';
25
25
  const template = document.createElement('template');
26
26
  template.innerHTML = templateHTML;
@@ -1,26 +1,41 @@
1
1
  import type { TRect, TSinchElementReact } from '../types';
2
2
  import type { SyntheticEvent } from 'react';
3
3
  export declare type TSinchDatePickerElement = HTMLElement & {
4
+ /** Date value in ISO 8601 format */
4
5
  value: string;
6
+ /** Date min limit in ISO 8601 format */
5
7
  min: string;
8
+ /** Date max limit in ISO 8601 format */
6
9
  max: string;
10
+ /** BCP 47 language tag (e.g. en-US), which changes day and month display names in the calendar */
7
11
  locale: string;
8
12
  readonly prevYearButtonRect: TRect;
9
13
  readonly nextYearButtonRect: TRect;
10
14
  readonly prevMonthButtonRect: TRect;
11
15
  readonly nextMonthButtonRect: TRect;
12
16
  nthButtonRect(index: number): TRect | null;
17
+ /** Change value handler, return date in ISO 8601 format */
13
18
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
19
+ /** Date value in ISO 8601 format */
14
20
  setAttribute(name: 'value', value: string): void;
21
+ /** Date min limit in ISO 8601 format */
15
22
  setAttribute(name: 'min', value: string): void;
23
+ /** Date max limit in ISO 8601 format */
16
24
  setAttribute(name: 'max', value: string): void;
25
+ /** BCP 47 language tag (e.g. en-US), which changes day and month display names in the calendar */
17
26
  setAttribute(name: 'locale', value: string): void;
18
27
  };
19
28
  export declare type TSinchDatePickerReact = TSinchElementReact<TSinchDatePickerElement> & {
20
- locale: string;
29
+ /** Date value in ISO 8601 format */
21
30
  value: string;
31
+ /** Date min limit in ISO 8601 format */
22
32
  min: string;
33
+ /** Date max limit in ISO 8601 format */
23
34
  max: string;
35
+ /** BCP 47 language tag (e.g. en-US), which changes day and month display names in the calendar */
36
+ locale: string;
37
+ /** Label that is used for a11y */
24
38
  'aria-label': string;
39
+ /** Change value handler, return date in ISO 8601 format */
25
40
  onChange: (e: SyntheticEvent<TSinchDatePickerElement, CustomEvent<string>>) => void;
26
41
  };
package/dialog/index.js CHANGED
@@ -144,7 +144,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
144
144
 
145
145
  this.addEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
146
146
 
147
- _classPrivateFieldGet(this, _$dialog).addEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
147
+ _classPrivateFieldGet(this, _$dialog).addEventListener('mousedown', _classPrivateFieldGet(this, _onBackdropClick));
148
148
 
149
149
  _classPrivateFieldGet(this, _$dialog).addEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
150
150
 
@@ -160,7 +160,7 @@ defineCustomElement('sinch-dialog', (_$dialog = new WeakMap(), _$closeButton = n
160
160
 
161
161
  this.removeEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
162
162
 
163
- _classPrivateFieldGet(this, _$dialog).removeEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
163
+ _classPrivateFieldGet(this, _$dialog).removeEventListener('mousedown', _classPrivateFieldGet(this, _onBackdropClick));
164
164
 
165
165
  _classPrivateFieldGet(this, _$dialog).removeEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
166
166
 
@@ -8,8 +8,6 @@ export declare type TSinchDropdownElement = HTMLElement & {
8
8
  value: string;
9
9
  maxVisibleItems: number | null;
10
10
  readonly dropdownRect: TRect;
11
- focus(): void;
12
- blur(): void;
13
11
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
14
12
  addEventListener(type: 'close', listener: (e: CustomEvent<void>) => void): void;
15
13
  setAttribute(name: 'open', value: ''): void;
@@ -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, NectaryElement, 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:var(--sinch-shape-radius-s);border:1px solid transparent;background-color:transparent;cursor:pointer;--sinch-size-icon:24px;--sinch-color-icon:var(--sinch-icon-button-color, var(--sinch-color-stormy-500))}button:focus{border-color:var(--sinch-color-stormy-500)}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;position:relative;display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:48px;height:48px;border-radius:var(--sinch-shape-radius-s);border:1px solid transparent;background-color:transparent;cursor:pointer;--sinch-size-icon:24px;--sinch-color-icon:var(--sinch-icon-button-color, var(--sinch-color-stormy-500))}button:focus-visible::before{position:absolute;content:"";left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;padding:2px;border:1px solid var(--sinch-color-aqua-400);border-radius:calc(var(--sinch-shape-radius-s) + 2px)}@supports not selector(:focus-visible){button:focus::before{position:absolute;content:"";left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;padding:2px;border:1px solid var(--sinch-color-aqua-400);border-radius:calc(var(--sinch-shape-radius-s) + 2px)}}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 NectaryElement {
@@ -2,8 +2,6 @@ import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchIconButtonElement = HTMLElement & {
3
3
  disabled: boolean;
4
4
  small: boolean;
5
- focus(): void;
6
- blur(): void;
7
5
  setAttribute(name: 'disabled', value: ''): void;
8
6
  setAttribute(name: 'small', value: ''): void;
9
7
  };
package/input/types.d.ts CHANGED
@@ -21,8 +21,6 @@ export declare type TSinchInputElement = HTMLElement & {
21
21
  selectionStart: number | null;
22
22
  selectionEnd: number | null;
23
23
  selectionDirection: 'forward' | 'backward' | 'none' | null;
24
- focus(): void;
25
- blur(): void;
26
24
  /** Change value event */
27
25
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
28
26
  /** Text field type, `text` by default */
package/link/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import '../icons/cancel';
1
+ import '../icons/open-in-new';
2
2
  import type { TSinchLinkElement, TSinchLinkReact } from './types';
3
3
  declare global {
4
4
  namespace JSX {
package/link/index.js CHANGED
@@ -7,7 +7,7 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
7
7
 
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
- import '../icons/cancel';
10
+ import '../icons/open-in-new';
11
11
  import { defineCustomElement, getBooleanAttribute, getAttribute, updateBooleanAttribute, updateAttribute, NectaryElement, isAttrTrue } from '../utils';
12
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
13
  const template = document.createElement('template');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "files": [
5
5
  "theme.css",
6
6
  "**/*/*.js",
@@ -3,8 +3,6 @@ import type { SyntheticEvent } from 'react';
3
3
  export declare type TSinchPaginationElement = HTMLElement & {
4
4
  value: number;
5
5
  max: number;
6
- focus(): void;
7
- blur(): void;
8
6
  readonly prevButtonRect: TRect;
9
7
  readonly nextButtonRect: TRect;
10
8
  nthButtonRect(index: number): TRect | null;
package/popover/index.js CHANGED
@@ -153,7 +153,7 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
153
153
 
154
154
  _classPrivateFieldGet(this, _$dialog).addEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
155
155
 
156
- _classPrivateFieldGet(this, _$dialog).addEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
156
+ _classPrivateFieldGet(this, _$dialog).addEventListener('mousedown', _classPrivateFieldGet(this, _onBackdropClick));
157
157
 
158
158
  this.addEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
159
159
 
@@ -169,7 +169,7 @@ defineCustomElement('sinch-popover', (_$target = new WeakMap(), _$dialog = new W
169
169
  disconnectedCallback() {
170
170
  _classPrivateFieldGet(this, _$dialog).removeEventListener('cancel', _classPrivateFieldGet(this, _onCancel));
171
171
 
172
- _classPrivateFieldGet(this, _$dialog).removeEventListener('click', _classPrivateFieldGet(this, _onBackdropClick));
172
+ _classPrivateFieldGet(this, _$dialog).removeEventListener('mousedown', _classPrivateFieldGet(this, _onBackdropClick));
173
173
 
174
174
  this.removeEventListener('close', _classPrivateFieldGet(this, _onCloseReactHandler));
175
175
 
@@ -4,8 +4,6 @@ export declare type TSinchRadioOptionElement = HTMLElement & {
4
4
  checked: boolean;
5
5
  disabled: boolean;
6
6
  text: string;
7
- focus(): void;
8
- blur(): void;
9
7
  setAttribute(name: 'value', value: string): void;
10
8
  setAttribute(name: 'checked', value: ''): void;
11
9
  setAttribute(name: 'disabled', value: ''): void;
package/search/types.d.ts CHANGED
@@ -9,8 +9,6 @@ export declare type TSinchSearchElement = HTMLElement & {
9
9
  selectionEnd: HTMLInputElement['selectionEnd'];
10
10
  selectionDirection: HTMLInputElement['selectionDirection'];
11
11
  readonly dropdownRect: TRect;
12
- focus(): void;
13
- blur(): void;
14
12
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
15
13
  setAttribute(name: 'value', value: string): void;
16
14
  setAttribute(name: 'label', value: string): void;
package/segment/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 _$caption, _$previewSlot, _$previewWrapper, _$infoSlot, _$infoWrapper, _$collapseSlot, _$collapseWrapper, _onPreviewSlotChange, _onInfoSlotChange, _onCollapseSlotChange;
4
+ var _$caption, _$previewSlot, _$previewWrapper, _$infoSlot, _$infoWrapper, _$collapseSlot, _$collapseWrapper, _$actionSlot, _$actionWrapper, _onPreviewSlotChange, _onInfoSlotChange, _onCollapseSlotChange, _onActionSlotChange;
5
5
 
6
6
  function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
7
7
 
@@ -10,11 +10,11 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
10
10
  import '../title';
11
11
  import { getTitleLevelFromType } from '../title/utils';
12
12
  import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, getRect, isAttrTrue, NectaryElement, setClass, updateAttribute, updateBooleanAttribute, updateLiteralAttribute } from '../utils';
13
- const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;gap:16px;width:100%;height:100%;border:1px solid var(--sinch-color-snow-700);border-radius:var(--sinch-shape-radius-l);box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);box-shadow:var(--sinch-elevation-level-2);padding:8px 24px 16px}#header{display:flex;flex-direction:row;align-items:center;height:48px;gap:8px;--sinch-size-icon:32px}#caption{font:var(--sinch-font-title-l);color:var(--sinch-color-text-default);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:1em}#info{display:flex;flex-direction:row;align-items:center;gap:8px;margin-left:auto;align-self:stretch}#info.empty{display:none}#preview{flex:1;flex-basis:auto;height:48px;min-width:0;overflow:hidden;margin-left:24px}#preview.empty{display:none}#info.empty+#collapse{margin-left:auto}#collapse.empty{display:none}#preview:not(.empty)+#info.empty+#collapse:not(.empty),#preview:not(.empty)+#info:not(.empty){margin-left:24px}#content-wrapper{flex:1;min-height:0;overflow-y:auto}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px}:host([collapsed]:not([collapsed=false])) :is(#content-wrapper,#action){display:none}:host([collapsed]:not([collapsed=false])) #wrapper{padding-bottom:8px}::slotted([slot=icon]){margin-right:8px}</style><div id="wrapper"><div id="header"><slot name="icon"></slot><sinch-title id="caption" level="3" type="m"></sinch-title><div id="preview"><slot name="preview"></slot></div><div id="info"><slot name="info"></slot></div><div id="collapse"><slot name="collapse"></slot></div></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
13
+ const templateHTML = '<style>:host{display:block}#wrapper{display:flex;flex-direction:column;gap:16px;width:100%;height:100%;border:1px solid var(--sinch-color-snow-700);border-radius:var(--sinch-shape-radius-l);box-sizing:border-box;background-color:var(--sinch-color-snow-100);color:var(--sinch-color-text-default);font:var(--sinch-font-body);box-shadow:var(--sinch-elevation-level-2);padding:8px 24px 16px}#header{display:flex;flex-direction:row;align-items:center;height:48px;gap:8px;--sinch-size-icon:32px}#caption{font:var(--sinch-font-title-l);color:var(--sinch-color-text-default);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:1em}#info{display:flex;flex-direction:row;align-items:center;gap:8px;margin-left:auto;align-self:stretch}#info.empty{display:none}#preview{flex:1;flex-basis:auto;height:48px;min-width:0;overflow:hidden;margin-left:24px}#preview.empty{display:none}#info.empty+#collapse{margin-left:auto}#collapse.empty{display:none}#preview:not(.empty)+#info.empty+#collapse:not(.empty),#preview:not(.empty)+#info:not(.empty){margin-left:24px}#content-wrapper{flex:1;min-height:0;overflow-y:auto}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px}#action.empty{display:none}:host([collapsed]:not([collapsed=false])) :is(#content-wrapper,#action){display:none}:host([collapsed]:not([collapsed=false])) #wrapper{padding-bottom:8px}::slotted([slot=icon]){margin-right:8px}</style><div id="wrapper"><div id="header"><slot name="icon"></slot><sinch-title id="caption" level="3" type="m"></sinch-title><div id="preview"><slot name="preview"></slot></div><div id="info"><slot name="info"></slot></div><div id="collapse"><slot name="collapse"></slot></div></div><div id="content-wrapper"><slot name="content"></slot></div><div id="action"><slot name="action"></slot></div></div>';
14
14
  import { assertSize, sizeValues } from './utils';
15
15
  const template = document.createElement('template');
16
16
  template.innerHTML = templateHTML;
17
- defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot = new WeakMap(), _$previewWrapper = new WeakMap(), _$infoSlot = new WeakMap(), _$infoWrapper = new WeakMap(), _$collapseSlot = new WeakMap(), _$collapseWrapper = new WeakMap(), _onPreviewSlotChange = new WeakMap(), _onInfoSlotChange = new WeakMap(), _onCollapseSlotChange = new WeakMap(), class extends NectaryElement {
17
+ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot = new WeakMap(), _$previewWrapper = new WeakMap(), _$infoSlot = new WeakMap(), _$infoWrapper = new WeakMap(), _$collapseSlot = new WeakMap(), _$collapseWrapper = new WeakMap(), _$actionSlot = new WeakMap(), _$actionWrapper = new WeakMap(), _onPreviewSlotChange = new WeakMap(), _onInfoSlotChange = new WeakMap(), _onCollapseSlotChange = new WeakMap(), _onActionSlotChange = new WeakMap(), class extends NectaryElement {
18
18
  constructor() {
19
19
  super();
20
20
 
@@ -53,6 +53,16 @@ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot =
53
53
  value: void 0
54
54
  });
55
55
 
56
+ _classPrivateFieldInitSpec(this, _$actionSlot, {
57
+ writable: true,
58
+ value: void 0
59
+ });
60
+
61
+ _classPrivateFieldInitSpec(this, _$actionWrapper, {
62
+ writable: true,
63
+ value: void 0
64
+ });
65
+
56
66
  _classPrivateFieldInitSpec(this, _onPreviewSlotChange, {
57
67
  writable: true,
58
68
  value: () => {
@@ -74,6 +84,13 @@ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot =
74
84
  }
75
85
  });
76
86
 
87
+ _classPrivateFieldInitSpec(this, _onActionSlotChange, {
88
+ writable: true,
89
+ value: () => {
90
+ setClass(_classPrivateFieldGet(this, _$actionWrapper), 'empty', _classPrivateFieldGet(this, _$actionSlot).assignedElements().length === 0);
91
+ }
92
+ });
93
+
77
94
  const shadowRoot = this.attachShadow();
78
95
  shadowRoot.appendChild(template.content.cloneNode(true));
79
96
 
@@ -85,11 +102,15 @@ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot =
85
102
 
86
103
  _classPrivateFieldSet(this, _$collapseSlot, shadowRoot.querySelector('slot[name="collapse"]'));
87
104
 
105
+ _classPrivateFieldSet(this, _$actionSlot, shadowRoot.querySelector('slot[name="action"]'));
106
+
88
107
  _classPrivateFieldSet(this, _$previewWrapper, shadowRoot.querySelector('#preview'));
89
108
 
90
109
  _classPrivateFieldSet(this, _$infoWrapper, shadowRoot.querySelector('#info'));
91
110
 
92
111
  _classPrivateFieldSet(this, _$collapseWrapper, shadowRoot.querySelector('#collapse'));
112
+
113
+ _classPrivateFieldSet(this, _$actionWrapper, shadowRoot.querySelector('#action'));
93
114
  }
94
115
 
95
116
  connectedCallback() {
@@ -99,11 +120,15 @@ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot =
99
120
 
100
121
  _classPrivateFieldGet(this, _$collapseSlot).addEventListener('slotchange', _classPrivateFieldGet(this, _onCollapseSlotChange));
101
122
 
123
+ _classPrivateFieldGet(this, _$actionSlot).addEventListener('slotchange', _classPrivateFieldGet(this, _onActionSlotChange));
124
+
102
125
  _classPrivateFieldGet(this, _onPreviewSlotChange).call(this);
103
126
 
104
127
  _classPrivateFieldGet(this, _onInfoSlotChange).call(this);
105
128
 
106
129
  _classPrivateFieldGet(this, _onCollapseSlotChange).call(this);
130
+
131
+ _classPrivateFieldGet(this, _onActionSlotChange).call(this);
107
132
  }
108
133
 
109
134
  disconnectedCallback() {
@@ -112,6 +137,8 @@ defineCustomElement('sinch-segment', (_$caption = new WeakMap(), _$previewSlot =
112
137
  _classPrivateFieldGet(this, _$infoSlot).removeEventListener('slotchange', _classPrivateFieldGet(this, _onInfoSlotChange));
113
138
 
114
139
  _classPrivateFieldGet(this, _$collapseSlot).removeEventListener('slotchange', _classPrivateFieldGet(this, _onCollapseSlotChange));
140
+
141
+ _classPrivateFieldGet(this, _$actionSlot).removeEventListener('slotchange', _classPrivateFieldGet(this, _onActionSlotChange));
115
142
  }
116
143
 
117
144
  static get observedAttributes() {
@@ -2,8 +2,6 @@ import type { TSinchElementReact } from '../types';
2
2
  import type { SyntheticEvent } from 'react';
3
3
  export declare type TSinchSegmentExpandElement = HTMLElement & {
4
4
  value: boolean;
5
- focus(): void;
6
- blur(): void;
7
5
  addEventListener(type: 'change', listener: (e: CustomEvent<boolean>) => void): void;
8
6
  setAttribute(name: 'value', value: string): void;
9
7
  };
@@ -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, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute } from '../utils';
11
- const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;position:relative;flex-direction:row;align-items:center;gap:12px;width:100%;height:42px;padding:8px 20px;box-sizing:border-box;border:1px solid var(--sinch-color-snow-600);border-left-width:0;border-right-width:0;color:var(--sinch-color-stormy-500);background-color:var(--sinch-color-snow-100);--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:16px}#wrapper:hover{background-color:var(--sinch-color-snow-500)}:host(:first-child) #wrapper{border-left-width:1px;border-top-left-radius:4px;border-bottom-left-radius:4px}:host(:last-child) #wrapper{border-right-width:1px;border-top-right-radius:4px;border-bottom-right-radius:4px}#content{font:var(--sinch-font-title-s);flex-shrink:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host([checked]:not([checked=false])) #wrapper{border-color:var(--sinch-color-stormy-500)}:host([checked]:not([checked=false]):not(:first-child)) #wrapper::before{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;left:0;top:-1px;bottom:-1px}:host([checked]:not([checked=false]):not(:last-child)) #wrapper::after{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;right:0;top:-1px;bottom:-1px}#button{all:initial;position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus::before{content:"";position:absolute;left:-3px;right:-3px;top:-4px;bottom:-4px;border-style:solid;border-color:var(--sinch-color-aqua-400);border-width:0}#button:focus-visible::before{border-width:2px}:host(:first-child) #button:focus::before{left:-4px;border-top-left-radius:6px;border-bottom-left-radius:6px}:host(:last-child) #button:focus::before{right:-4px;border-top-right-radius:6px;border-bottom-right-radius:6px}@supports not selector(:focus-visible){#button:focus::before{border-width:2px}}:host([disabled]:not([disabled=false])) #wrapper{background-color:var(--sinch-color-snow-100);color:var(--sinch-color-stormy-100);--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><slot name="icon"></slot><label for="button" id="content"></label> <button id="button"></button></div>';
11
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;position:relative;flex-direction:row;align-items:center;gap:12px;width:100%;height:32px;padding:0 16px;box-sizing:border-box;border:1px solid var(--sinch-color-snow-600);border-left-width:0;border-right-width:0;color:var(--sinch-color-stormy-500);background-color:var(--sinch-color-snow-100);--sinch-color-icon:var(--sinch-color-stormy-500);--sinch-size-icon:16px}#wrapper:hover{background-color:var(--sinch-color-snow-500)}:host(:first-child) #wrapper{border-left-width:1px;border-top-left-radius:4px;border-bottom-left-radius:4px}:host(:last-child) #wrapper{border-right-width:1px;border-top-right-radius:4px;border-bottom-right-radius:4px}#content{font:var(--sinch-font-title-s);flex-shrink:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host([checked]:not([checked=false])) #wrapper{border-color:var(--sinch-color-stormy-500)}:host([checked]:not([checked=false]):not(:first-child)) #wrapper::before{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;left:0;top:-1px;bottom:-1px}:host([checked]:not([checked=false]):not(:last-child)) #wrapper::after{content:"";width:1px;background-color:var(--sinch-color-stormy-500);position:absolute;right:0;top:-1px;bottom:-1px}#button{all:initial;position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;cursor:pointer;z-index:1}#button:disabled{cursor:unset}#button:focus::before{content:"";position:absolute;left:-3px;right:-3px;top:-4px;bottom:-4px;border-style:solid;border-color:var(--sinch-color-aqua-400);border-width:0}#button:focus-visible::before{border-width:2px}:host(:first-child) #button:focus::before{left:-4px;border-top-left-radius:6px;border-bottom-left-radius:6px}:host(:last-child) #button:focus::before{right:-4px;border-top-right-radius:6px;border-bottom-right-radius:6px}@supports not selector(:focus-visible){#button:focus::before{border-width:2px}}:host([disabled]:not([disabled=false])) #wrapper{background-color:var(--sinch-color-snow-100);color:var(--sinch-color-stormy-100);--sinch-color-icon:var(--sinch-color-stormy-100)}</style><div id="wrapper"><slot name="icon"></slot><label for="button" id="content"></label> <button id="button"></button></div>';
12
12
  const template = document.createElement('template');
13
13
  template.innerHTML = templateHTML;
14
14
  defineCustomElement('sinch-segmented-control-option', (_$button = new WeakMap(), _$label = new WeakMap(), _onClick = new WeakMap(), class extends NectaryElement {
@@ -3,8 +3,6 @@ export declare type TSinchSegmentedControlOptionElement = HTMLElement & {
3
3
  value: string;
4
4
  disabled: boolean;
5
5
  text: string;
6
- focus(): void;
7
- blur(): void;
8
6
  setAttribute(name: 'value', value: string): void;
9
7
  setAttribute(name: 'text', value: string): void;
10
8
  setAttribute(name: 'disabled', value: ''): void;
@@ -2,8 +2,6 @@ import type { TSinchElementReact } from '../types';
2
2
  export declare type TSinchSegmentedIconControlOptionElement = HTMLElement & {
3
3
  value: string;
4
4
  disabled: boolean;
5
- focus(): void;
6
- blur(): void;
7
5
  setAttribute(name: 'value', value: string): void;
8
6
  setAttribute(name: 'disabled', value: ''): void;
9
7
  };
package/select/index.js CHANGED
@@ -13,7 +13,7 @@ function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(
13
13
 
14
14
  import '../dropdown';
15
15
  import { defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, 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-popover-expand-width:1}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;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)}</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>';
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-popover-expand-width:1}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;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)}</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"><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
17
  const template = document.createElement('template');
18
18
  template.innerHTML = templateHTML;
19
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(), class extends NectaryElement {
package/select/types.d.ts CHANGED
@@ -10,8 +10,6 @@ export declare type TSinchSelectElement = HTMLElement & {
10
10
  maxVisibleItems: number | null;
11
11
  disabled: boolean;
12
12
  readonly dropdownRect: TRect;
13
- focus(): void;
14
- blur(): void;
15
13
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
16
14
  setAttribute(name: 'value', value: string): void;
17
15
  setAttribute(name: 'label', value: string): void;
@@ -4,8 +4,6 @@ export declare type TSinchTabsOptionElement = HTMLElement & {
4
4
  disabled: boolean;
5
5
  checked: boolean;
6
6
  text: string;
7
- focus(): void;
8
- blur(): void;
9
7
  setAttribute(name: 'value', value: string): void;
10
8
  setAttribute(name: 'disabled', value: ''): void;
11
9
  setAttribute(name: 'checked', value: ''): void;
@@ -1,6 +1,3 @@
1
1
  import type { TSinchElementReact } from '../types';
2
- export declare type TSinchTagCloseElement = HTMLElement & {
3
- focus(): void;
4
- blur(): void;
5
- };
2
+ export declare type TSinchTagCloseElement = HTMLElement;
6
3
  export declare type TSinchTagCloseReact = TSinchElementReact<TSinchTagCloseElement>;
package/text/index.js CHANGED
@@ -7,9 +7,7 @@ template.innerHTML = templateHTML;
7
7
  defineCustomElement('sinch-text', class extends NectaryElement {
8
8
  constructor() {
9
9
  super();
10
- const shadowRoot = this.attachShadow({
11
- delegatesFocus: false
12
- });
10
+ const shadowRoot = this.attachShadow();
13
11
  shadowRoot.appendChild(template.content.cloneNode(true));
14
12
  }
15
13
 
@@ -13,8 +13,6 @@ export declare type TSinchTextareaElement = HTMLElement & {
13
13
  selectionDirection: HTMLTextAreaElement['selectionDirection'];
14
14
  rows: HTMLTextAreaElement['rows'];
15
15
  resizable: boolean;
16
- focus(): void;
17
- blur(): void;
18
16
  addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
19
17
  setAttribute(name: 'value', value: string): void;
20
18
  setAttribute(name: 'label', value: string): void;
@@ -0,0 +1,17 @@
1
+ import '../icon-button';
2
+ import '../icons/done';
3
+ import '../icons/arrow-drop-up';
4
+ import '../icons/arrow-drop-down';
5
+ import '../segmented-control';
6
+ import '../segmented-control-option';
7
+ import type { TSinchTimePickerElement, TSinchTimePickerReact } from './types';
8
+ declare global {
9
+ namespace JSX {
10
+ interface IntrinsicElements {
11
+ 'sinch-time-picker': TSinchTimePickerReact;
12
+ }
13
+ }
14
+ interface HTMLElementTagNameMap {
15
+ 'sinch-time-picker': TSinchTimePickerElement;
16
+ }
17
+ }
@@ -0,0 +1,525 @@
1
+ import _classPrivateFieldGet from '@babel/runtime/helpers/classPrivateFieldGet';
2
+ import _classPrivateFieldSet from '@babel/runtime/helpers/classPrivateFieldSet';
3
+
4
+ var _$pickerHours, _$pickerMinutes, _$pickerTouch, _$needleHour, _$needleMinute, _$headerHours, _$headerHoursText, _$headerMinutes, _$headerMinutesText, _$ampm, _$submitButton, _hour, _minute, _getClickDegree, _onPickerClick, _render, _selectHour, _selectMinute, _onAmPmChange, _onSubmitButtonClick, _onHoursKeydown, _onMinutesKeydown;
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 '../icon-button';
15
+ import '../icons/done';
16
+ import '../icons/arrow-drop-up';
17
+ import '../icons/arrow-drop-down';
18
+ import '../segmented-control';
19
+ import '../segmented-control-option';
20
+ import { defineCustomElement, getAttribute, getBooleanAttribute, getRect, isAttrTrue, NectaryElement, setClass, updateAttribute, updateBooleanAttribute } from '../utils';
21
+ const templateHTML = '<style>:host{display:block;outline:0}#wrapper{display:flex;flex-direction:column;width:248px;padding:16px;box-sizing:border-box;gap:16px}#header{position:relative;width:100%;height:48px;font:var(--sinch-font-title-xl);line-height:48px}#footer{display:flex;justify-content:center;width:100%;height:32px}#picker{position:relative;width:216px;height:216px;border-radius:50%;box-sizing:border-box;border:1px solid var(--sinch-color-stormy-500)}#digit-minutes,#picker-hours{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:50%}.digit-hour-12,.digit-hour-24,.digit-minute{position:absolute;width:28px;height:28px;font:var(--sinch-font-text-s);line-height:28px;text-align:center;color:var(--sinch-color-text-default);top:calc(50% - 14px);left:calc(50% - 14px);z-index:1;cursor:pointer}.digit-hour-24{font:var(--sinch-font-text-xs);line-height:28px;color:var(--sinch-color-text-muted)}.digit-minute{font:var(--sinch-font-text-xs);line-height:28px;color:var(--sinch-color-text-muted)}.digit-hour-12:hover,.digit-hour-24:hover,.digit-minute:hover{color:var(--sinch-color-tropical-500)}.digit-hour-12.selected,.digit-hour-24.selected,.digit-minute.selected{color:var(--sinch-color-tropical-500)}.digit-hour-12.selected{font-size:16px}.digit-hour-24.selected{font-size:16px}.digit-minute.selected{font-size:16px}#picker-touch{position:absolute;left:0;top:0;width:100%;height:100%;cursor:pointer;border-radius:50%}#needle-hour,#needle-minute,#picker-touch::after{background-color:var(--sinch-color-stormy-500)}#needle-hour,#needle-minute{position:absolute;transform-origin:bottom center;transform:rotate(0);bottom:50%;height:50px;transition-duration:.25s;transition-timing-function:ease-in-out;transition-property:transform height;z-index:2}@media (prefers-reduced-motion){#needle-hour,#needle-minute{transition:none}}#needle-hour{width:4px;left:calc(50% - 2px);border-radius:2px}#needle-minute{width:2px;left:calc(50% - 1px);border-radius:1px}#needle-minute:not(.selected)::after{content:"";position:absolute;transform:translateX(-50%);left:0;top:-16px;width:4px;height:4px;border-radius:50%;background-color:var(--sinch-color-tropical-500)}#picker-touch::after{content:"";position:absolute;top:50%;left:50%;width:12px;height:12px;border-radius:50%;transform:translate(-50%,-50%)}#header-hours,#header-minutes{position:absolute;padding:0 4px;width:50px;outline:0;--sinch-icon-size:24px}#header-hours{right:calc(50% + 8px);text-align:right}#header-minutes{left:calc(50% + 8px)}#header-hours::before,#header-minutes::before{content:"";display:none;position:absolute;border-radius:12px;left:50%;top:50%;width:100%;height:100%;transform:translate(-50%,-50%);padding:1px;border:1px solid var(--sinch-color-aqua-400)}#header-hours-down,#header-hours-up,#header-minutes-down,#header-minutes-up{display:none;position:absolute;left:50%;transform:translateX(-50%)}#header-hours-up,#header-minutes-up{top:-18px}#header-hours-down,#header-minutes-down{bottom:-18px}#header-hours:focus #header-hours-down,#header-hours:focus #header-hours-up,#header-hours:focus::before{display:block}#header-minutes:focus #header-minutes-down,#header-minutes:focus #header-minutes-up,#header-minutes:focus::before{display:block}#header-colon{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}#submit{position:absolute;right:0;top:50%;transform:translateY(-50%)}:host([ampm]) .digit-hour-24{display:none}:host(:not([ampm])) #footer{display:none}</style><div id="wrapper"><div id="header"><div id="header-hours" tabindex="0" role="meter" aria-valuemin="0" aria-valuemax="23" aria-valuenow="0" aria-valuetext="0"><span>00</span><sinch-icon-arrow-drop-up id="header-hours-up"></sinch-icon-arrow-drop-up><sinch-icon-arrow-drop-down id="header-hours-down"></sinch-icon-arrow-drop-down></div><div id="header-colon">&colon;</div><div id="header-minutes" tabindex="0" role="meter" aria-valuemin="0" aria-valuemax="59" aria-valuenow="0" aria-valuetext="0"><span>00</span><sinch-icon-arrow-drop-up id="header-minutes-up"></sinch-icon-arrow-drop-up><sinch-icon-arrow-drop-down id="header-minutes-down"></sinch-icon-arrow-drop-down></div><sinch-icon-button id="submit" small aria-label="Submit"><sinch-icon-done slot="icon"></sinch-icon-done></sinch-icon-button></div><div id="picker" aria-hidden="true"><div id="picker-hours"></div><div id="picker-minutes"></div><div id="picker-touch"><div id="needle-hour"></div><div id="needle-minute"></div></div></div><div id="footer"><sinch-segmented-control id="ampm"><sinch-segmented-control-option value="am" text="AM" aria-label="AM"></sinch-segmented-control-option><sinch-segmented-control-option value="pm" text="PM" aria-label="PM"></sinch-segmented-control-option></sinch-segmented-control></div></div>';
22
+ import { getNeedleRotationDeg, getShortestCssDeg, hourToIndex, parseTime, stringifyHour, stringifyHourFace, stringifyMinute, stringifyTime } from './utils';
23
+ const template = document.createElement('template');
24
+ template.innerHTML = templateHTML;
25
+ const PICKER_RADIUS = 216 / 2;
26
+ const MINUTE_DIGIT_SIZE = 30;
27
+ const HOUR_12_DIGIT_SIZE = 26;
28
+ const HOUR_24_DIGIT_SIZE = 26;
29
+ const MINUTE_RADIUS = PICKER_RADIUS - MINUTE_DIGIT_SIZE;
30
+ const HOUR_12_RADIUS = MINUTE_RADIUS - HOUR_12_DIGIT_SIZE;
31
+ const HOUR_24_RADIUS = HOUR_12_RADIUS - HOUR_24_DIGIT_SIZE;
32
+ const NEEDLE_HOUR_12_LENGTH = HOUR_12_RADIUS;
33
+ const NEEDLE_HOUR_24_LENGTH = HOUR_24_RADIUS;
34
+ const NEEDLE_MINUTE_LENGTH = MINUTE_RADIUS;
35
+ defineCustomElement('sinch-time-picker', (_$pickerHours = new WeakMap(), _$pickerMinutes = new WeakMap(), _$pickerTouch = new WeakMap(), _$needleHour = new WeakMap(), _$needleMinute = new WeakMap(), _$headerHours = new WeakMap(), _$headerHoursText = new WeakMap(), _$headerMinutes = new WeakMap(), _$headerMinutesText = new WeakMap(), _$ampm = new WeakMap(), _$submitButton = new WeakMap(), _hour = new WeakMap(), _minute = new WeakMap(), _getClickDegree = new WeakSet(), _onPickerClick = new WeakMap(), _render = new WeakSet(), _selectHour = new WeakSet(), _selectMinute = new WeakSet(), _onAmPmChange = new WeakMap(), _onSubmitButtonClick = new WeakMap(), _onHoursKeydown = new WeakMap(), _onMinutesKeydown = new WeakMap(), class extends NectaryElement {
36
+ constructor() {
37
+ super();
38
+
39
+ _classPrivateMethodInitSpec(this, _selectMinute);
40
+
41
+ _classPrivateMethodInitSpec(this, _selectHour);
42
+
43
+ _classPrivateMethodInitSpec(this, _render);
44
+
45
+ _classPrivateMethodInitSpec(this, _getClickDegree);
46
+
47
+ _classPrivateFieldInitSpec(this, _$pickerHours, {
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+
52
+ _classPrivateFieldInitSpec(this, _$pickerMinutes, {
53
+ writable: true,
54
+ value: void 0
55
+ });
56
+
57
+ _classPrivateFieldInitSpec(this, _$pickerTouch, {
58
+ writable: true,
59
+ value: void 0
60
+ });
61
+
62
+ _classPrivateFieldInitSpec(this, _$needleHour, {
63
+ writable: true,
64
+ value: void 0
65
+ });
66
+
67
+ _classPrivateFieldInitSpec(this, _$needleMinute, {
68
+ writable: true,
69
+ value: void 0
70
+ });
71
+
72
+ _classPrivateFieldInitSpec(this, _$headerHours, {
73
+ writable: true,
74
+ value: void 0
75
+ });
76
+
77
+ _classPrivateFieldInitSpec(this, _$headerHoursText, {
78
+ writable: true,
79
+ value: void 0
80
+ });
81
+
82
+ _classPrivateFieldInitSpec(this, _$headerMinutes, {
83
+ writable: true,
84
+ value: void 0
85
+ });
86
+
87
+ _classPrivateFieldInitSpec(this, _$headerMinutesText, {
88
+ writable: true,
89
+ value: void 0
90
+ });
91
+
92
+ _classPrivateFieldInitSpec(this, _$ampm, {
93
+ writable: true,
94
+ value: void 0
95
+ });
96
+
97
+ _classPrivateFieldInitSpec(this, _$submitButton, {
98
+ writable: true,
99
+ value: void 0
100
+ });
101
+
102
+ _classPrivateFieldInitSpec(this, _hour, {
103
+ writable: true,
104
+ value: 0
105
+ });
106
+
107
+ _classPrivateFieldInitSpec(this, _minute, {
108
+ writable: true,
109
+ value: 0
110
+ });
111
+
112
+ _classPrivateFieldInitSpec(this, _onPickerClick, {
113
+ writable: true,
114
+ value: e => {
115
+ const [cssDeg, rowIndex] = _classPrivateMethodGet(this, _getClickDegree, _getClickDegree2).call(this, e.x, e.y);
116
+
117
+ const isHourRowClick = rowIndex > 0;
118
+ const isHour24RowClick = rowIndex > 1;
119
+
120
+ if (isHourRowClick) {
121
+ const digitIndex = Math.round(cssDeg / 30) % 12;
122
+ const is24 = getBooleanAttribute(this, 'ampm') === false;
123
+
124
+ if (is24) {
125
+ if (isHour24RowClick) {
126
+ _classPrivateFieldSet(this, _hour, digitIndex === 0 ? 0 : digitIndex + 12);
127
+ } else {
128
+ _classPrivateFieldSet(this, _hour, digitIndex === 0 ? 12 : digitIndex);
129
+ }
130
+ } else {
131
+ _classPrivateFieldSet(this, _hour, digitIndex + (_classPrivateFieldGet(this, _$ampm).value === 'pm' ? 12 : 0));
132
+ }
133
+
134
+ _classPrivateFieldGet(this, _$headerHours).focus();
135
+ } else {
136
+ _classPrivateFieldSet(this, _minute, Math.round(cssDeg / 6) % 60);
137
+
138
+ _classPrivateFieldGet(this, _$headerMinutes).focus();
139
+ }
140
+
141
+ _classPrivateMethodGet(this, _render, _render2).call(this);
142
+ }
143
+ });
144
+
145
+ _classPrivateFieldInitSpec(this, _onAmPmChange, {
146
+ writable: true,
147
+ value: e => {
148
+ e.stopPropagation();
149
+ const value = e.detail;
150
+
151
+ switch (value) {
152
+ case 'am':
153
+ {
154
+ if (_classPrivateFieldGet(this, _hour) >= 12) {
155
+ _classPrivateFieldSet(this, _hour, _classPrivateFieldGet(this, _hour) - 12);
156
+
157
+ _classPrivateMethodGet(this, _render, _render2).call(this);
158
+ }
159
+
160
+ break;
161
+ }
162
+
163
+ case 'pm':
164
+ {
165
+ if (_classPrivateFieldGet(this, _hour) < 12) {
166
+ _classPrivateFieldSet(this, _hour, _classPrivateFieldGet(this, _hour) + 12);
167
+
168
+ _classPrivateMethodGet(this, _render, _render2).call(this);
169
+ }
170
+
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ });
176
+
177
+ _classPrivateFieldInitSpec(this, _onSubmitButtonClick, {
178
+ writable: true,
179
+ value: () => {
180
+ const value = stringifyTime(_classPrivateFieldGet(this, _hour), _classPrivateFieldGet(this, _minute));
181
+ this.dispatchEvent(new CustomEvent('change', {
182
+ bubbles: true,
183
+ detail: value
184
+ }));
185
+ }
186
+ });
187
+
188
+ _classPrivateFieldInitSpec(this, _onHoursKeydown, {
189
+ writable: true,
190
+ value: e => {
191
+ switch (e.key) {
192
+ case 'ArrowUp':
193
+ {
194
+ _classPrivateFieldSet(this, _hour, (_classPrivateFieldGet(this, _hour) + 1) % 24);
195
+
196
+ _classPrivateMethodGet(this, _render, _render2).call(this);
197
+
198
+ break;
199
+ }
200
+
201
+ case 'ArrowDown':
202
+ {
203
+ _classPrivateFieldSet(this, _hour, (_classPrivateFieldGet(this, _hour) + 23) % 24);
204
+
205
+ _classPrivateMethodGet(this, _render, _render2).call(this);
206
+
207
+ break;
208
+ }
209
+ }
210
+ }
211
+ });
212
+
213
+ _classPrivateFieldInitSpec(this, _onMinutesKeydown, {
214
+ writable: true,
215
+ value: e => {
216
+ switch (e.key) {
217
+ case 'ArrowUp':
218
+ {
219
+ _classPrivateFieldSet(this, _minute, (_classPrivateFieldGet(this, _minute) + 1) % 60);
220
+
221
+ _classPrivateMethodGet(this, _render, _render2).call(this);
222
+
223
+ break;
224
+ }
225
+
226
+ case 'ArrowDown':
227
+ {
228
+ _classPrivateFieldSet(this, _minute, (_classPrivateFieldGet(this, _minute) + 59) % 60);
229
+
230
+ _classPrivateMethodGet(this, _render, _render2).call(this);
231
+
232
+ break;
233
+ }
234
+ }
235
+ }
236
+ });
237
+
238
+ const shadowRoot = this.attachShadow();
239
+ shadowRoot.appendChild(template.content.cloneNode(true));
240
+
241
+ _classPrivateFieldSet(this, _$pickerHours, shadowRoot.querySelector('#picker-hours'));
242
+
243
+ _classPrivateFieldSet(this, _$pickerMinutes, shadowRoot.querySelector('#picker-minutes'));
244
+
245
+ _classPrivateFieldSet(this, _$pickerTouch, shadowRoot.querySelector('#picker'));
246
+
247
+ _classPrivateFieldSet(this, _$needleHour, shadowRoot.querySelector('#needle-hour'));
248
+
249
+ _classPrivateFieldSet(this, _$needleMinute, shadowRoot.querySelector('#needle-minute'));
250
+
251
+ _classPrivateFieldSet(this, _$headerHours, shadowRoot.querySelector('#header-hours'));
252
+
253
+ _classPrivateFieldSet(this, _$headerMinutes, shadowRoot.querySelector('#header-minutes'));
254
+
255
+ _classPrivateFieldSet(this, _$headerHoursText, shadowRoot.querySelector('#header-hours > span'));
256
+
257
+ _classPrivateFieldSet(this, _$headerMinutesText, shadowRoot.querySelector('#header-minutes > span'));
258
+
259
+ _classPrivateFieldSet(this, _$ampm, shadowRoot.querySelector('#ampm'));
260
+
261
+ _classPrivateFieldSet(this, _$submitButton, shadowRoot.querySelector('#submit'));
262
+
263
+ _classPrivateFieldGet(this, _$needleMinute).style.height = `${NEEDLE_MINUTE_LENGTH}px`;
264
+ _classPrivateFieldGet(this, _$needleHour).style.height = `${NEEDLE_HOUR_12_LENGTH}px`;
265
+ const MINUTE_DIGIT_RADIUS = MINUTE_RADIUS + MINUTE_DIGIT_SIZE / 2;
266
+ const HOUR_12_DIGIT_RADIUS = HOUR_12_RADIUS + HOUR_12_DIGIT_SIZE / 2;
267
+ const HOUR_24_DIGIT_RADIUS = HOUR_24_RADIUS + HOUR_24_DIGIT_SIZE / 2;
268
+ const hours12Frag = document.createDocumentFragment();
269
+
270
+ for (let i = 0; i < 12; i++) {
271
+ const rad = Math.PI / 6 * (i - 3);
272
+ const el = document.createElement('div');
273
+ const x = Math.cos(rad) * HOUR_12_DIGIT_RADIUS;
274
+ const y = Math.sin(rad) * HOUR_12_DIGIT_RADIUS;
275
+ const hourDisplayValue = stringifyHourFace(i);
276
+ el.className = 'digit-hour-12';
277
+ el.style.transform = `translate(${x}px, ${y}px)`;
278
+ el.textContent = hourDisplayValue;
279
+ hours12Frag.appendChild(el);
280
+ }
281
+
282
+ _classPrivateFieldGet(this, _$pickerHours).appendChild(hours12Frag);
283
+
284
+ const hours24Frag = document.createDocumentFragment();
285
+
286
+ for (let i = 12; i < 24; i++) {
287
+ const rad = Math.PI / 6 * (i - 3);
288
+ const el = document.createElement('div');
289
+ const x = Math.cos(rad) * HOUR_24_DIGIT_RADIUS;
290
+ const y = Math.sin(rad) * HOUR_24_DIGIT_RADIUS;
291
+ const hourDisplayValue = stringifyHourFace(i);
292
+ el.className = 'digit-hour-24';
293
+ el.style.transform = `translate(${x}px, ${y}px)`;
294
+ el.textContent = hourDisplayValue;
295
+ hours24Frag.appendChild(el);
296
+ }
297
+
298
+ _classPrivateFieldGet(this, _$pickerHours).appendChild(hours24Frag);
299
+
300
+ const minutesFrag = document.createDocumentFragment();
301
+
302
+ for (let i = 0; i < 60; i += 5) {
303
+ const rad = Math.PI / 30 * (i - 15);
304
+ const el = document.createElement('div');
305
+ const x = Math.cos(rad) * MINUTE_DIGIT_RADIUS;
306
+ const y = Math.sin(rad) * MINUTE_DIGIT_RADIUS;
307
+ el.className = 'digit-minute';
308
+ el.style.transform = `translate(${x}px, ${y}px)`;
309
+ el.textContent = stringifyMinute(i);
310
+ minutesFrag.appendChild(el);
311
+ }
312
+
313
+ _classPrivateFieldGet(this, _$pickerMinutes).appendChild(minutesFrag);
314
+ }
315
+
316
+ connectedCallback() {
317
+ _classPrivateFieldGet(this, _$pickerTouch).addEventListener('click', _classPrivateFieldGet(this, _onPickerClick));
318
+
319
+ _classPrivateFieldGet(this, _$ampm).addEventListener('change', _classPrivateFieldGet(this, _onAmPmChange));
320
+
321
+ _classPrivateFieldGet(this, _$submitButton).addEventListener('click', _classPrivateFieldGet(this, _onSubmitButtonClick));
322
+
323
+ _classPrivateFieldGet(this, _$headerHours).addEventListener('keydown', _classPrivateFieldGet(this, _onHoursKeydown));
324
+
325
+ _classPrivateFieldGet(this, _$headerMinutes).addEventListener('keydown', _classPrivateFieldGet(this, _onMinutesKeydown));
326
+ }
327
+
328
+ disconnectedCallback() {
329
+ _classPrivateFieldGet(this, _$pickerTouch).removeEventListener('click', _classPrivateFieldGet(this, _onPickerClick));
330
+
331
+ _classPrivateFieldGet(this, _$ampm).removeEventListener('change', _classPrivateFieldGet(this, _onAmPmChange));
332
+
333
+ _classPrivateFieldGet(this, _$submitButton).removeEventListener('click', _classPrivateFieldGet(this, _onSubmitButtonClick));
334
+
335
+ _classPrivateFieldGet(this, _$headerHours).removeEventListener('keydown', _classPrivateFieldGet(this, _onHoursKeydown));
336
+
337
+ _classPrivateFieldGet(this, _$headerMinutes).removeEventListener('keydown', _classPrivateFieldGet(this, _onMinutesKeydown));
338
+ }
339
+
340
+ static get observedAttributes() {
341
+ return ['value', 'ampm', 'submit-aria-label'];
342
+ }
343
+
344
+ attributeChangedCallback(name, prevValue, newVal) {
345
+ if (newVal === prevValue) {
346
+ return;
347
+ }
348
+
349
+ switch (name) {
350
+ case 'value':
351
+ {
352
+ if (newVal === null) {
353
+ throw new Error('Missing "value" attribute');
354
+ }
355
+
356
+ const {
357
+ hours,
358
+ minutes
359
+ } = parseTime(newVal);
360
+
361
+ _classPrivateFieldSet(this, _hour, hours);
362
+
363
+ _classPrivateFieldSet(this, _minute, minutes);
364
+
365
+ _classPrivateMethodGet(this, _render, _render2).call(this);
366
+
367
+ break;
368
+ }
369
+
370
+ case 'ampm':
371
+ {
372
+ const isAmpm = isAttrTrue(newVal);
373
+ updateBooleanAttribute(this, 'ampm', isAmpm);
374
+
375
+ _classPrivateMethodGet(this, _render, _render2).call(this);
376
+
377
+ break;
378
+ }
379
+
380
+ case 'submit-aria-label':
381
+ {
382
+ _classPrivateFieldGet(this, _$submitButton).ariaLabel = newVal;
383
+ break;
384
+ }
385
+ }
386
+ }
387
+
388
+ get nodeName() {
389
+ return 'select';
390
+ }
391
+
392
+ set value(value) {
393
+ updateAttribute(this, 'value', value);
394
+ }
395
+
396
+ get value() {
397
+ return getAttribute(this, 'value', '');
398
+ }
399
+
400
+ set ampm(value) {
401
+ updateBooleanAttribute(this, 'ampm', value);
402
+ }
403
+
404
+ get ampm() {
405
+ return getBooleanAttribute(this, 'ampm');
406
+ }
407
+
408
+ get submitButtonRect() {
409
+ return getRect(_classPrivateFieldGet(this, _$submitButton));
410
+ }
411
+
412
+ get amButtonRect() {
413
+ if (!this.ampm) {
414
+ return null;
415
+ }
416
+
417
+ const $am = _classPrivateFieldGet(this, _$ampm).querySelector('[value="am"]');
418
+
419
+ return $am != null ? getRect($am) : null;
420
+ }
421
+
422
+ get pmButtonRect() {
423
+ if (!this.ampm) {
424
+ return null;
425
+ }
426
+
427
+ const $pm = _classPrivateFieldGet(this, _$ampm).querySelector('[value="pm"]');
428
+
429
+ return $pm != null ? getRect($pm) : null;
430
+ }
431
+
432
+ hourDigitRect(hour) {
433
+ const $digit = _classPrivateFieldGet(this, _$pickerHours).children[hourToIndex(hour, !this.ampm)];
434
+
435
+ return $digit != null ? getRect($digit) : null;
436
+ }
437
+
438
+ minuteDigitRect(minute) {
439
+ const $digit = _classPrivateFieldGet(this, _$pickerMinutes).children[Math.round(minute / 5)];
440
+
441
+ return $digit != null ? getRect($digit) : null;
442
+ }
443
+
444
+ }));
445
+
446
+ function _getClickDegree2(x, y) {
447
+ const touchRect = _classPrivateFieldGet(this, _$pickerTouch).getBoundingClientRect();
448
+
449
+ const cx = touchRect.width / 2;
450
+ const cy = touchRect.height / 2;
451
+ const px = x - touchRect.x;
452
+ const py = touchRect.height - y + touchRect.y;
453
+ const dx = px - cx;
454
+ const dy = py - cy;
455
+ const len = Math.sqrt(dx * dx + dy * dy);
456
+ const cosRad = dx / len;
457
+ const rad = Math.acos(cosRad * (dy < 0 ? -1 : 1));
458
+ const deg = rad * (180 / Math.PI);
459
+ let cssDeg = (deg - 90 - 360) % 360 * -1;
460
+
461
+ if (dy < 0) {
462
+ cssDeg += 180;
463
+ }
464
+
465
+ const rowIndex = len > MINUTE_RADIUS ? 0 : len > HOUR_12_RADIUS ? 1 : 2;
466
+ return [cssDeg, rowIndex];
467
+ }
468
+
469
+ function _render2() {
470
+ const is24 = getBooleanAttribute(this, 'ampm') === false;
471
+
472
+ _classPrivateMethodGet(this, _selectHour, _selectHour2).call(this, is24);
473
+
474
+ _classPrivateMethodGet(this, _selectMinute, _selectMinute2).call(this);
475
+
476
+ _classPrivateFieldGet(this, _$headerHoursText).textContent = stringifyHour(_classPrivateFieldGet(this, _hour), is24);
477
+ _classPrivateFieldGet(this, _$headerMinutesText).textContent = stringifyMinute(_classPrivateFieldGet(this, _minute));
478
+ updateAttribute(_classPrivateFieldGet(this, _$headerHours), 'aria-valuenow', _classPrivateFieldGet(this, _hour));
479
+ updateAttribute(_classPrivateFieldGet(this, _$headerHours), 'aria-valuetext', _classPrivateFieldGet(this, _hour));
480
+ updateAttribute(_classPrivateFieldGet(this, _$headerMinutes), 'aria-valuenow', _classPrivateFieldGet(this, _minute));
481
+ updateAttribute(_classPrivateFieldGet(this, _$headerMinutes), 'aria-valuetext', _classPrivateFieldGet(this, _minute));
482
+ }
483
+
484
+ function _selectHour2(is24) {
485
+ const $hours = _classPrivateFieldGet(this, _$pickerHours).children;
486
+
487
+ const hourDigitIndex = _classPrivateFieldGet(this, _hour) % 12;
488
+ const selectedIndex = hourToIndex(_classPrivateFieldGet(this, _hour), is24);
489
+ const currentCssDeg = getNeedleRotationDeg(_classPrivateFieldGet(this, _$needleHour));
490
+ const hourCssDeg = getShortestCssDeg(currentCssDeg, hourDigitIndex * 30);
491
+
492
+ for (let i = 0; i < $hours.length; i++) {
493
+ setClass($hours[i], 'selected', i === selectedIndex);
494
+ }
495
+
496
+ _classPrivateFieldGet(this, _$needleHour).style.transform = `rotate(${hourCssDeg}deg)`;
497
+
498
+ if (is24) {
499
+ if (_classPrivateFieldGet(this, _hour) > 0 && _classPrivateFieldGet(this, _hour) <= 12) {
500
+ _classPrivateFieldGet(this, _$needleHour).style.height = `${NEEDLE_HOUR_12_LENGTH}px`;
501
+ } else {
502
+ _classPrivateFieldGet(this, _$needleHour).style.height = `${NEEDLE_HOUR_24_LENGTH}px`;
503
+ }
504
+ } else {
505
+ _classPrivateFieldGet(this, _$needleHour).style.height = `${NEEDLE_HOUR_12_LENGTH}px`;
506
+ }
507
+
508
+ _classPrivateFieldGet(this, _$ampm).setAttribute('value', _classPrivateFieldGet(this, _hour) >= 0 && _classPrivateFieldGet(this, _hour) < 12 ? 'am' : 'pm');
509
+ }
510
+
511
+ function _selectMinute2() {
512
+ const $minutes = _classPrivateFieldGet(this, _$pickerMinutes).children;
513
+
514
+ const isNeedleSelected = _classPrivateFieldGet(this, _minute) % 5 === 0;
515
+ const selectedIndex = _classPrivateFieldGet(this, _minute) / 5;
516
+ const currentCssDeg = getNeedleRotationDeg(_classPrivateFieldGet(this, _$needleMinute));
517
+ const minuteCssDeg = getShortestCssDeg(currentCssDeg, _classPrivateFieldGet(this, _minute) * 6);
518
+
519
+ for (let i = 0; i < $minutes.length; i++) {
520
+ setClass($minutes[i], 'selected', selectedIndex === i);
521
+ }
522
+
523
+ setClass(_classPrivateFieldGet(this, _$needleMinute), 'selected', isNeedleSelected);
524
+ _classPrivateFieldGet(this, _$needleMinute).style.transform = `rotate(${minuteCssDeg}deg)`;
525
+ }
@@ -0,0 +1,31 @@
1
+ import type { TRect, TSinchElementReact } from '../types';
2
+ import type { SyntheticEvent } from 'react';
3
+ export declare type TSinchTimePickerElement = HTMLElement & {
4
+ /** Time value in ISO 8601 format */
5
+ value: string;
6
+ /** AM/PM 12-hour clock system, `false` by default */
7
+ ampm: boolean;
8
+ readonly submitButtonRect: TRect;
9
+ readonly amButtonRect: TRect | null;
10
+ readonly pmButtonRect: TRect | null;
11
+ hourDigitRect(hour: number): TRect | null;
12
+ minuteDigitRect(minute: number): TRect | null;
13
+ /** Change value handler, return time in ISO 8601 format */
14
+ addEventListener(type: 'change', listener: (e: CustomEvent<string>) => void): void;
15
+ /** Time value in ISO 8601 format */
16
+ setAttribute(name: 'value', value: string): void;
17
+ /** AM/PM 12-hour clock system, `false` by default */
18
+ setAttribute(name: 'ampm', value: boolean): void;
19
+ };
20
+ export declare type TSinchTimePickerReact = TSinchElementReact<TSinchTimePickerElement> & {
21
+ /** Time value in ISO 8601 format */
22
+ value: string;
23
+ /** AM/PM 12-hour clock system, `false` by default */
24
+ ampm?: boolean;
25
+ /** Label that is used for a11y */
26
+ 'aria-label': string;
27
+ /** Submit button label that is used for a11y */
28
+ 'submit-aria-label': string;
29
+ /** Change value handler, return time in ISO 8601 format */
30
+ onChange: (e: SyntheticEvent<TSinchTimePickerElement, CustomEvent<string>>) => void;
31
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export declare const parseTime: (value: string) => {
2
+ hours: number;
3
+ minutes: number;
4
+ };
5
+ export declare const stringifyTime: (hour: number, minute: number) => string;
6
+ export declare const stringifyHour: (hour: number, is24: boolean) => string;
7
+ export declare const stringifyHourFace: (hour: number) => string;
8
+ export declare const stringifyMinute: (minute: number) => string;
9
+ export declare const hourToIndex: (hour: number, is24: boolean) => number;
10
+ export declare const getNeedleRotationDeg: (elem: HTMLElement) => number;
11
+ export declare const getShortestCssDeg: (currentDeg: number, nextDeg: number) => number;
@@ -0,0 +1,94 @@
1
+ export const parseTime = value => {
2
+ if (value === '') {
3
+ return {
4
+ hours: 0,
5
+ minutes: 0
6
+ };
7
+ }
8
+
9
+ const timeParts = value.split(':');
10
+
11
+ if (timeParts.length < 3) {
12
+ throw new Error(`Incorrect time format: ${value}. Should be "hh:mm:ss"`);
13
+ }
14
+
15
+ const hours = parseInt(timeParts[0]);
16
+ const minutes = parseInt(timeParts[1]);
17
+ const seconds = parseInt(timeParts[2]);
18
+
19
+ if (isNaN(hours) || hours > 23 || hours < 0) {
20
+ throw new Error(`Invalid hours value: ${value}`);
21
+ }
22
+
23
+ if (isNaN(minutes) || minutes > 59 || minutes < 0) {
24
+ throw new Error(`Invalid minutes value: ${value}`);
25
+ }
26
+
27
+ if (isNaN(seconds) || seconds > 59 || seconds < 0) {
28
+ throw new Error(`Invalid seconds value: ${value}`);
29
+ }
30
+
31
+ return {
32
+ hours,
33
+ minutes
34
+ };
35
+ };
36
+
37
+ const pad = value => {
38
+ return value.toString().padStart(2, '0');
39
+ };
40
+
41
+ export const stringifyTime = (hour, minute) => {
42
+ return `${pad(hour)}:${pad(minute)}:00`;
43
+ };
44
+ export const stringifyHour = (hour, is24) => {
45
+ if (is24) {
46
+ return pad(hour);
47
+ }
48
+
49
+ if (hour === 0 || hour === 12) {
50
+ return '12';
51
+ }
52
+
53
+ return pad(hour % 12);
54
+ };
55
+ export const stringifyHourFace = hour => {
56
+ return hour === 0 ? '12' : hour === 12 ? '24' : String(hour);
57
+ };
58
+ export const stringifyMinute = minute => {
59
+ return pad(minute);
60
+ };
61
+ export const hourToIndex = (hour, is24) => {
62
+ if (is24) {
63
+ if (hour === 0) {
64
+ return 12;
65
+ }
66
+
67
+ if (hour === 12) {
68
+ return 0;
69
+ }
70
+
71
+ return hour;
72
+ }
73
+
74
+ return hour % 12;
75
+ };
76
+ export const getNeedleRotationDeg = elem => {
77
+ const match = elem.style.transform.match(/^rotate\((-?\d+)deg\)$/);
78
+
79
+ if (match === null) {
80
+ return 0;
81
+ }
82
+
83
+ return Number(match[1]);
84
+ };
85
+ export const getShortestCssDeg = (currentDeg, nextDeg) => {
86
+ const angle = currentDeg % 360;
87
+ const diff = (360 - (angle - nextDeg)) % 360;
88
+
89
+ if (diff > 180) {
90
+ return currentDeg - 360 + diff;
91
+ }
92
+
93
+ return currentDeg + diff;
94
+ };
package/toggle/types.d.ts CHANGED
@@ -6,8 +6,6 @@ export declare type TSinchToggleElement = HTMLElement & {
6
6
  labeled: boolean;
7
7
  disabled: boolean;
8
8
  text: string | null;
9
- focus(): void;
10
- blur(): void;
11
9
  addEventListener(type: 'change', listener: (e: CustomEvent<boolean>) => void): void;
12
10
  setAttribute(name: 'checked', value: ''): void;
13
11
  setAttribute(name: 'small', value: ''): void;
package/utils.js CHANGED
@@ -30,7 +30,7 @@ export class NectaryElement extends HTMLElement {
30
30
  attachShadow(options) {
31
31
  return super.attachShadow({
32
32
  mode: 'closed',
33
- delegatesFocus: true,
33
+ delegatesFocus: false,
34
34
  customElements: nectaryRegistry,
35
35
  ...options
36
36
  });