@nectary/components 2.1.1 → 2.1.3
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/accordion-item/index.js +1 -1
- package/action-menu/index.js +1 -1
- package/button/index.js +1 -0
- package/color-menu/index.js +3 -3
- package/dialog/index.js +1 -1
- package/dialog/utils.d.ts +2 -0
- package/dialog/utils.js +18 -0
- package/emoji-picker/index.js +1 -34
- package/icon-button/index.js +1 -0
- package/package.json +1 -1
- package/pop/index.js +60 -5
- package/pop/utils.d.ts +2 -2
- package/pop/utils.js +8 -4
- package/select-button/index.js +1 -0
- package/select-menu/index.js +4 -10
- package/table-row/index.js +1 -1
package/accordion-item/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import '../icon';
|
|
|
2
2
|
import '../title';
|
|
3
3
|
import '../text';
|
|
4
4
|
import { defineCustomElement, getAttribute, getBooleanAttribute, getLiteralAttribute, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateLiteralAttribute } from '../utils';
|
|
5
|
-
const templateHTML = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}#button{all:initial;cursor:pointer;display:flex;align-items:center;gap:8px;box-sizing:border-box;width:100%;height:48px;padding:12px 8px;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button::before{width:8px;height:8px;border-radius:50%;margin-left:2px;margin-right:8px}:host([status=success]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 18px}#dropdown-icon{transform:rotate(0)}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><slot name="icon"></slot><sinch-title id="title" level="3" type="m" ellipsis></sinch-title><sinch-text id="optional" type="m"></sinch-text><sinch-icon id="dropdown-icon" name="keyboard_arrow_down"></sinch-icon></button><div id="content" role="region" aria-labelledby="button"><slot name="content"></slot></div></div>';
|
|
5
|
+
const templateHTML = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}#button{all:initial;cursor:pointer;display:flex;align-items:center;gap:8px;box-sizing:border-box;width:100%;height:48px;padding:12px 8px;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button::before{width:8px;height:8px;border-radius:50%;margin-left:2px;margin-right:8px}:host([status=success]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #button::before{content:"";background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 18px}#dropdown-icon{transform:rotate(0)}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><slot name="icon"></slot><sinch-title id="title" level="3" type="m" ellipsis></sinch-title><sinch-text id="optional" type="m"></sinch-text><sinch-icon id="dropdown-icon" name="keyboard_arrow_down"></sinch-icon></button><div id="content" role="region" aria-labelledby="button"><slot name="content"></slot></div></div>';
|
|
6
6
|
import { statusValues } from './utils';
|
|
7
7
|
const template = document.createElement('template');
|
|
8
8
|
template.innerHTML = templateHTML;
|
package/action-menu/index.js
CHANGED
|
@@ -92,9 +92,9 @@ defineCustomElement('sinch-action-menu', class extends NectaryElement {
|
|
|
92
92
|
case 'Enter':
|
|
93
93
|
case 'Space':
|
|
94
94
|
{
|
|
95
|
+
e.preventDefault();
|
|
95
96
|
const $opt = this.#findSelectedOption();
|
|
96
97
|
if ($opt !== null) {
|
|
97
|
-
e.preventDefault();
|
|
98
98
|
$opt.click();
|
|
99
99
|
}
|
|
100
100
|
break;
|
package/button/index.js
CHANGED
package/color-menu/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getReactEventHandler, getRect, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, subscribeContext } from '../utils';
|
|
1
|
+
import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, getIntegerAttribute, getReactEventHandler, getRect, NectaryElement, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, subscribeContext, isTargetEqual } from '../utils';
|
|
2
2
|
const templateHTML = '<style>:host{display:block;outline:0}#listbox{display:flex;flex-direction:row;flex-wrap:wrap;padding:4px 10px;overflow-y:auto}#listbox.empty{display:none}</style><div id="listbox" role="presentation"><slot id="options"></slot></div>';
|
|
3
3
|
const NUM_COLS_DEFAULT = 5;
|
|
4
4
|
const ITEM_WIDTH = 44;
|
|
@@ -132,7 +132,7 @@ defineCustomElement('sinch-color-menu', class extends NectaryElement {
|
|
|
132
132
|
};
|
|
133
133
|
#onListboxClick = e => {
|
|
134
134
|
const $elem = e.target;
|
|
135
|
-
if (
|
|
135
|
+
if (isTargetEqual(e, this.#$listbox)) {
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
138
|
this.focus();
|
|
@@ -156,9 +156,9 @@ defineCustomElement('sinch-color-menu', class extends NectaryElement {
|
|
|
156
156
|
case 'Space':
|
|
157
157
|
case 'Enter':
|
|
158
158
|
{
|
|
159
|
+
e.preventDefault();
|
|
159
160
|
const $option = this.#findSelectedOption();
|
|
160
161
|
if ($option !== null) {
|
|
161
|
-
e.preventDefault();
|
|
162
162
|
this.#dispatchChangeEvent($option);
|
|
163
163
|
}
|
|
164
164
|
break;
|
package/dialog/index.js
CHANGED
|
@@ -2,9 +2,9 @@ import '../icon-button';
|
|
|
2
2
|
import '../icon';
|
|
3
3
|
import '../stop-events';
|
|
4
4
|
import '../title';
|
|
5
|
-
import { disableScroll, enableScroll } from '../pop/utils';
|
|
6
5
|
import { defineCustomElement, getAttribute, getBooleanAttribute, getRect, isAttrTrue, updateAttribute, getReactEventHandler, NectaryElement, updateBooleanAttribute, setClass, isTargetEqual } from '../utils';
|
|
7
6
|
const templateHTML = '<style>:host{display:contents;--sinch-comp-dialog-max-width:512px;--sinch-comp-dialog-max-height:50vh}#dialog{position:fixed;left:0;right:0;margin:auto;display:flex;flex-direction:column;padding:24px 0;max-width:var(--sinch-comp-dialog-max-width);max-height:unset;border-radius:var(--sinch-comp-dialog-shape-radius);box-sizing:border-box;contain:content;background-color:var(--sinch-comp-dialog-color-default-background-initial);border:none;box-shadow:var(--sinch-comp-dialog-shadow);outline:0}#dialog:not([open]){display:none}dialog::backdrop{background-color:#000;opacity:.55}#header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;margin-bottom:12px;padding:0 24px}#caption{--sinch-global-color-text:var(--sinch-comp-dialog-color-default-title-initial);--sinch-comp-title-font:var(--sinch-comp-dialog-font-title)}#content{min-height:0;overflow:auto;max-height:var(--sinch-comp-dialog-max-height);padding:4px 24px}#action{display:flex;flex-direction:row;justify-content:flex-end;gap:16px;margin-top:20px;padding:0 24px}#action.empty{display:none}#close{position:relative;left:4px;top:-4px;--sinch-global-color-icon:var(--sinch-comp-dialog-color-default-icon-initial)}</style><dialog id="dialog"><div id="header"><sinch-title id="caption" type="m" level="3" ellipsis></sinch-title><sinch-icon-button id="close" size="s"><sinch-icon id="icon-close" slot="icon" name="close"></sinch-icon></sinch-icon-button></div><div id="content"><sinch-stop-events events="close"><slot name="content"></slot></sinch-stop-events></div><div id="action"><sinch-stop-events events="close"><slot name="buttons"></slot></sinch-stop-events></div></dialog>';
|
|
7
|
+
import { disableScroll, enableScroll } from './utils';
|
|
8
8
|
const template = document.createElement('template');
|
|
9
9
|
template.innerHTML = templateHTML;
|
|
10
10
|
defineCustomElement('sinch-dialog', class extends NectaryElement {
|
package/dialog/utils.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const bodyEl = document.body;
|
|
2
|
+
export const disableScroll = () => {
|
|
3
|
+
bodyEl.__dialog_counter__ = (bodyEl.__dialog_counter__ ?? 0) + 1;
|
|
4
|
+
if (bodyEl.__dialog_counter__ === 1) {
|
|
5
|
+
const scrollWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
6
|
+
bodyEl.style.overflow = 'hidden';
|
|
7
|
+
if (scrollWidth > 0) {
|
|
8
|
+
bodyEl.style.setProperty('padding-right', `${scrollWidth}px`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const enableScroll = () => {
|
|
13
|
+
bodyEl.__dialog_counter__ = Math.max(0, (bodyEl.__dialog_counter__ ?? 0) - 1);
|
|
14
|
+
if (bodyEl.__dialog_counter__ === 0) {
|
|
15
|
+
bodyEl.style.overflow = '';
|
|
16
|
+
bodyEl.style.removeProperty('padding-right');
|
|
17
|
+
}
|
|
18
|
+
};
|
package/emoji-picker/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import '../tabs-icon-option';
|
|
|
9
9
|
import '../emoji';
|
|
10
10
|
import '../text';
|
|
11
11
|
import '../icon';
|
|
12
|
-
import { defineCustomElement, getAttribute, getBooleanAttribute, NectaryElement, updateAttribute, updateBooleanAttribute, getReactEventHandler, getRect,
|
|
12
|
+
import { defineCustomElement, getAttribute, getBooleanAttribute, NectaryElement, updateAttribute, updateBooleanAttribute, getReactEventHandler, getRect, debounceTimeout, setClass } from '../utils';
|
|
13
13
|
import dataJson from './data.json';
|
|
14
14
|
const templateHTML = '<style>:host{display:block}#wrapper{width:384px;max-height:504px;display:flex;flex-direction:column;gap:8px;padding:12px 0}#toolbar{display:flex;gap:8px;padding:0 12px}#search{flex:1;min-width:0}#search-clear:not(.active){display:none}#list-wrapper{overflow-y:auto;overflow-x:hidden;width:384px;box-sizing:border-box;scrollbar-gutter:stable}#list{display:flex;flex-wrap:wrap;gap:8px;padding:4px 12px 0;width:384px;box-sizing:border-box}#not-found{display:none;width:100%;height:48px;align-items:center;justify-content:center;pointer-events:none;user-select:none;--sinch-global-color-text:var(--sinch-comp-emoji-picker-color-default-text-not-found);--sinch-comp-text-font:var(--sinch-comp-emoji-picker-font-not-found)}#not-found.active{display:flex}#tabs svg{pointer-events:none;height:var(--sinch-global-size-icon);fill:var(--sinch-global-color-icon)}</style><div id="wrapper"><div id="toolbar"><sinch-input id="search" size="l" aria-label="Search emojis"><sinch-icon id="icon-search" slot="icon" name="search"></sinch-icon><sinch-icon-button id="search-clear" slot="right" aria-label="Clear"><sinch-icon slot="icon" name="close"></sinch-icon></sinch-icon-button></sinch-input><sinch-popover id="skin-popover" orientation="bottom-left" aria-label="Emoji skin tone select"><sinch-icon-button id="skin-button" slot="target" size="l" aria-label="Select emoji skin tones"><sinch-color-swatch id="skin-swatch" slot="icon" name="skintone-default"></sinch-color-swatch></sinch-icon-button><sinch-color-menu id="skin-menu" slot="content" cols="1" value="skintone-default" aria-label="Emoji skin tone menu"><sinch-color-menu-option value="skintone-default"></sinch-color-menu-option><sinch-color-menu-option value="skintone-light"></sinch-color-menu-option><sinch-color-menu-option value="skintone-light-medium"></sinch-color-menu-option><sinch-color-menu-option value="skintone-medium"></sinch-color-menu-option><sinch-color-menu-option value="skintone-medium-dark"></sinch-color-menu-option><sinch-color-menu-option value="skintone-dark"></sinch-color-menu-option></sinch-color-menu></sinch-popover></div><sinch-tabs id="tabs" aria-label="Emoji groups"><sinch-tabs-icon-option id="tab-emotions"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M15.5 11a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm-7 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2ZM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8Zm4.41-6.11a.745.745 0 0 0-1.03.24A3.98 3.98 0 0 1 12 16c-1.38 0-2.64-.7-3.38-1.88a.747.747 0 1 0-1.27.79A5.446 5.446 0 0 0 12 17.5c1.9 0 3.63-.97 4.65-2.58.22-.35.11-.81-.24-1.03Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-people"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 6a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z"/><path d="M15.89 8.11C15.5 7.72 14.83 7 13.53 7h-2.54a5.023 5.023 0 0 1-4.92-4.15.998.998 0 0 0-.98-.85c-.61 0-1.09.54-1 1.14A7.037 7.037 0 0 0 9 8.71V21c0 .55.45 1 1 1s1-.45 1-1v-5h2v5c0 .55.45 1 1 1s1-.45 1-1V10.05l3.24 3.24a.996.996 0 1 0 1.41-1.41l-3.76-3.77Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-animals"><svg slot="icon" viewBox="0 0 24 24"><path d="M17 14c-.24-.24-.44-.49-.65-.75C17.51 11.5 19 8.56 19 5c0-1.95-.74-3-2-3-1.54 0-3.96 2.06-5 5.97C10.96 4.06 8.54 2 7 2 5.74 2 5 3.05 5 5c0 3.56 1.49 6.5 2.65 8.25-.21.26-.41.51-.65.75-.25.25-2 1.39-2 3.5C5 19.98 7.02 22 9.5 22c1.5 0 2.5-.5 2.5-.5s1 .5 2.5.5c2.48 0 4.5-2.02 4.5-4.5 0-2.11-1.75-3.25-2-3.5Zm-.12-9.97c.06.17.12.48.12.97 0 2.84-1.11 5.24-2.07 6.78-.38-.26-.83-.48-1.4-.62.24-4.52 2.44-6.83 3.35-7.13ZM7 5c0-.49.06-.8.12-.97.91.3 3.11 2.61 3.36 7.13-.58.14-1.03.35-1.4.62C8.11 10.24 7 7.84 7 5Zm7.5 15c-1 0-1.8-.33-2.22-.56.42-.18.72-.71.72-.94 0-.28-.45-.5-1-.5s-1 .22-1 .5c0 .23.3.76.72.94-.42.23-1.22.56-2.22.56A2.5 2.5 0 0 1 7 17.5c0-.7.43-1.24 1-1.73.44-.36.61-.52 1.3-1.37.76-.95 1.09-1.4 2.7-1.4s1.94.45 2.7 1.4c.69.85.86 1.01 1.3 1.37.57.49 1 1.03 1 1.73a2.5 2.5 0 0 1-2.5 2.5Zm-.5-4c0 .41-.22.75-.5.75s-.5-.34-.5-.75.22-.75.5-.75.5.34.5.75Zm-3 0c0 .41-.22.75-.5.75s-.5-.34-.5-.75.22-.75.5-.75.5.34.5.75Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-food"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 19H3c-.55 0-1 .45-1 1s.45 1 1 1h16c.55 0 1-.45 1-1s-.45-1-1-1Zm1-16H9v2.4l1.81 1.45c.12.09.19.24.19.39v4.26c0 .28-.22.5-.5.5h-4c-.28 0-.5-.22-.5-.5V7.24c0-.15.07-.3.19-.39L8 5.4V3H6c-1.1 0-2 .9-2 2v8c0 2.21 1.79 4 4 4h6c2.21 0 4-1.79 4-4v-3h2c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2Zm0 5h-2V5h2v3Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-travel"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m21.99 14.77-1.43-4.11c-.14-.4-.52-.66-.97-.66H12.4c-.46 0-.83.26-.98.66L10 14.77v5.24c0 .55.45.99 1 .99s1-.45 1-1v-1h8v1a1 1 0 0 0 2 .01l-.01-5.24Zm-10.38-1.43.69-2c.05-.2.24-.34.46-.34h6.48c.21 0 .4.14.47.34l.69 2a.5.5 0 0 1-.47.66h-7.85a.5.5 0 0 1-.47-.66Zm.38 3.66c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1Zm8 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1Z"/><path d="M14 4.5V9h1V4c0-.55-.45-1-1-1H8c-.55 0-1 .45-1 1v4H3c-.55 0-1 .45-1 1v12h1V9.5c0-.28.22-.5.5-.5h4c.28 0 .5-.22.5-.5v-4c0-.28.22-.5.5-.5h5c.28 0 .5.22.5.5Z"/><path d="M7 11H5v2h2v-2Zm5-6h-2v2h2V5ZM7 15H5v2h2v-2Zm0 4H5v2h2v-2Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-sports"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19.52 2.49C17.18.15 12.9.62 9.97 3.55c-1.6 1.6-2.52 3.87-2.54 5.46-.02 1.58.26 3.89-1.35 5.5l-3.54 3.53c-.39.39-.39 1.02 0 1.42.39.39 1.02.39 1.42 0l3.53-3.54c1.61-1.61 3.92-1.33 5.5-1.35 1.58-.02 3.86-.94 5.46-2.54 2.93-2.92 3.41-7.2 1.07-9.54Zm-9.2 9.19c-1.53-1.53-1.05-4.61 1.06-6.72 2.11-2.11 5.18-2.59 6.72-1.06 1.53 1.53 1.05 4.61-1.06 6.72-2.11 2.11-5.18 2.59-6.72 1.06ZM18 17c.53 0 1.04.21 1.41.59.78.78.78 2.05 0 2.83-.37.37-.88.58-1.41.58-.53 0-1.04-.21-1.41-.59-.78-.78-.78-2.05 0-2.83.37-.37.88-.58 1.41-.58Zm0-2a3.998 3.998 0 0 0-2.83 6.83c.78.78 1.81 1.17 2.83 1.17a3.998 3.998 0 0 0 2.83-6.83A3.998 3.998 0 0 0 18 15Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-objects"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 3c-.46 0-.93.04-1.4.14-2.76.53-4.96 2.76-5.48 5.52-.48 2.61.48 5.01 2.22 6.56.43.38.66.91.66 1.47V19c0 1.1.9 2 2 2h.28a1.98 1.98 0 0 0 3.44 0H14c1.1 0 2-.9 2-2v-2.31c0-.55.22-1.09.64-1.46A6.956 6.956 0 0 0 19 10c0-3.87-3.13-7-7-7Zm.5 11h-1v-2.59L9.67 9.59l.71-.71L12 10.5l1.62-1.62.71.71-1.83 1.83V14Zm1 5c-.01 0-.02-.01-.03-.01V19h-2.94v-.01c-.01 0-.02.01-.03.01-.28 0-.5-.22-.5-.5s.22-.5.5-.5c.01 0 .02.01.03.01V18h2.94v.01c.01 0 .02-.01.03-.01.28 0 .5.22.5.5s-.22.5-.5.5Zm0-2h-3c-.28 0-.5-.22-.5-.5s.22-.5.5-.5h3c.28 0 .5.22.5.5s-.22.5-.5.5Z"/></svg></sinch-tabs-icon-option><sinch-tabs-icon-option id="tab-symbols"><svg slot="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M10 5H4c-.55 0-1 .45-1 1s.45 1 1 1h2v3c0 .55.45 1 1 1s1-.45 1-1V7h2c.55 0 1-.45 1-1s-.45-1-1-1Zm0-3H4c-.55 0-1 .45-1 1s.45 1 1 1h6c.55 0 1-.45 1-1s-.45-1-1-1Zm10.89 11.11a.996.996 0 0 0-1.41 0l-6.36 6.36a.996.996 0 1 0 1.41 1.41l6.36-6.36a.996.996 0 0 0 0-1.41ZM14.5 16a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm5 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm-4-10A2.5 2.5 0 0 0 18 8.5V4h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1v3.51c-.42-.32-.93-.51-1.5-.51a2.5 2.5 0 0 0 0 5Zm-5.05 7.09a.996.996 0 1 0-1.41-1.41l-.71.71-.71-.71.35-.35a2.499 2.499 0 0 0-1.77-4.27 2.499 2.499 0 0 0-1.77 4.27l.35.35-1.06 1.06c-.98.98-.98 2.56 0 3.54.5.48 1.14.72 1.78.72.64 0 1.28-.24 1.77-.73l1.06-1.06.71.71a.996.996 0 1 0 1.41-1.41l-.71-.71.71-.71Zm-4.6-3.89a.5.5 0 0 1 .35-.15.5.5 0 0 1 .35.15c.19.2.19.51 0 .71l-.35.35-.35-.36a.5.5 0 0 1-.15-.35.5.5 0 0 1 .15-.35Zm0 5.65a.5.5 0 0 1-.35.15.5.5 0 0 1-.35-.15.5.5 0 0 1-.15-.35.5.5 0 0 1 .15-.35l1.06-1.06.71.71-1.07 1.05Z"/></svg></sinch-tabs-icon-option></sinch-tabs><div id="list-wrapper"><div id="list"></div><div id="not-found"><sinch-text type="m">No results</sinch-text></div></div></div>';
|
|
15
15
|
const groupLabels = ['Emotions', 'People', 'Animals and nature', 'Food and drinks', 'Travel and places', 'Sports and activities', 'Objects', 'Symbols and flags'];
|
|
@@ -63,9 +63,6 @@ defineCustomElement('sinch-emoji-picker', class extends NectaryElement {
|
|
|
63
63
|
this.#$searchClearButton.addEventListener('-click', this.#onSearchClearClick, {
|
|
64
64
|
signal
|
|
65
65
|
});
|
|
66
|
-
this.addEventListener('keydown', this.#onListboxKeyDown, {
|
|
67
|
-
signal
|
|
68
|
-
});
|
|
69
66
|
this.#$skinButton.addEventListener('-click', this.#onSkinButtonClick, {
|
|
70
67
|
signal
|
|
71
68
|
});
|
|
@@ -81,8 +78,6 @@ defineCustomElement('sinch-emoji-picker', class extends NectaryElement {
|
|
|
81
78
|
this.addEventListener('-change', this.#onChangeReactHandler, {
|
|
82
79
|
signal
|
|
83
80
|
});
|
|
84
|
-
subscribeContext(this, 'keydown', this.#onContextKeyDown, signal);
|
|
85
|
-
subscribeContext(this, 'visibility', this.#onContextVisibility, signal);
|
|
86
81
|
this.#updateTabs();
|
|
87
82
|
this.#updateEmojis();
|
|
88
83
|
}
|
|
@@ -118,34 +113,6 @@ defineCustomElement('sinch-emoji-picker', class extends NectaryElement {
|
|
|
118
113
|
detail: value
|
|
119
114
|
}));
|
|
120
115
|
};
|
|
121
|
-
#onContextKeyDown = e => {
|
|
122
|
-
this.#handleKeydown(e.detail);
|
|
123
|
-
};
|
|
124
|
-
#onContextVisibility = e => {
|
|
125
|
-
if (e.detail) {} else {}
|
|
126
|
-
};
|
|
127
|
-
#onListboxKeyDown = e => {
|
|
128
|
-
this.#handleKeydown(e);
|
|
129
|
-
};
|
|
130
|
-
#handleKeydown(e) {
|
|
131
|
-
switch (e.code) {
|
|
132
|
-
case 'Space':
|
|
133
|
-
case 'Enter':
|
|
134
|
-
{
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
case 'ArrowUp':
|
|
138
|
-
{
|
|
139
|
-
e.preventDefault();
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
case 'ArrowDown':
|
|
143
|
-
{
|
|
144
|
-
e.preventDefault();
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
116
|
#onTabsChange = e => {
|
|
150
117
|
const value = e.detail;
|
|
151
118
|
updateAttribute(this.#$tabs, 'value', value);
|
package/icon-button/index.js
CHANGED
package/package.json
CHANGED
package/pop/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCustomElement, getBooleanAttribute, getLiteralAttribute, getRect, isAttrTrue, updateLiteralAttribute, getReactEventHandler, updateBooleanAttribute, NectaryElement, throttleAnimationFrame, isElementFocused, updateIntegerAttribute, getIntegerAttribute, getFirstFocusableElement, getFirstSlotElement, Context, subscribeContext, isTargetEqual } from '../utils';
|
|
2
2
|
const templateHTML = '<style>:host{display:contents;position:relative}dialog{position:fixed;left:0;top: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}#content{position:relative;z-index:1}#target-open{display:flex;flex-direction:column;position:absolute;left:0;top:0}#focus{display:none;position:absolute;width:0;height:0}</style><slot id="target" name="target" aria-haspopup="dialog" aria-expanded="false"></slot><div id="focus"></div><dialog id="dialog"><div id="target-open"><slot name="target-open"></slot></div><div id="content"><slot name="content"></slot></div></dialog>';
|
|
3
|
-
import {
|
|
3
|
+
import { disableOverscroll, enableOverscroll, orientationValues } from './utils';
|
|
4
4
|
const template = document.createElement('template');
|
|
5
5
|
template.innerHTML = templateHTML;
|
|
6
6
|
defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
@@ -17,6 +17,8 @@ defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
|
17
17
|
#keydownContext;
|
|
18
18
|
#visibilityContext;
|
|
19
19
|
#targetStyleValue = null;
|
|
20
|
+
#modalWidth = 0;
|
|
21
|
+
#modalHeight = 0;
|
|
20
22
|
constructor() {
|
|
21
23
|
super();
|
|
22
24
|
const shadowRoot = this.attachShadow();
|
|
@@ -201,7 +203,10 @@ defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
205
|
}
|
|
204
|
-
|
|
206
|
+
disableOverscroll();
|
|
207
|
+
window.addEventListener('scroll', this.#updatePosition, {
|
|
208
|
+
passive: false
|
|
209
|
+
});
|
|
205
210
|
window.addEventListener('resize', this.#onResize);
|
|
206
211
|
requestAnimationFrame(() => {
|
|
207
212
|
if (this.isConnected && this.#$dialog.open) {
|
|
@@ -242,14 +247,18 @@ defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
|
242
247
|
if (this.#targetActiveElement !== null) {
|
|
243
248
|
if (!isElementFocused(this.#targetActiveElement)) {
|
|
244
249
|
this.#$targetSlot.addEventListener('focus', this.#stopEventPropagation, true);
|
|
245
|
-
this.#targetActiveElement.focus(
|
|
250
|
+
this.#targetActiveElement.focus({
|
|
251
|
+
preventScroll: true
|
|
252
|
+
});
|
|
246
253
|
this.#$targetSlot.removeEventListener('focus', this.#stopEventPropagation, true);
|
|
247
254
|
if (!isElementFocused(this.#targetActiveElement)) {
|
|
248
255
|
const $targetEl = this.#targetActiveElement;
|
|
249
256
|
requestAnimationFrame(() => {
|
|
250
257
|
if (this.isConnected && !this.#$dialog.open) {
|
|
251
258
|
this.#$targetSlot.addEventListener('focus', this.#stopEventPropagation, true);
|
|
252
|
-
$targetEl.focus(
|
|
259
|
+
$targetEl.focus({
|
|
260
|
+
preventScroll: true
|
|
261
|
+
});
|
|
253
262
|
this.#$targetSlot.removeEventListener('focus', this.#stopEventPropagation, true);
|
|
254
263
|
}
|
|
255
264
|
});
|
|
@@ -257,14 +266,58 @@ defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
|
257
266
|
this.#targetActiveElement = null;
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
|
-
|
|
269
|
+
enableOverscroll();
|
|
261
270
|
this.#resizeThrottle.cancel();
|
|
262
271
|
window.removeEventListener('resize', this.#onResize);
|
|
272
|
+
window.removeEventListener('scroll', this.#updatePosition);
|
|
263
273
|
this.#$contentSlot.removeEventListener('slotchange', this.#onContentSlotChange);
|
|
264
274
|
}
|
|
265
275
|
#onResize = () => {
|
|
266
276
|
this.#resizeThrottle.fn();
|
|
267
277
|
};
|
|
278
|
+
#updatePosition = () => {
|
|
279
|
+
const targetRect = this.modal ? this.#getTargetRect() : this.#$targetWrapper.getBoundingClientRect();
|
|
280
|
+
const orient = this.orientation;
|
|
281
|
+
const modalWidth = this.#modalWidth;
|
|
282
|
+
const modalHeight = this.#modalHeight;
|
|
283
|
+
const inset = this.inset;
|
|
284
|
+
let xPos = 0;
|
|
285
|
+
let yPos = 0;
|
|
286
|
+
if (orient === 'bottom-right' || orient === 'top-right' || orient === 'top-stretch' || orient === 'bottom-stretch') {
|
|
287
|
+
xPos = targetRect.x;
|
|
288
|
+
}
|
|
289
|
+
if (orient === 'bottom-left' || orient === 'top-left') {
|
|
290
|
+
xPos = targetRect.x + targetRect.width - modalWidth;
|
|
291
|
+
}
|
|
292
|
+
if (orient === 'bottom-center' || orient === 'top-center') {
|
|
293
|
+
xPos = targetRect.x + targetRect.width / 2 - modalWidth / 2;
|
|
294
|
+
}
|
|
295
|
+
if (orient === 'center-right') {
|
|
296
|
+
xPos = targetRect.x + targetRect.width;
|
|
297
|
+
}
|
|
298
|
+
if (orient === 'center-left') {
|
|
299
|
+
xPos = targetRect.x - modalWidth;
|
|
300
|
+
}
|
|
301
|
+
if (orient === 'bottom-left' || orient === 'bottom-right' || orient === 'bottom-stretch' || orient === 'bottom-center') {
|
|
302
|
+
yPos = targetRect.y + targetRect.height;
|
|
303
|
+
}
|
|
304
|
+
if (orient === 'top-left' || orient === 'top-right' || orient === 'top-stretch' || orient === 'top-center') {
|
|
305
|
+
yPos = targetRect.y - modalHeight;
|
|
306
|
+
}
|
|
307
|
+
if (orient === 'center-left' || orient === 'center-right') {
|
|
308
|
+
yPos = targetRect.y + targetRect.height / 2 - modalHeight / 2;
|
|
309
|
+
}
|
|
310
|
+
const clampedXPos = Math.max(inset, Math.min(xPos, window.innerWidth - modalWidth - inset));
|
|
311
|
+
const clampedYPos = Math.max(inset, Math.min(yPos, window.innerHeight - modalHeight - inset));
|
|
312
|
+
this.#$dialog.style.setProperty('left', `${clampedXPos}px`);
|
|
313
|
+
this.#$dialog.style.setProperty('top', `${clampedYPos}px`);
|
|
314
|
+
if (!this.modal) {
|
|
315
|
+
const targetLeftPos = targetRect.x - clampedXPos;
|
|
316
|
+
const targetTopPos = targetRect.y - clampedYPos;
|
|
317
|
+
this.#$targetOpenWrapper.style.setProperty('left', `${targetLeftPos}px`);
|
|
318
|
+
this.#$targetOpenWrapper.style.setProperty('top', `${targetTopPos}px`);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
268
321
|
#updateOrientation = () => {
|
|
269
322
|
this.#$dialog.style.setProperty('width', 'max-content');
|
|
270
323
|
const targetRect = this.#getTargetRect();
|
|
@@ -276,6 +329,8 @@ defineCustomElement('sinch-pop', class extends NectaryElement {
|
|
|
276
329
|
const inset = this.inset;
|
|
277
330
|
let xPos = 0;
|
|
278
331
|
let yPos = 0;
|
|
332
|
+
this.#modalHeight = modalHeight;
|
|
333
|
+
this.#modalWidth = modalWidth;
|
|
279
334
|
if (orient === 'bottom-right' || orient === 'top-right' || orient === 'top-stretch' || orient === 'bottom-stretch') {
|
|
280
335
|
xPos = targetRect.x;
|
|
281
336
|
}
|
package/pop/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { TSinchPopOrientation } from './types';
|
|
2
2
|
export declare const orientationValues: readonly TSinchPopOrientation[];
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
3
|
+
export declare const disableOverscroll: () => void;
|
|
4
|
+
export declare const enableOverscroll: () => void;
|
package/pop/utils.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
export const orientationValues = ['top-left', 'top-right', 'bottom-left', 'bottom-right', 'bottom-stretch', 'bottom-center', 'top-stretch', 'top-center', 'center-left', 'center-right'];
|
|
2
2
|
const bodyEl = document.body;
|
|
3
|
-
export const
|
|
4
|
-
bodyEl.style.overflow = 'hidden';
|
|
3
|
+
export const disableOverscroll = () => {
|
|
5
4
|
bodyEl.__pop_counter__ = (bodyEl.__pop_counter__ ?? 0) + 1;
|
|
5
|
+
if (bodyEl.__pop_counter__ === 1) {
|
|
6
|
+
bodyEl.style.setProperty('overscroll-behavior', 'none');
|
|
7
|
+
document.documentElement.style.setProperty('overscroll-behavior', 'none');
|
|
8
|
+
}
|
|
6
9
|
};
|
|
7
|
-
export const
|
|
10
|
+
export const enableOverscroll = () => {
|
|
8
11
|
bodyEl.__pop_counter__ = Math.max(0, (bodyEl.__pop_counter__ ?? 0) - 1);
|
|
9
12
|
if (bodyEl.__pop_counter__ === 0) {
|
|
10
|
-
|
|
13
|
+
bodyEl.style.removeProperty('overscroll-behavior');
|
|
14
|
+
document.documentElement.style.removeProperty('overscroll-behavior');
|
|
11
15
|
}
|
|
12
16
|
};
|
package/select-button/index.js
CHANGED
package/select-menu/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import '../input';
|
|
|
2
2
|
import '../icon-button';
|
|
3
3
|
import '../icon';
|
|
4
4
|
import '../text';
|
|
5
|
-
import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, unpackCsv, getFirstCsvValue, getIntegerAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateCsv, updateExplicitBooleanAttribute, updateIntegerAttribute, debounceTimeout, setClass, subscribeContext, hasClass } from '../utils';
|
|
5
|
+
import { attrValueToPixels, defineCustomElement, getAttribute, getBooleanAttribute, unpackCsv, getFirstCsvValue, getIntegerAttribute, getReactEventHandler, isAttrTrue, NectaryElement, updateAttribute, updateBooleanAttribute, updateCsv, updateExplicitBooleanAttribute, updateIntegerAttribute, debounceTimeout, setClass, subscribeContext, hasClass, isTargetEqual } from '../utils';
|
|
6
6
|
const templateHTML = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto}#search{display:none;margin:10px}#search.active{display:block}#search-clear:not(.active){display:none}#not-found{display:flex;align-items:center;justify-content:center;width:100%;height:30px;margin-bottom:10px;pointer-events:none;user-select:none;--sinch-comp-text-font:var(--sinch-comp-select-menu-font-not-found-text);--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-not-found-text-initial)}#not-found:not(.active){display:none}::slotted(.hidden){display:none}</style><sinch-input id="search" size="s" placeholder="Search"><sinch-icon id="icon-search" slot="icon" name="search"></sinch-icon><sinch-icon-button id="search-clear" slot="right"><sinch-icon slot="icon" name="close"></sinch-icon></sinch-icon-button></sinch-input><div id="not-found"><sinch-text type="m">No results</sinch-text></div><div id="listbox" role="presentation"><slot></slot></div>';
|
|
7
7
|
const ITEM_HEIGHT = 40;
|
|
8
8
|
const NUM_ITEMS_SEARCH = 7;
|
|
@@ -39,7 +39,6 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
|
|
|
39
39
|
this.addEventListener('keydown', this.#onListboxKeyDown, options);
|
|
40
40
|
this.addEventListener('focus', this.#onFocus, options);
|
|
41
41
|
this.addEventListener('blur', this.#onListboxBlur, options);
|
|
42
|
-
this.#$listbox.addEventListener('mousedown', this.#onListboxMousedown, options);
|
|
43
42
|
this.#$listbox.addEventListener('click', this.#onListboxClick, options);
|
|
44
43
|
this.#$search.addEventListener('-change', this.#onSearchChange, options);
|
|
45
44
|
this.#$searchClear.addEventListener('-click', this.#onSearchClearClick, options);
|
|
@@ -109,20 +108,15 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
|
|
|
109
108
|
this.#$search.focus();
|
|
110
109
|
}
|
|
111
110
|
};
|
|
112
|
-
#onListboxMousedown = e => {
|
|
113
|
-
const $elem = e.target;
|
|
114
|
-
if (!getBooleanAttribute($elem, 'disabled')) {
|
|
115
|
-
this.#dispatchChangeEvent($elem);
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
111
|
#onListboxBlur = () => {
|
|
119
112
|
this.#selectOption(null);
|
|
120
113
|
};
|
|
121
114
|
#onListboxClick = e => {
|
|
122
115
|
const $elem = e.target;
|
|
123
116
|
this.focus();
|
|
124
|
-
if (!getBooleanAttribute($elem, 'disabled')) {
|
|
117
|
+
if (!isTargetEqual(e, this.#$listbox) && !getBooleanAttribute($elem, 'disabled')) {
|
|
125
118
|
this.#selectOption($elem);
|
|
119
|
+
this.#dispatchChangeEvent($elem);
|
|
126
120
|
}
|
|
127
121
|
};
|
|
128
122
|
#onSearchChange = e => {
|
|
@@ -167,9 +161,9 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
|
|
|
167
161
|
case 'Space':
|
|
168
162
|
case 'Enter':
|
|
169
163
|
{
|
|
164
|
+
e.preventDefault();
|
|
170
165
|
const $option = this.#findSelectedOption();
|
|
171
166
|
if ($option !== null) {
|
|
172
|
-
e.preventDefault();
|
|
173
167
|
this.#dispatchChangeEvent($option);
|
|
174
168
|
}
|
|
175
169
|
break;
|
package/table-row/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineCustomElement, getBooleanAttribute, isAttrTrue, NectaryElement, updateBooleanAttribute } from '../utils';
|
|
2
|
-
const templateHTML = '<style>:host{display:table-row;background-color:var(--sinch-comp-table-color-row-default-background-initial)}:host([selected]){background-color:var(--sinch-comp-table-color-row-checked-background-initial)}:host(:hover){background-color:var(--sinch-comp-table-color-row-default-background-hover)}:host([sticky]) ::slotted(sinch-table-head-cell){position:sticky;top:0;z-index:1;background-color:var(--sinch-comp-table-color-row-default-background-sticky)}</style><slot></slot>';
|
|
2
|
+
const templateHTML = '<style>:host{display:table-row;background-color:var(--sinch-comp-table-color-row-default-background-initial)}:host([selected]){background-color:var(--sinch-comp-table-color-row-checked-background-initial)}:host(:hover){background-color:var(--sinch-comp-table-color-row-default-background-hover)}:host([sticky]) ::slotted(sinch-table-head-cell){position:sticky;top:0;z-index:1;background-color:var(--sinch-comp-table-color-row-default-background-sticky)}:host(:last-child) ::slotted(sinch-table-cell){border-bottom:none}</style><slot></slot>';
|
|
3
3
|
const template = document.createElement('template');
|
|
4
4
|
template.innerHTML = templateHTML;
|
|
5
5
|
defineCustomElement('sinch-table-row', class extends NectaryElement {
|