@tylertech/forge 3.5.1 → 3.6.0-dev.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.
Files changed (61) hide show
  1. package/custom-elements.json +1171 -1128
  2. package/dist/checkbox/forge-checkbox.css +1 -0
  3. package/dist/lib.js +27 -19
  4. package/dist/lib.js.map +4 -4
  5. package/dist/radio/forge-radio.css +2 -0
  6. package/dist/switch/forge-switch.css +2 -0
  7. package/dist/vscode.css-custom-data.json +15 -0
  8. package/dist/vscode.html-custom-data.json +81 -106
  9. package/esm/app-bar/profile-button/app-bar-profile-button.js +5 -2
  10. package/esm/avatar/avatar-constants.d.ts +0 -7
  11. package/esm/avatar/avatar-constants.js +1 -10
  12. package/esm/avatar/avatar.d.ts +24 -21
  13. package/esm/avatar/avatar.js +68 -45
  14. package/esm/avatar/index.d.ts +1 -3
  15. package/esm/avatar/index.js +4 -6
  16. package/esm/button/base/base-button-adapter.js +1 -1
  17. package/esm/button-area/button-area.js +1 -1
  18. package/esm/checkbox/checkbox.d.ts +1 -0
  19. package/esm/checkbox/checkbox.js +2 -1
  20. package/esm/dialog/dialog-adapter.d.ts +7 -0
  21. package/esm/dialog/dialog-adapter.js +43 -19
  22. package/esm/dialog/dialog-constants.d.ts +6 -0
  23. package/esm/dialog/dialog-constants.js +6 -2
  24. package/esm/dialog/dialog-core.d.ts +8 -0
  25. package/esm/dialog/dialog-core.js +20 -0
  26. package/esm/dialog/dialog.d.ts +14 -0
  27. package/esm/dialog/dialog.js +13 -1
  28. package/esm/icon-button/icon-button-constants.d.ts +4 -0
  29. package/esm/icon-button/icon-button-constants.js +2 -0
  30. package/esm/icon-button/icon-button-core.d.ts +4 -4
  31. package/esm/icon-button/icon-button-core.js +16 -14
  32. package/esm/icon-button/icon-button.d.ts +32 -29
  33. package/esm/icon-button/icon-button.js +5 -30
  34. package/esm/profile-card/profile-card.js +5 -2
  35. package/esm/radio/radio/radio.d.ts +1 -0
  36. package/esm/radio/radio/radio.js +2 -1
  37. package/esm/split-view/split-view/split-view-adapter.js +1 -0
  38. package/esm/split-view/split-view-panel/split-view-panel.js +1 -1
  39. package/esm/switch/switch.d.ts +1 -0
  40. package/esm/switch/switch.js +2 -1
  41. package/esm/table/table-utils.js +6 -6
  42. package/esm/tabs/tab-bar/tab-bar-adapter.d.ts +0 -5
  43. package/esm/tabs/tab-bar/tab-bar-adapter.js +3 -11
  44. package/esm/tabs/tab-bar/tab-bar-constants.d.ts +0 -3
  45. package/esm/tabs/tab-bar/tab-bar-constants.js +0 -4
  46. package/esm/tabs/tab-bar/tab-bar-core.js +7 -7
  47. package/esm/tabs/tab-bar/tab-bar.d.ts +6 -3
  48. package/esm/tabs/tab-bar/tab-bar.js +6 -3
  49. package/package.json +2 -2
  50. package/sass/button-area/_core.scss +3 -0
  51. package/sass/checkbox/_core.scss +2 -2
  52. package/sass/core/styles/tokens/checkbox/_tokens.scss +1 -0
  53. package/sass/core/styles/tokens/radio/_tokens.scss +1 -0
  54. package/sass/core/styles/tokens/switch/_tokens.scss +1 -0
  55. package/sass/dialog/dialog.scss +5 -0
  56. package/sass/radio/radio/_core.scss +2 -2
  57. package/sass/switch/_core.scss +2 -2
  58. package/esm/avatar/avatar-adapter.d.ts +0 -36
  59. package/esm/avatar/avatar-adapter.js +0 -55
  60. package/esm/avatar/avatar-core.d.ts +0 -38
  61. package/esm/avatar/avatar-core.js +0 -101
