@nyaruka/temba-components 0.116.0 → 0.117.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 (39) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/temba-components.js +44 -26
  3. package/dist/temba-components.js.map +1 -1
  4. package/out-tsc/src/button/Button.js +5 -0
  5. package/out-tsc/src/button/Button.js.map +1 -1
  6. package/out-tsc/src/chat/Chat.js +5 -1
  7. package/out-tsc/src/chat/Chat.js.map +1 -1
  8. package/out-tsc/src/dropdown/Dropdown.js +1 -1
  9. package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
  10. package/out-tsc/src/list/TembaMenu.js +17 -5
  11. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  12. package/out-tsc/src/options/Options.js +13 -16
  13. package/out-tsc/src/options/Options.js.map +1 -1
  14. package/out-tsc/src/select/Select.js +6 -2
  15. package/out-tsc/src/select/Select.js.map +1 -1
  16. package/out-tsc/src/select/UserSelect.js +0 -1
  17. package/out-tsc/src/select/UserSelect.js.map +1 -1
  18. package/out-tsc/src/select/WorkspaceSelect.js +65 -0
  19. package/out-tsc/src/select/WorkspaceSelect.js.map +1 -0
  20. package/out-tsc/src/user/TembaUser.js +2 -1
  21. package/out-tsc/src/user/TembaUser.js.map +1 -1
  22. package/out-tsc/temba-modules.js +2 -0
  23. package/out-tsc/temba-modules.js.map +1 -1
  24. package/package.json +1 -1
  25. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  26. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  27. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  28. package/screenshots/truth/select/expressions.png +0 -0
  29. package/screenshots/truth/select/functions.png +0 -0
  30. package/src/button/Button.ts +5 -0
  31. package/src/chat/Chat.ts +5 -1
  32. package/src/dropdown/Dropdown.ts +1 -1
  33. package/src/list/TembaMenu.ts +20 -5
  34. package/src/options/Options.ts +13 -17
  35. package/src/select/Select.ts +5 -2
  36. package/src/select/UserSelect.ts +0 -1
  37. package/src/select/WorkspaceSelect.ts +71 -0
  38. package/src/user/TembaUser.ts +2 -1
  39. package/temba-modules.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.116.0",
3
+ "version": "0.117.0",
4
4
  "description": "Web components to support rapidpro and related projects",
5
5
  "author": "Nyaruka <code@nyaruka.coim>",
6
6
  "main": "dist/index.js",
@@ -128,6 +128,11 @@ export class Button extends LitElement {
128
128
  background: transparent;
129
129
  }
130
130
 
131
+ .lined-button .button-mask {
132
+ display: block;
133
+ flex-grow: 1;
134
+ }
135
+
131
136
  .lined-button .button-mask:hover {
132
137
  background: rgba(0, 0, 0, 0.03);
133
138
  }
package/src/chat/Chat.ts CHANGED
@@ -223,6 +223,10 @@ export class Chat extends RapidElement {
223
223
  word-break: break-word;
224
224
  }
225
225
 
