@nectary/components 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skeleton/index.d.ts +11 -0
- package/skeleton/index.js +75 -0
- package/skeleton/types.d.ts +9 -0
- package/skeleton/types.js +1 -0
- package/skeleton-item/index.d.ts +11 -0
- package/skeleton-item/index.js +38 -0
- package/skeleton-item/types.d.ts +13 -0
- package/skeleton-item/types.js +1 -0
- package/theme/chip.css +6 -0
- package/theme/tag.css +6 -0
- package/toast-manager/index.js +3 -3
- package/tooltip/index.js +2 -2
- package/utils/dom.d.ts +1 -0
- package/utils/dom.js +2 -1
- package/utils/index.d.ts +1 -0
- package/utils/index.js +2 -1
- package/utils/uid.d.ts +1 -0
- package/utils/uid.js +13 -0
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TSinchSkeletonElement, TSinchSkeletonReact } from './types';
|
|
2
|
+
declare global {
|
|
3
|
+
namespace JSX {
|
|
4
|
+
interface IntrinsicElements {
|
|
5
|
+
'sinch-skeleton': TSinchSkeletonReact;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
interface HTMLElementTagNameMap {
|
|
9
|
+
'sinch-skeleton': TSinchSkeletonElement;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { defineCustomElement, getUid, isAttrTrue, NectaryElement, shouldReduceMotion } from '../utils';
|
|
2
|
+
const templateHTML = '<style>:host{display:block}#wrapper{position:relative;display:flex;flex-direction:column;gap:16px;height:100%;box-sizing:border-box;overflow:hidden}:host([card]:not([card=false]))>#wrapper{padding:16px;background-color:var(--sinch-color-snow-100);border-radius:var(--sinch-shape-radius-l);border:1px solid var(--sinch-color-snow-500)}#shimmer{position:absolute;inset:0;background-image:linear-gradient(90deg,transparent 0,var(--sinch-color-snow-400) 100px,transparent 200px);clip-path:url("#clip")}#svg{display:block;width:0;height:0}</style><svg id="svg"><defs><clipPath id="clip"></clipPath></defs></svg><div id="wrapper"><slot></slot><div id="shimmer"></div></div>';
|
|
3
|
+
const template = document.createElement('template');
|
|
4
|
+
template.innerHTML = templateHTML;
|
|
5
|
+
const ANIMATION_DURATION = 2000;
|
|
6
|
+
const BORDER_WIDTH = 1;
|
|
7
|
+
defineCustomElement('sinch-skeleton', class extends NectaryElement {
|
|
8
|
+
#animation = null;
|
|
9
|
+
#shimmer;
|
|
10
|
+
#controller = null;
|
|
11
|
+
#clip;
|
|
12
|
+
#borderWidth = 0;
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
const shadowRoot = this.attachShadow();
|
|
16
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
17
|
+
this.#shimmer = shadowRoot.querySelector('#shimmer');
|
|
18
|
+
this.#clip = shadowRoot.querySelector('#clip');
|
|
19
|
+
}
|
|
20
|
+
connectedCallback() {
|
|
21
|
+
const id = getUid();
|
|
22
|
+
this.#shimmer.style.setProperty('clip-path', `url(#${id})`);
|
|
23
|
+
this.#clip.setAttribute('id', id);
|
|
24
|
+
this.#controller = new AbortController();
|
|
25
|
+
if (!shouldReduceMotion()) {
|
|
26
|
+
this.addEventListener('skeleton-item-data', this.#onSkeletonItemData, {
|
|
27
|
+
signal: this.#controller.signal
|
|
28
|
+
});
|
|
29
|
+
this.#updateAnimation();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
disconnectedCallback() {
|
|
33
|
+
this.#animation.cancel();
|
|
34
|
+
this.#animation = null;
|
|
35
|
+
this.#controller.abort();
|
|
36
|
+
this.#controller = null;
|
|
37
|
+
}
|
|
38
|
+
static get observedAttributes() {
|
|
39
|
+
return ['card'];
|
|
40
|
+
}
|
|
41
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
42
|
+
if (oldVal === newVal) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
switch (name) {
|
|
46
|
+
case 'card':
|
|
47
|
+
{
|
|
48
|
+
this.#borderWidth = isAttrTrue(newVal) ? BORDER_WIDTH : 0;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
#updateAnimation() {
|
|
54
|
+
const bb = this.getBoundingClientRect();
|
|
55
|
+
const bgWidth = bb.width * 4;
|
|
56
|
+
this.#shimmer.style.setProperty('background-size', `${bgWidth}px`);
|
|
57
|
+
this.#animation = this.#shimmer.animate({
|
|
58
|
+
backgroundPosition: [`0px`, `${bgWidth}px`]
|
|
59
|
+
}, {
|
|
60
|
+
duration: ANIMATION_DURATION,
|
|
61
|
+
iterations: Infinity
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
#onSkeletonItemData = e => {
|
|
65
|
+
const bb = this.getBoundingClientRect();
|
|
66
|
+
const data = e.detail;
|
|
67
|
+
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
68
|
+
rect.setAttribute('x', (data.x - bb.x - this.#borderWidth).toString());
|
|
69
|
+
rect.setAttribute('y', (data.y - bb.y - this.#borderWidth).toString());
|
|
70
|
+
rect.setAttribute('width', data.width.toString());
|
|
71
|
+
rect.setAttribute('height', data.height.toString());
|
|
72
|
+
rect.setAttribute('rx', data.radius.toString());
|
|
73
|
+
this.#clip.appendChild(rect);
|
|
74
|
+
};
|
|
75
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TSinchElementReact } from '../types';
|
|
2
|
+
export type TSinchSkeletonElement = HTMLElement & {
|
|
3
|
+
/** Card like container */
|
|
4
|
+
setAttribute(name: 'card', value: ''): void;
|
|
5
|
+
};
|
|
6
|
+
export type TSinchSkeletonReact = TSinchElementReact<TSinchSkeletonElement> & {
|
|
7
|
+
/** Card like container */
|
|
8
|
+
card?: boolean;
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TSinchSkeletonItemElement, TSinchSkeletonItemReact } from './types';
|
|
2
|
+
declare global {
|
|
3
|
+
namespace JSX {
|
|
4
|
+
interface IntrinsicElements {
|
|
5
|
+
'sinch-skeleton-item': TSinchSkeletonItemReact;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
interface HTMLElementTagNameMap {
|
|
9
|
+
'sinch-skeleton-item': TSinchSkeletonItemElement;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineCustomElement, getCssVar, NectaryElement, attrValueToInteger, shouldReduceMotion } from '../utils';
|
|
2
|
+
const templateHTML = '<style>:host{display:block;height:var(--sinch-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([size=xs]){height:var(--sinch-size-xs);--sinch-shape-radius:var(--sinch-shape-radius-xs)}:host([size="s"]){height:var(--sinch-size-s);--sinch-shape-radius:var(--sinch-shape-radius-s)}:host([size="m"]){height:var(--sinch-size-m);--sinch-shape-radius:var(--sinch-shape-radius-m)}:host([size="l"]){height:var(--sinch-size-l);--sinch-shape-radius:var(--sinch-shape-radius-l)}#content{height:100%;background-color:var(--sinch-color-snow-500);border-radius:var(--sinch-shape-radius)}</style><div id="content"></div>';
|
|
3
|
+
const template = document.createElement('template');
|
|
4
|
+
template.innerHTML = templateHTML;
|
|
5
|
+
defineCustomElement('sinch-skeleton-item', class extends NectaryElement {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
const shadowRoot = this.attachShadow();
|
|
9
|
+
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
10
|
+
}
|
|
11
|
+
connectedCallback() {
|
|
12
|
+
if (!shouldReduceMotion()) {
|
|
13
|
+
requestAnimationFrame(() => {
|
|
14
|
+
const {
|
|
15
|
+
x,
|
|
16
|
+
y,
|
|
17
|
+
width,
|
|
18
|
+
height
|
|
19
|
+
} = this.getBoundingClientRect();
|
|
20
|
+
const radiusStr = getCssVar(this, '--sinch-shape-radius') ?? '0';
|
|
21
|
+
const radius = attrValueToInteger(radiusStr, {
|
|
22
|
+
min: 0,
|
|
23
|
+
defaultValue: 0
|
|
24
|
+
});
|
|
25
|
+
this.dispatchEvent(new CustomEvent('skeleton-item-data', {
|
|
26
|
+
bubbles: true,
|
|
27
|
+
detail: {
|
|
28
|
+
x,
|
|
29
|
+
y,
|
|
30
|
+
width,
|
|
31
|
+
height,
|
|
32
|
+
radius
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TRect, TSinchElementReact } from '../types';
|
|
2
|
+
import type { TSinchSizeEx } from '../utils/size';
|
|
3
|
+
export type TSinchSkeletonItemBoundingBox = TRect & {
|
|
4
|
+
radius: number;
|
|
5
|
+
};
|
|
6
|
+
export type TSinchSkeletonItemElement = HTMLElement & {
|
|
7
|
+
/** Size */
|
|
8
|
+
setAttribute(name: 'size', value: TSinchSizeEx): void;
|
|
9
|
+
};
|
|
10
|
+
export type TSinchSkeletonItemReact = TSinchElementReact<TSinchSkeletonItemElement> & {
|
|
11
|
+
/** Size */
|
|
12
|
+
size?: TSinchSizeEx;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/theme/chip.css
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
--sinch-chip-color-light-violet-fg: var(--sinch-color-violet-700);
|
|
19
19
|
--sinch-chip-color-light-yellow-bg: var(--sinch-color-bolt-200);
|
|
20
20
|
--sinch-chip-color-light-yellow-fg: var(--sinch-color-bolt-700);
|
|
21
|
+
--sinch-chip-color-light-red-bg: var(--sinch-color-jasper-200);
|
|
22
|
+
--sinch-chip-color-light-red-fg: var(--sinch-color-jasper-700);
|
|
21
23
|
--sinch-chip-color-dark-blue-bg: var(--sinch-color-night-700);
|
|
22
24
|
--sinch-chip-color-dark-blue-fg: var(--sinch-color-night-200);
|
|
23
25
|
--sinch-chip-color-dark-brown-bg: var(--sinch-color-mud-700);
|
|
@@ -34,6 +36,8 @@
|
|
|
34
36
|
--sinch-chip-color-dark-violet-fg: var(--sinch-color-violet-200);
|
|
35
37
|
--sinch-chip-color-dark-yellow-bg: var(--sinch-color-bolt-700);
|
|
36
38
|
--sinch-chip-color-dark-yellow-fg: var(--sinch-color-bolt-200);
|
|
39
|
+
--sinch-chip-color-dark-red-bg: var(--sinch-color-jasper-700);
|
|
40
|
+
--sinch-chip-color-dark-red-fg: var(--sinch-color-jasper-200);
|
|
37
41
|
--sinch-chip-color-blue-bg: var(--sinch-color-night-400);
|
|
38
42
|
--sinch-chip-color-blue-fg: var(--sinch-color-snow-100);
|
|
39
43
|
--sinch-chip-color-brown-bg: var(--sinch-color-mud-400);
|
|
@@ -50,6 +54,8 @@
|
|
|
50
54
|
--sinch-chip-color-violet-fg: var(--sinch-color-stormy-500);
|
|
51
55
|
--sinch-chip-color-yellow-bg: var(--sinch-color-bolt-400);
|
|
52
56
|
--sinch-chip-color-yellow-fg: var(--sinch-color-stormy-500);
|
|
57
|
+
--sinch-chip-color-red-bg: var(--sinch-color-jasper-400);
|
|
58
|
+
--sinch-chip-color-red-fg: var(--sinch-color-stormy-500);
|
|
53
59
|
--sinch-chip-color-celtic-bg: var(--sinch-color-feedback-info-bg);
|
|
54
60
|
--sinch-chip-color-celtic-fg: var(--sinch-color-feedback-info-contrast);
|
|
55
61
|
--sinch-chip-color-olive-bg: var(--sinch-color-feedback-success-bg);
|
package/theme/tag.css
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
--sinch-tag-color-light-violet-fg: var(--sinch-color-violet-700);
|
|
19
19
|
--sinch-tag-color-light-yellow-bg: var(--sinch-color-bolt-200);
|
|
20
20
|
--sinch-tag-color-light-yellow-fg: var(--sinch-color-bolt-700);
|
|
21
|
+
--sinch-tag-color-light-red-bg: var(--sinch-color-jasper-200);
|
|
22
|
+
--sinch-tag-color-light-red-fg: var(--sinch-color-jasper-700);
|
|
21
23
|
--sinch-tag-color-dark-blue-bg: var(--sinch-color-night-700);
|
|
22
24
|
--sinch-tag-color-dark-blue-fg: var(--sinch-color-night-200);
|
|
23
25
|
--sinch-tag-color-dark-brown-bg: var(--sinch-color-mud-700);
|
|
@@ -34,6 +36,8 @@
|
|
|
34
36
|
--sinch-tag-color-dark-violet-fg: var(--sinch-color-violet-200);
|
|
35
37
|
--sinch-tag-color-dark-yellow-bg: var(--sinch-color-bolt-700);
|
|
36
38
|
--sinch-tag-color-dark-yellow-fg: var(--sinch-color-bolt-200);
|
|
39
|
+
--sinch-tag-color-dark-red-bg: var(--sinch-color-jasper-700);
|
|
40
|
+
--sinch-tag-color-dark-red-fg: var(--sinch-color-jasper-200);
|
|
37
41
|
--sinch-tag-color-blue-bg: var(--sinch-color-night-400);
|
|
38
42
|
--sinch-tag-color-blue-fg: var(--sinch-color-snow-100);
|
|
39
43
|
--sinch-tag-color-brown-bg: var(--sinch-color-mud-400);
|
|
@@ -50,6 +54,8 @@
|
|
|
50
54
|
--sinch-tag-color-violet-fg: var(--sinch-color-stormy-500);
|
|
51
55
|
--sinch-tag-color-yellow-bg: var(--sinch-color-bolt-400);
|
|
52
56
|
--sinch-tag-color-yellow-fg: var(--sinch-color-stormy-500);
|
|
57
|
+
--sinch-tag-color-red-bg: var(--sinch-color-jasper-400);
|
|
58
|
+
--sinch-tag-color-red-fg: var(--sinch-color-stormy-500);
|
|
53
59
|
--sinch-tag-color-celtic-bg: var(--sinch-color-feedback-info-bg);
|
|
54
60
|
--sinch-tag-color-celtic-fg: var(--sinch-color-feedback-info-contrast);
|
|
55
61
|
--sinch-tag-color-olive-bg: var(--sinch-color-feedback-success-bg);
|
package/toast-manager/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../title';
|
|
2
2
|
import '../text';
|
|
3
|
-
import { cloneNode, defineCustomElement, getRect, NectaryElement } from '../utils';
|
|
3
|
+
import { cloneNode, defineCustomElement, getRect, NectaryElement, shouldReduceMotion } from '../utils';
|
|
4
4
|
const templateHTML = '<style>:host{display:block}#items{display:block;width:0;height:0;visibility:hidden;overflow:hidden}#list{display:flex;flex-direction:column;position:fixed;z-index:1;bottom:0;right:16px}.item-wrapper{height:0;opacity:0;position:relative}.item-wrapper[data-deleting]::after{content:"";position:absolute;top:0;left:0;bottom:0;right:0}</style><slot id="items"></slot><div id="list"></div>';
|
|
5
5
|
const DURATION_ADD = 250;
|
|
6
6
|
const DURATION_REMOVE = 250;
|
|
@@ -11,7 +11,7 @@ defineCustomElement('sinch-toast-manager', class extends NectaryElement {
|
|
|
11
11
|
#$slot;
|
|
12
12
|
#$list;
|
|
13
13
|
#map = new WeakMap();
|
|
14
|
-
#shouldReduceMotion
|
|
14
|
+
#shouldReduceMotion;
|
|
15
15
|
#animations = new Set();
|
|
16
16
|
constructor() {
|
|
17
17
|
super();
|
|
@@ -19,10 +19,10 @@ defineCustomElement('sinch-toast-manager', class extends NectaryElement {
|
|
|
19
19
|
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
20
20
|
this.#$slot = shadowRoot.querySelector('slot');
|
|
21
21
|
this.#$list = shadowRoot.querySelector('#list');
|
|
22
|
+
this.#shouldReduceMotion = shouldReduceMotion();
|
|
22
23
|
}
|
|
23
24
|
connectedCallback() {
|
|
24
25
|
this.#$slot.addEventListener('slotchange', this.#onSlotChange);
|
|
25
|
-
this.#shouldReduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
26
26
|
}
|
|
27
27
|
disconnectedCallback() {
|
|
28
28
|
this.#$slot.removeEventListener('slotchange', this.#onSlotChange);
|
package/tooltip/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../text';
|
|
2
2
|
import '../pop';
|
|
3
|
-
import { defineCustomElement, getBooleanAttribute, getAttribute, getLiteralAttribute, updateBooleanAttribute, updateAttribute, updateLiteralAttribute, NectaryElement, setClass, rectOverlap, getReactEventHandler } from '../utils';
|
|
3
|
+
import { defineCustomElement, getBooleanAttribute, getAttribute, getLiteralAttribute, updateBooleanAttribute, updateAttribute, updateLiteralAttribute, NectaryElement, setClass, rectOverlap, getReactEventHandler, shouldReduceMotion } from '../utils';
|
|
4
4
|
const templateHTML = '<style>:host{display:contents}#content-wrapper{padding-bottom:8px}#content{position:relative;display:block;max-width:300px;padding:2px 6px;box-sizing:border-box;color:var(--sinch-color-text-default);background-color:var(--sinch-color-snow-600);border-radius:var(--sinch-shape-radius-xs);pointer-events:none;opacity:0}:host([orientation=left]) #content-wrapper{padding-bottom:0;padding-right:8px}:host([orientation=right]) #content-wrapper{padding-bottom:0;padding-left:8px}:host([orientation^=bottom]) #content-wrapper{padding-bottom:0;padding-top:8px}#text{word-break:break-word;pointer-events:none}#tip{position:absolute;left:50%;top:100%;transform:translateX(-50%) rotate(0);transform-origin:top center;fill:var(--sinch-color-snow-600);pointer-events:none}#tip.hidden{display:none}:host([orientation=left]) #tip{transform:translateX(-50%) rotate(270deg);top:50%;left:100%}:host([orientation=right]) #tip{transform:translateX(-50%) rotate(90deg);top:50%;left:0}:host([orientation^=bottom]) #tip{transform:translateX(-50%) rotate(180deg);top:0}:host([inverted]:not([inverted=false])) #content{background-color:var(--sinch-color-stormy-500);color:var(--sinch-color-text-inverted)}:host([inverted]:not([inverted=false])) #tip{fill:var(--sinch-color-stormy-500)}</style><sinch-pop id="pop"><slot id="target" slot="target"></slot><div id="content-wrapper" slot="content"><div id="content"><sinch-text id="text" type="s"></sinch-text><svg id="tip" width="8" height="4" aria-hidden="true"><path d="m4 4 4-4h-8l4 4Z"/></svg></div></div></sinch-pop>';
|
|
5
5
|
import { TooltipState } from './tooltip-state';
|
|
6
6
|
import { assertOrientation, getPopOrientation, orientationValues } from './utils';
|
|
@@ -32,7 +32,7 @@ defineCustomElement('sinch-tooltip', class extends NectaryElement {
|
|
|
32
32
|
this.#$contentWrapper = shadowRoot.querySelector('#content-wrapper');
|
|
33
33
|
this.#$tip = shadowRoot.querySelector('#tip');
|
|
34
34
|
this.#$target = shadowRoot.querySelector('#target');
|
|
35
|
-
this.#shouldReduceMotion =
|
|
35
|
+
this.#shouldReduceMotion = shouldReduceMotion();
|
|
36
36
|
this.#tooltipState = new TooltipState({
|
|
37
37
|
showDelay: SHOW_DELAY,
|
|
38
38
|
hideDelay: this.#shouldReduceMotion ? HIDE_DELAY + ANIMATION_DURATION : HIDE_DELAY,
|
package/utils/dom.d.ts
CHANGED
|
@@ -29,4 +29,5 @@ export declare const hasClass: (elem: Element, name: string) => boolean;
|
|
|
29
29
|
export declare const getCssVar: (element: Element, variableName: string) => string | null;
|
|
30
30
|
export declare const getCssVars: (element: Element, variableNames: string[]) => (string | null)[];
|
|
31
31
|
export declare const cloneNode: (el: Element, deep: boolean) => Element;
|
|
32
|
+
export declare const shouldReduceMotion: () => boolean;
|
|
32
33
|
export {};
|
package/utils/dom.js
CHANGED
package/utils/index.d.ts
CHANGED
package/utils/index.js
CHANGED
package/utils/uid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getUid: () => string;
|
package/utils/uid.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const getUid = () => crypto.getRandomValues(new Uint8Array(21)).reduce((id, byte) => {
|
|
2
|
+
const nextByte = byte & 63;
|
|
3
|
+
if (nextByte < 36) {
|
|
4
|
+
return id + nextByte.toString(36);
|
|
5
|
+
}
|
|
6
|
+
if (nextByte < 62) {
|
|
7
|
+
return id + (nextByte - 26).toString(36).toUpperCase();
|
|
8
|
+
}
|
|
9
|
+
if (nextByte > 62) {
|
|
10
|
+
return `${id}-`;
|
|
11
|
+
}
|
|
12
|
+
return `${id}_`;
|
|
13
|
+
}, '');
|