@@ -29,7 +29,6 @@ export class TabBarCore {
29
29
  this._scrollForwardButtonListener = () => this._onScrollForward();
30
30
  }
31
31
  initialize() {
32
- this._adapter.initialize();
33
32
  this._adapter.addSlotListener(this._tabsChangedListener);
34
33
  this._adapter.addHostListener(TAB_CONSTANTS.events.SELECT, this._tabSelectedListener);
35
34
  this._adapter.addHostListener('keydown', this._keydownListener);
@@ -43,7 +42,6 @@ export class TabBarCore {
43
42
  this._isInitialized = true;
44
43
  }
45
44
  destroy() {
46
- this._adapter.destroy();
47
45
  this._adapter.destroyContainerSizeObserver();
48
46
  this._adapter.destroyScrollObserver(this._scrollListener);
49
47
  this._isInitialized = false;
@@ -54,7 +52,7 @@ export class TabBarCore {
54
52
  this._tryScrollActiveTabIntoView();
55
53
  }
56
54
  _onTabSelected(evt) {
57
- this._selectTab(evt.target);
55
+ this._selectTab({ tab: evt.target, focusTab: true });
58
56
  }
59
57
  async _onKeydown(evt) {
60
58
  const orientation = this._vertical ? 'vertical' : 'horizontal';
@@ -91,14 +89,14 @@ export class TabBarCore {
91
89
  return;
92
90
  }
93
91
  if (this._autoActivate) {
94
- this._selectTab(this._tabs[index]);
92
+ this._selectTab({ tab: this._tabs[index], focusTab: true });
95
93
  }
96
94
  else {
97
95
  this._tabs[index].focus({ preventScroll: true, focusVisible: true });
98
96
  await this._adapter.tryScrollTabIntoView(this._tabs[index]);
99
97
  }
100
98
  }
101
- async _selectTab(tab, emitEvent = true) {
99
+ async _selectTab({ tab, emitEvent = true, focusTab = false }) {
102
100
  if (!tab || tab.disabled) {
103
101
  return;
104
102
  }
@@ -121,7 +119,9 @@ export class TabBarCore {
121
119
  }
122
120
  // Selecting a tab causes an animation of the indicator to start relative to the currently selected tab
123
121
  tab.selected = true;
124
- tab.focus({ preventScroll: true });
122
+ if (focusTab) {
123
+ tab.focus({ preventScroll: true });
124
+ }
125
125
  await this._adapter.tryScrollTabIntoView(tab);
126
126
  // Always deselect the currently selected tab after selecting a new tab to allow
127
127
  // for the tab indicator animation to run properly (the newly selected tab attempts
@@ -223,7 +223,7 @@ export class TabBarCore {
223
223
  this._activeTab = value ?? undefined;
224
224
  if (typeof this._activeTab === 'number') {
225
225
  const newSelectedTab = this._tabs[this._activeTab];
226
- this._selectTab(newSelectedTab, false);
226
+ this._selectTab({ tab: newSelectedTab, emitEvent: false, focusTab: false });
227
227
  this._adapter.setHostAttribute(TAB_BAR_CONSTANTS.attributes.ACTIVE_TAB, String(this._activeTab));
228
228
  }
229
229
  else {
@@ -5,7 +5,9 @@
5
5
  */
6
6
  import { BaseComponent, IBaseComponent } from '../../core/base/base-component';
7
7
  import { ITabBarChangeEventData } from './tab-bar-constants';
8
- export interface ITabBarComponent extends IBaseComponent {
8
+ import { IWithElementInternals } from '../../core/mixins/internals/with-element-internals';
9
+ import { IWithDefaultAria } from '../../core/mixins/internals/with-default-aria';
10
+ export interface ITabBarComponent extends IBaseComponent, IWithDefaultAria, IWithElementInternals {
9
11
  disabled: boolean;
10
12
  activeTab: number | null | undefined;
11
13
  vertical: boolean;
@@ -25,6 +27,7 @@ declare global {
25
27
  'forge-tab-bar-change': CustomEvent<ITabBarChangeEventData>;
26
28
  }
27
29
  }
30
+ declare const TabBarComponent_base: import("../../constants").AbstractConstructor<import("../../core/mixins/internals/with-default-aria").WithDefaultAriaContract> & import("../../constants").AbstractConstructor<import("../../core/mixins/internals/with-element-internals").WithElementInternalsContract> & typeof BaseComponent;
28
31
  /**
29
32
  * @tag forge-tab-bar
30
33
  *
@@ -57,7 +60,6 @@ declare global {
57
60
  * @attribute {boolean} [secondary=false] - Deprecated. Controls whether the tabs are styled as secondary tab navigation.
58
61
  * @attribute {boolean} [auto-activate=false] - Controls whether the tabs are automatically activated when receiving focus.
59
62
  * @attribute {boolean} [scroll-buttons=false] - Controls whether scroll buttons are displayed when the tabs overflow their container.
60
- * @attribute {string} [data-aria-label] - The ARIA label to forward to the internal tablist element.
61
63
  *
62
64
  * @event {CustomEvent<ITabBarChangeEventData>} forge-tab-bar-change - Dispatches when the active tab changes.
63
65
  *
@@ -69,7 +71,7 @@ declare global {
69
71
  * @csspart container - The container element.
70
72
  * @csspart scroll-container - The scroll container element.
71
73
  */
72
- export declare class TabBarComponent extends BaseComponent implements ITabBarComponent {
74
+ export declare class TabBarComponent extends TabBarComponent_base implements ITabBarComponent {
73
75
  static get observedAttributes(): string[];
74
76
  private _core;
75
77
  constructor();
@@ -87,3 +89,4 @@ export declare class TabBarComponent extends BaseComponent implements ITabBarCom
87
89
  autoActivate: boolean;
88
90
  scrollButtons: boolean;
89
91
  }
92
+ export {};
@@ -13,7 +13,10 @@ import { TabBarAdapter } from './tab-bar-adapter';
13
13
  import { TAB_BAR_CONSTANTS } from './tab-bar-constants';
14
14
  import { TabBarCore } from './tab-bar-core';
15
15
  import { tylIconKeyboardArrowLeft, tylIconKeyboardArrowRight, tylIconKeyboardArrowUp, tylIconKeyboardArrowDown } from '@tylertech/tyler-icons/standard';
16
- const template = '<template><div class=\"forge-tab-bar\" part=\"container\"><div role=\"tablist\" class=\"scroll-container\" part=\"scroll-container\"><slot></slot></div></div></template>';
16
+ import { WithElementInternals } from '../../core/mixins/internals/with-element-internals';
17
+ import { WithDefaultAria } from '../../core/mixins/internals/with-default-aria';
18
+ import { setDefaultAria } from '../../constants';
19
+ const template = '<template><div class=\"forge-tab-bar\" part=\"container\"><div class=\"scroll-container\" part=\"scroll-container\"><slot></slot></div></div></template>';
17
20
  const styles = ':host{position:relative;display:block}:host([hidden]){display:none}.forge-tab-bar{--_tab-bar-justify:var(--forge-tab-bar-justify, space-between);--_tab-bar-stretch:var(--forge-tab-bar-stretch, 1);--_tab-bar-divider-color:var(--forge-tab-bar-divider-color, var(--forge-theme-outline, #e0e0e0));--_tab-bar-divider-thickness:var(--forge-tab-bar-divider-thickness, 1px)}.forge-tab-bar{position:relative;display:grid;grid-template-columns:auto 1fr auto;max-width:100%;max-height:100%;align-items:center;border-bottom:var(--_tab-bar-divider-thickness) solid var(--_tab-bar-divider-color)}.scroll-container{position:relative;display:flex;justify-content:var(--_tab-bar-justify);align-items:flex-end;box-sizing:border-box;overflow:auto;scroll-behavior:smooth;scrollbar-width:none;grid-column:2}.scroll-container::-webkit-scrollbar{display:none}::slotted(*){flex:var(--_tab-bar-stretch);align-self:stretch}::slotted([selected]){z-index:1}forge-icon-button{--forge-icon-button-shape-squared:0px}:host([vertical]) .forge-tab-bar{grid-template-columns:none;grid-template-rows:auto 1fr auto;align-items:initial;border-bottom:none;border-right:var(--_tab-bar-divider-thickness) solid var(--_tab-bar-divider-color);height:100%}:host([vertical]) .scroll-container{display:inline-flex;flex-direction:column;align-items:stretch;gap:0;grid-column:auto;grid-row:2}:host([vertical]) .scroll-button{justify-self:center}:host([inverted]:not([vertical])) .forge-tab-bar{border-bottom:none;border-top:variale(divider-thickness) solid var(--_tab-bar-divider-color)}:host([inverted][vertical]) .forge-tab-bar{border-bottom:none;border-top:var(--_tab-bar-divider-thickness) solid var(--_tab-bar-divider-color)}:host([clustered]) .forge-tab-bar{--_tab-bar-justify:var(--forge-tab-bar-justify, flex-start);--_tab-bar-stretch:var(--forge-tab-bar-stretch, 0)}:host([clustered=start]) .forge-tab-bar{--_tab-bar-justify:var(--forge-tab-bar-justify, flex-start)}:host([clustered=center]) .forge-tab-bar{--_tab-bar-justify:var(--forge-tab-bar-justify, center)}:host([clustered=end]) .forge-tab-bar{--_tab-bar-justify:var(--forge-tab-bar-justify, flex-end)}';
18
21
  /**
19
22
  * @tag forge-tab-bar
@@ -47,7 +50,6 @@ const styles = ':host{position:relative;display:block}:host([hidden]){display:no
47
50
  * @attribute {boolean} [secondary=false] - Deprecated. Controls whether the tabs are styled as secondary tab navigation.
48
51
  * @attribute {boolean} [auto-activate=false] - Controls whether the tabs are automatically activated when receiving focus.
49
52
  * @attribute {boolean} [scroll-buttons=false] - Controls whether scroll buttons are displayed when the tabs overflow their container.
50
- * @attribute {string} [data-aria-label] - The ARIA label to forward to the internal tablist element.
51
53
  *
52
54
  * @event {CustomEvent<ITabBarChangeEventData>} forge-tab-bar-change - Dispatches when the active tab changes.
53
55
  *
@@ -59,7 +61,7 @@ const styles = ':host{position:relative;display:block}:host([hidden]){display:no
59
61
  * @csspart container - The container element.
60
62
  * @csspart scroll-container - The scroll container element.
61
63
  */
62
- let TabBarComponent = class TabBarComponent extends BaseComponent {
64
+ let TabBarComponent = class TabBarComponent extends WithDefaultAria(WithElementInternals(BaseComponent)) {
63
65
  static get observedAttributes() {
64
66
  return Object.values(TAB_BAR_CONSTANTS.observedAttributes);
65
67
  }
@@ -70,6 +72,7 @@ let TabBarComponent = class TabBarComponent extends BaseComponent {
70
72
  this._core = new TabBarCore(new TabBarAdapter(this));
71
73
  }
72
74
  connectedCallback() {
75
+ this[setDefaultAria]({ role: 'tablist' }, { setAttribute: true });
73
76
  this._core.initialize();
74
77
  }
75
78
  disconnectedCallback() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tylertech/forge",
3
3
  "description": "Tyler Forge™ Web Components library",
4
- "version": "3.5.1",
4
+ "version": "3.6.0-dev.0",
5
5
  "author": "Tyler Technologies, Inc.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -21,4 +21,4 @@
21
21
  "tslib": "^2.8.1"
22
22
  },
23
23
  "customElements": "custom-elements.json"
24
- }
24
+ }
@@ -15,11 +15,14 @@
15
15
  @mixin base {
16
16
  position: relative;
17
17
  overflow: hidden;
18
+ block-size: 100%;
19
+ inline-size: 100%;
18
20
  }
19
21
 
20
22
  @mixin enabled {
21
23
  cursor: #{token(cursor)};
22
24
  }
25
+
23
26
  @mixin disabled {
24
27
  cursor: #{token(disabled-cursor)};
25
28
  }
@@ -17,8 +17,7 @@
17
17
  @mixin checkbox {
18
18
  position: relative;
19
19
  flex-direction: #{token(direction)};
20
- flex-shrink: 0;
21
- align-items: center;
20
+ align-items: #{token(align)};
22
21
  justify-content: #{token(justify)};
23
22
  gap: #{token(gap)};
24
23
 
@@ -39,6 +38,7 @@
39
38
  justify-content: center;
40
39
 
41
40
  display: flex;
41
+ flex-shrink: 0;
42
42
 
43
43
  border-radius: #{token(state-layer-shape)};
44
44
  inline-size: #{token(state-layer-width)};
@@ -38,6 +38,7 @@ $tokens: (
38
38
  // Label
39
39
  gap: utils.module-val(checkbox, gap, 0),
40
40
  justify: utils.module-val(checkbox, justify, start),
41
+ align: utils.module-val(checkbox, align, center),
41
42
  direction: utils.module-val(checkbox, direction, initial),
42
43
  // State layer
43
44
  state-layer-width: utils.module-ref(checkbox, state-layer-width, state-layer-size),
@@ -33,6 +33,7 @@ $tokens: (
33
33
  // Label
34
34
  gap: utils.module-val(radio, gap, 0),
35
35
  justify: utils.module-val(radio, justify, start),
36
+ align: utils.module-val(radio, align, center),
36
37
  direction: utils.module-val(radio, direction, initial),
37
38
  // State layer
38
39
  state-layer-width: utils.module-ref(radio, state-layer-width, state-layer-size),
@@ -52,6 +52,7 @@ $tokens: (
52
52
  // Label
53
53
  gap: utils.module-val(switch, gap, 0),
54
54
  justify: utils.module-val(switch, justify, start),
55
+ align: utils.module-val(switch, align, center),
55
56
  direction: utils.module-val(switch, direction, initial),
56
57
  // State layer
57
58
  state-layer-width: utils.module-ref(switch, state-layer-width, state-layer-size),
@@ -4,6 +4,7 @@
4
4
  * License: Apache-2.0
5
5
  */
6
6
  @use './core' as *;
7
+ @use '../utils/mixins' as utils;
7
8
  @use './animations';
8
9
  @use '../backdrop';
9
10
  @use '../core/styles/theme';
@@ -55,6 +56,10 @@ $can-animate: '[visible]:not([animation-type=none])';
55
56
  @include surface;
56
57
  }
57
58
 
59
+ .visually-hidden {
60
+ @include utils.visually-hidden;
61
+ }
62
+
58
63
  //
59
64
  // Backdrop
60
65
  //
@@ -16,8 +16,7 @@
16
16
  @mixin radio {
17
17
  position: relative;
18
18
  flex-direction: #{token(direction)};
19
- flex-shrink: 0;
20
- align-items: center;
19
+ align-items: #{token(align)};
21
20
  justify-content: #{token(justify)};
22
21
  gap: #{token(gap)};
23
22
 
@@ -34,6 +33,7 @@
34
33
  justify-content: center;
35
34
 
36
35
  display: flex;
36
+ flex-shrink: 0;
37
37
 
38
38
  border-radius: #{token(shape)};
39
39
  inline-size: #{token(state-layer-width)};
@@ -36,8 +36,7 @@ $_handle-on-translate: calc(#{token(track-width)} - #{$_track-border-radius} * 2
36
36
  position: relative;
37
37
 
38
38
  flex-direction: #{token(direction)};
39
- flex-shrink: 0;
40
- align-items: center;
39
+ align-items: #{token(align)};
41
40
  justify-content: #{token(justify)};
42
41
  gap: #{token(gap)};
43
42
  }
@@ -65,6 +64,7 @@ $_handle-on-translate: calc(#{token(track-width)} - #{$_track-border-radius} * 2
65
64
  align-items: center;
66
65
 
67
66
  display: flex;
67
+ flex-shrink: 0;
68
68
 
69
69
  block-size: #{$_container-block-size};
70
70
 
@@ -1,36 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { BaseAdapter, IBaseAdapter } from '../core/base/base-adapter';
7
- import { IAvatarComponent } from './avatar';
8
- export interface IAvatarAdapter extends IBaseAdapter {
9
- setBackgroundImageUrl(url: string): Promise<boolean>;
10
- removeBackgroundImage(): void;
11
- setText(value: string): void;
12
- clearText(): void;
13
- }
14
- /**
15
- * The DOM adapter behind the `<forge-avatar>` element.
16
- */
17
- export declare class AvatarAdapter extends BaseAdapter<IAvatarComponent> implements IAvatarAdapter {
18
- private _root;
19
- private _defaultSlot;
20
- constructor(component: IAvatarComponent);
21
- /**
22
- * Sets the background image URL.
23
- * @param url The URL.
24
- */
25
- setBackgroundImageUrl(url: string): Promise<boolean>;
26
- /**
27
- * Removes the background image URL.
28
- */
29
- removeBackgroundImage(): void;
30
- /**
31
- * Sets the avatar text content.
32
- * @param value The text value.
33
- */
34
- setText(value: string): void;
35
- clearText(): void;
36
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { getShadowElement, removeAllChildren } from '@tylertech/forge-core';
7
- import { BaseAdapter } from '../core/base/base-adapter';
8
- import { AVATAR_CONSTANTS } from './avatar-constants';
9
- /**
10
- * The DOM adapter behind the `<forge-avatar>` element.
11
- */
12
- export class AvatarAdapter extends BaseAdapter {
13
- constructor(component) {
14
- super(component);
15
- this._root = getShadowElement(this._component, AVATAR_CONSTANTS.selectors.ROOT);
16
- this._defaultSlot = getShadowElement(this._component, AVATAR_CONSTANTS.selectors.DEFAULT_SLOT);
17
- }
18
- /**
19
- * Sets the background image URL.
20
- * @param url The URL.
21
- */
22
- async setBackgroundImageUrl(url) {
23
- // Set before loading image to prevent a flash of background color
24
- this._root.classList.add('forge-avatar--image');
25
- return new Promise(resolve => {
26
- const image = new Image();
27
- image.onload = () => {
28
- this._root.style.backgroundImage = `url(${image.src})`;
29
- resolve(true);
30
- };
31
- image.onerror = () => {
32
- this._root.classList.remove('forge-avatar--image');
33
- resolve(false);
34
- };
35
- image.src = url;
36
- });
37
- }
38
- /**
39
- * Removes the background image URL.
40
- */
41
- removeBackgroundImage() {
42
- this._root.style.removeProperty('background-image');
43
- this._root.classList.remove('forge-avatar--image');
44
- }
45
- /**
46
- * Sets the avatar text content.
47
- * @param value The text value.
48
- */
49
- setText(value) {
50
- this._defaultSlot.textContent = value;
51
- }
52
- clearText() {
53
- removeAllChildren(this._defaultSlot);
54
- }
55
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { IAvatarAdapter } from './avatar-adapter';
7
- export interface IAvatarCore {
8
- imageUrl: string;
9
- text: string;
10
- letterCount: number;
11
- }
12
- export declare class AvatarCore implements IAvatarCore {
13
- private _adapter;
14
- private _imageUrl;
15
- private _text;
16
- private _letterCount;
17
- private _initialized;
18
- constructor(_adapter: IAvatarAdapter);
19
- initialize(): void;
20
- destroy(): void;
21
- private _render;
22
- private _setBackgroundImageUrl;
23
- private _setText;
24
- /**
25
- * Gets the text content to display in the avatar.
26
- * @param {string} value The text to parse.
27
- */
28
- private _getTextContent;
29
- /** Gets/sets the text to display. */
30
- get text(): string;
31
- set text(value: string);
32
- /** Controls the number of letters to display from the text. By default the text is split on spaces and the first character of each word is used. */
33
- get letterCount(): number;
34
- set letterCount(value: number);
35
- /** Sets the background image URL to use. */
36
- get imageUrl(): string;
37
- set imageUrl(value: string);
38
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { isDefined, isString } from '@tylertech/forge-core';
7
- import { AVATAR_CONSTANTS } from './avatar-constants';
8
- export class AvatarCore {
9
- constructor(_adapter) {
10
- this._adapter = _adapter;
11
- this._text = '';
12
- this._letterCount = AVATAR_CONSTANTS.numbers.DEFAULT_LETTER_COUNT;
13
- this._initialized = false;
14
- }
15
- initialize() {
16
- this._render();
17
- this._initialized = true;
18
- }
19
- destroy() {
20
- this._initialized = false;
21
- }
22
- _render() {
23
- this._setText();
24
- this._setBackgroundImageUrl();
25
- }
26
- async _setBackgroundImageUrl() {
27
- if (this._imageUrl) {
28
- if (await this._adapter.setBackgroundImageUrl(this._imageUrl)) {
29
- this._adapter.clearText();
30
- }
31
- }
32
- else {
33
- this._adapter.removeBackgroundImage();
34
- }
35
- }
36
- _setText() {
37
- const data = this._getTextContent(this._text, this._letterCount);
38
- if (data) {
39
- this._adapter.setText(data);
40
- }
41
- else {
42
- this._adapter.clearText();
43
- }
44
- }
45
- /**
46
- * Gets the text content to display in the avatar.
47
- * @param {string} value The text to parse.
48
- */
49
- _getTextContent(value, count) {
50
- if (!value || !isString(value) || count <= 0) {
51
- return '';
52
- }
53
- let text;
54
- if (count === 1) {
55
- text = value[0].toUpperCase();
56
- }
57
- else {
58
- const words = value.match(/\S+/g) || [];
59
- text = words.slice(0, count).reduce((prev, curr) => (prev += curr[0].toUpperCase()), '');
60
- }
61
- return text;
62
- }
63
- /** Gets/sets the text to display. */
64
- get text() {
65
- return this._text;
66
- }
67
- set text(value) {
68
- if (this._text !== value) {
69
- this._text = value || '';
70
- this._adapter.setHostAttribute(AVATAR_CONSTANTS.attributes.TEXT, this._text);
71
- if (this._initialized) {
72
- this._render();
73
- }
74
- }
75
- }
76
- /** Controls the number of letters to display from the text. By default the text is split on spaces and the first character of each word is used. */
77
- get letterCount() {
78
- return this._letterCount;
79
- }
80
- set letterCount(value) {
81
- if (this._letterCount !== value) {
82
- this._letterCount = value;
83
- this._adapter.setHostAttribute(AVATAR_CONSTANTS.attributes.LETTER_COUNT, isDefined(this._letterCount) ? this._letterCount.toString() : '');
84
- if (this._initialized) {
85
- this._render();
86
- }
87
- }
88
- }
89
- /** Sets the background image URL to use. */
90
- get imageUrl() {
91
- return this._imageUrl;
92
- }
93
- set imageUrl(value) {
94
- if (this._imageUrl !== value) {
95
- this._imageUrl = value;
96
- if (this._initialized) {
97
- this._render();
98
- }
99
- }
100
- }
101
- }