226
+ .message-text {
227
+ white-space: pre-line;
228
+ }
229
+
226
230
  .chat {
227
231
  width: 28rem;
228
232
  border-radius: var(--curvature);
@@ -780,7 +784,7 @@ export class Chat extends RapidElement {
780
784
  ? html`
781
785
  <div class="bubble">
782
786
  ${name ? html`<div class="name">${name}</div>` : null}
783
- <div class="message">${message.text}</div>
787
+ <div class="message message-text">${message.text}</div>
784
788
 
785
789
  <!--div>${message.date.toLocaleDateString(
786
790
  undefined,
@@ -37,7 +37,7 @@ export class Dropdown extends RapidElement {
37
37
  z-index: 2;
38
38
  padding: 0;
39
39
  opacity: 0;
40
- border-radius: var(--curvature);
40
+ border-radius: calc(var(--curvature) * 1.5);
41
41
  background: #fff;
42
42
  transition: all calc(0.8 * var(--transition-speed)) var(--bounce);
43
43
  user-select: none;
@@ -8,6 +8,7 @@ import { Dropdown } from '../dropdown/Dropdown';
8
8
  import { NotificationList } from './NotificationList';
9
9
  import { ResizeElement } from '../ResizeElement';
10
10
  import { Store } from '../store/Store';
11
+
11
12
  export interface MenuItem {
12
13
  id?: string;
13
14
  vanity_id?: string;
@@ -32,6 +33,7 @@ export interface MenuItem {
32
33
  trigger?: boolean;
33
34
  event?: string;
34
35
  mobile?: boolean;
36
+ initial?: string;
35
37
  }
36
38
 
37
39
  interface MenuItemState {
@@ -587,11 +589,6 @@ export class TembaMenu extends ResizeElement {
587
589
  margin-right: 0.75em;
588
590
  }
589
591
 
590
- temba-button[lined] {
591
- margin: 0.2em 0;
592
- display: block;
593
- }
594
-
595
592
  .expand-icon {
596
593
  transform: rotate(180deg);
597
594
  --icon-color: rgba(255, 255, 255, 0.5);
@@ -653,6 +650,14 @@ export class TembaMenu extends ResizeElement {
653
650
  .level-0 .icon-wrapper {
654
651
  padding: 0.4em 0.9em;
655
652
  }
653
+
654
+ temba-workspace-select {
655
+ margin: 0.2em;
656
+ display: block;
657
+ --options-shadow: none;
658
+ --color-widget-border: transparent;
659
+ --widget-box-shadow: none;
660
+ }
656
661
  `;
657
662
  }
658
663
 
@@ -1062,6 +1067,16 @@ export class TembaMenu extends ResizeElement {
1062
1067
  return html`<div class="divider"></div>`;
1063
1068
  }
1064
1069
 
1070
+ if (menuItem.type === 'temba-workspace-select') {
1071
+ return html`<temba-workspace-select
1072
+ @change=${(event) => {
1073
+ event.stopPropagation();
1074
+ event.preventDefault();
1075
+ }}
1076
+ .values=${[JSON.parse(menuItem.initial)]}
1077
+ ></temba-workspace-select>`;
1078
+ }
1079
+
1065
1080
  if (menuItem.type === 'temba-notification-list') {
1066
1081
  return html`<temba-notification-list
1067
1082
  endpoint=${menuItem.href}
@@ -17,16 +17,14 @@ export class Options extends RapidElement {
17
17
  user-select: none;
18
18
  border-radius: var(--curvature-widget);
19
19
  overflow: hidden;
20
- margin-top: var(--options-margin-top);
21
20
  display: flex;
22
21
  flex-direction: column;
23
- // transform: scaleY(0.5) translateY(-5em);
24
22
  transition: transform var(--transition-speed)
25
23
  cubic-bezier(0.71, 0.18, 0.61, 1.33),
26
24
  opacity var(--transition-speed) cubic-bezier(0.71, 0.18, 0.61, 1.33);
27
25
  opacity: 0;
28
- border: 1px transparent;
29
26
  z-index: 1000;
27
+ pointer-events: none;
30
28
  }
31
29
 
32
30
  .shadow {
@@ -97,10 +95,11 @@ export class Options extends RapidElement {
97
95
  }
98
96
 
99
97
  .show {
100
- // transform: scaleY(1) translateY(0);
101
98
  border: 1px solid var(--color-widget-border);
102
99
  opacity: 1;
103
100
  z-index: 1;
101
+ pointer-events: auto;
102
+ margin-top: var(--options-margin-top);
104
103
  }
105
104
 
106
105
  .option {
@@ -351,7 +350,7 @@ export class Options extends RapidElement {
351
350
  this.tempOptions = changed.get('options');
352
351
  window.setTimeout(() => {
353
352
  this.tempOptions = [];
354
- }, 0);
353
+ }, 200);
355
354
  }
356
355
  }
357
356
 
@@ -568,17 +567,12 @@ export class Options extends RapidElement {
568
567
  .getBoundingClientRect();
569
568
 
570
569
  if (this.anchorTo) {
571
- this.top = 0;
572
570
  const anchorBounds = this.anchorTo.getBoundingClientRect();
571
+ this.top = anchorBounds.bottom;
573
572
  if (anchorBounds.bottom + optionsBounds.height > window.innerHeight) {
574
573
  this.top = -(optionsBounds.height + anchorBounds.height + 20);
575
574
  }
576
575
  this.left = anchorBounds.left;
577
-
578
- // adjust for parent scrolling
579
- if (this.scrollParent) {
580
- this.top += -this.scrollParent.scrollTop;
581
- }
582
576
  }
583
577
  }
584
578
  }
@@ -631,13 +625,15 @@ export class Options extends RapidElement {
631
625
  vertical *= -1;
632
626
  }
633
627
 
634
- const containerStyle = {
635
- 'margin-left': `${this.marginHorizontal}px`,
636
- 'margin-top': `${vertical}px`
637
- };
628
+ const containerStyle = this.visible
629
+ ? {
630
+ 'margin-left': `${this.marginHorizontal}px`,
631
+ 'margin-top': `${vertical}px`
632
+ }
633
+ : {};
638
634
 
639
635
  if (this.top) {
640
- containerStyle[`transform`] = `translateY(${this.top}px)`;
636
+ containerStyle['top'] = `${this.top}px`;
641
637
  }
642
638
 
643
639
  if (this.left) {
@@ -653,7 +649,7 @@ export class Options extends RapidElement {
653
649
  'options-container': true,
654
650
  show: this.visible,
655
651
  top: this.poppedTop,
656
- anchored: !this.block,
652
+ anchored: !this.block && !!this.anchorTo,
657
653
  loading: this.loading,
658
654
  shadow: !this.hideShadow,
659
655
  bordered: this.hideShadow
@@ -499,6 +499,9 @@ export class Select<T extends SelectOption> extends FormElement {
499
499
  @property({ type: Array, attribute: 'options' })
500
500
  private staticOptions: any[] = [];
501
501
 
502
+ @property({ type: Boolean })
503
+ allowAnchor: boolean = true;
504
+
502
505
  private alphaSort = (a: any, b: any) => {
503
506
  // by default, all endpoint values are sorted by name
504
507
  if (this.endpoint) {
@@ -1510,7 +1513,7 @@ export class Select<T extends SelectOption> extends FormElement {
1510
1513
  .renderOptionDetail=${this.renderOptionDetail}
1511
1514
  .renderOptionName=${this.renderOptionName}
1512
1515
  .renderOption=${this.renderOption || this.renderOptionDefault}
1513
- .anchorTo=${this.anchorElement}
1516
+ .anchorTo=${this.allowAnchor ? this.anchorElement : null}
1514
1517
  .options=${this.visibleOptions}
1515
1518
  .spaceSelect=${this.spaceSelect}
1516
1519
  .nameKey=${this.nameKey}
@@ -1523,7 +1526,7 @@ export class Select<T extends SelectOption> extends FormElement {
1523
1526
  <temba-options
1524
1527
  @temba-selection=${this.handleExpressionSelection}
1525
1528
  @temba-canceled=${() => {}}
1526
- .anchorTo=${this.anchorExpressions}
1529
+ .anchorTo=${this.allowAnchor ? this.anchorExpressions : null}
1527
1530
  .options=${this.completionOptions}
1528
1531
  .renderOption=${renderCompletionOption}
1529
1532
  ?visible=${this.completionOptions.length > 0}
@@ -64,7 +64,6 @@ export class UserSelect extends Select<UserOption> {
64
64
  email=${option.email}
65
65
  name=${option.name}
66
66
  avatar=${option.avatar}
67
- scale="0.8"
68
67
  showname
69
68
  ></temba-user>`;
70
69
  }
@@ -0,0 +1,71 @@
1
+ import { css, CSSResultArray, html, TemplateResult } from 'lit';
2
+ import { Select, SelectOption } from './Select';
3
+ import { property } from 'lit/decorators.js';
4
+ import { getScrollParent } from '../utils';
5
+
6
+ export interface WorkspaceOption extends SelectOption {
7
+ name: string;
8
+ id: string;
9
+ type: string;
10
+ }
11
+
12
+ export class WorkspaceSelect extends Select<WorkspaceOption> {
13
+ static get styles(): CSSResultArray {
14
+ return [
15
+ super.styles,
16
+ css`
17
+ :host {
18
+ border: 0px solid blue;
19
+ }
20
+ `
21
+ ];
22
+ }
23
+
24
+ @property({ type: String })
25
+ endpoint = '/api/internal/orgs.json';
26
+
27
+ @property({ type: String })
28
+ nameKey = 'name';
29
+
30
+ @property({ type: String })
31
+ valueKey = 'id';
32
+
33
+ @property({ type: String })
34
+ placeholder: string = 'Choose Workspace';
35
+
36
+ @property({ type: Boolean })
37
+ sorted: boolean = true;
38
+
39
+ @property({ type: Object })
40
+ workspace: WorkspaceOption;
41
+
42
+ constructor() {
43
+ super();
44
+ this.shouldExclude = (option: WorkspaceOption) => {
45
+ const selected = this.values[0];
46
+ return option.id === selected?.id;
47
+ };
48
+
49
+ this.searchable = true;
50
+ }
51
+
52
+ public firstUpdated(changed: Map<string, any>) {
53
+ super.firstUpdated(changed);
54
+ this.allowAnchor = !!getScrollParent(this);
55
+ }
56
+
57
+ public prepareOptionsDefault(options: WorkspaceOption[]): WorkspaceOption[] {
58
+ options.forEach((option) => {
59
+ option.type = 'workspace';
60
+ });
61
+ return options;
62
+ }
63
+
64
+ public renderOptionDefault(option: WorkspaceOption): TemplateResult {
65
+ if (!option) {
66
+ return html``;
67
+ }
68
+
69
+ return html`<temba-user name=${option.name} showname></temba-user>`;
70
+ }
71
+ }
@@ -108,7 +108,8 @@ export class TembaUser extends RapidElement {
108
108
  border-radius: 100%;
109
109
  font-weight: 400;
110
110
  overflow: hidden;
111
- font-size: 12px;
111
+ font-size: 0.8em;
112
+ margin-right: 0.75em;
112
113
  box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.1);
113
114
  background:${this.bgimage || this.bgcolor};"
114
115
  >
package/temba-modules.ts CHANGED
@@ -63,6 +63,7 @@ import { StartProgress } from './src/progress/StartProgress';
63
63
  import { ShortcutList } from './src/list/ShortcutList';
64
64
  import { PopupSelect } from './src/select/PopupSelect';
65
65
  import { UserSelect } from './src/select/UserSelect';
66
+ import { WorkspaceSelect } from './src/select/WorkspaceSelect';
66
67
 
67
68
  export function addCustomElement(name: string, comp: any) {
68
69
  if (!window.customElements.get(name)) {
@@ -136,3 +137,4 @@ addCustomElement('temba-start-progress', StartProgress);
136
137
  addCustomElement('temba-shortcuts', ShortcutList);
137
138
  addCustomElement('temba-popup-select', PopupSelect);
138
139
  addCustomElement('temba-user-select', UserSelect);
140
+ addCustomElement('temba-workspace-select', WorkspaceSelect);