@nyaruka/temba-components 0.27.2 → 0.28.2
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/CHANGELOG.md +21 -0
- package/README.md +2 -1
- package/demo/index.html +176 -127
- package/dist/{956247ac.js → 2cd62ab6.js} +91 -66
- package/dist/index.js +91 -66
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/contacts/ContactTickets.js +34 -49
- package/out-tsc/src/contacts/ContactTickets.js.map +1 -1
- package/out-tsc/src/list/TembaMenu.js +9 -3
- package/out-tsc/src/list/TembaMenu.js.map +1 -1
- package/out-tsc/src/slider/TembaSlider.js +42 -25
- package/out-tsc/src/slider/TembaSlider.js.map +1 -1
- package/out-tsc/src/tabpane/Tab.js +4 -0
- package/out-tsc/src/tabpane/Tab.js.map +1 -1
- package/out-tsc/src/tabpane/TabPane.js +45 -6
- package/out-tsc/src/tabpane/TabPane.js.map +1 -1
- package/out-tsc/test/temba-slider.test.js +11 -0
- package/out-tsc/test/temba-slider.test.js.map +1 -0
- package/package.json +1 -1
- package/src/contacts/ContactTickets.ts +43 -53
- package/src/list/TembaMenu.ts +9 -3
- package/src/slider/TembaSlider.ts +43 -32
- package/src/tabpane/Tab.ts +3 -0
- package/src/tabpane/TabPane.ts +44 -6
- package/stories/temba-checkbox.stories.md +2 -12
- package/test/temba-slider.test.ts +11 -0
|
@@ -3,9 +3,11 @@ import { css, html } from 'lit';
|
|
|
3
3
|
import { property } from 'lit/decorators';
|
|
4
4
|
import { CustomEventType } from '../interfaces';
|
|
5
5
|
import { RapidElement } from '../RapidElement';
|
|
6
|
+
import { getClasses } from '../utils';
|
|
6
7
|
export class TabPane extends RapidElement {
|
|
7
8
|
constructor() {
|
|
8
9
|
super(...arguments);
|
|
10
|
+
this.collapses = false;
|
|
9
11
|
this.index = 0;
|
|
10
12
|
}
|
|
11
13
|
static get styles() {
|
|
@@ -21,6 +23,7 @@ export class TabPane extends RapidElement {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
.tab {
|
|
26
|
+
user-select: none;
|
|
24
27
|
padding: 0.5em 1em;
|
|
25
28
|
margin: 0em 0em;
|
|
26
29
|
cursor: pointer;
|
|
@@ -32,10 +35,39 @@ export class TabPane extends RapidElement {
|
|
|
32
35
|
border: 0px solid rgba(0, 0, 0, 0.45);
|
|
33
36
|
color: var(--color-text-dark);
|
|
34
37
|
--icon-color: var(--color-text-dark);
|
|
38
|
+
white-space: nowrap;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.tab.hidden {
|
|
42
|
+
display: none;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
.tab temba-icon {
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.tab .name {
|
|
49
|
+
margin-left: 0.4em;
|
|
50
|
+
max-width: 80px;
|
|
38
51
|
margin-right: 0.4em;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
transition: max-width 500ms ease-in-out;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tab .badge {
|
|
57
|
+
margin-left: 0.4em;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@media (max-width: 900px) {
|
|
61
|
+
.collapses .tab .name {
|
|
62
|
+
max-width: 0px;
|
|
63
|
+
margin: 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (max-width: 600px) {
|
|
68
|
+
.collapses .tab .badge {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
39
71
|
}
|
|
40
72
|
|
|
41
73
|
.tab.selected {
|
|
@@ -60,7 +92,6 @@ export class TabPane extends RapidElement {
|
|
|
60
92
|
}
|
|
61
93
|
|
|
62
94
|
.badge {
|
|
63
|
-
margin-left: 0.4em;
|
|
64
95
|
}
|
|
65
96
|
|
|
66
97
|
.count {
|
|
@@ -111,14 +142,19 @@ export class TabPane extends RapidElement {
|
|
|
111
142
|
tabs.push(tab);
|
|
112
143
|
}
|
|
113
144
|
return html `
|
|
114
|
-
<div
|
|
145
|
+
<div
|
|
146
|
+
class="tabs ${getClasses({ tabs: true, collapses: this.collapses })}"
|
|
147
|
+
>
|
|
115
148
|
${tabs.map((tab, index) => html `
|
|
116
149
|
<div
|
|
117
150
|
@click=${this.handleTabClick}
|
|
118
151
|
data-index=${index}
|
|
119
|
-
class="
|
|
120
|
-
|
|
121
|
-
:
|
|
152
|
+
class="${getClasses({
|
|
153
|
+
tab: true,
|
|
154
|
+
selected: index == this.index,
|
|
155
|
+
hidden: tab.hidden,
|
|
156
|
+
notify: tab.notify,
|
|
157
|
+
})}"
|
|
122
158
|
style="${tab.selectionColor && index == this.index
|
|
123
159
|
? `color:${tab.selectionColor};--icon-color:${tab.selectionColor};`
|
|
124
160
|
: ''} ${tab.selectionBackground && index == this.index
|
|
@@ -126,7 +162,7 @@ export class TabPane extends RapidElement {
|
|
|
126
162
|
: ''}"
|
|
127
163
|
>
|
|
128
164
|
${tab.icon ? html `<temba-icon name=${tab.icon} />` : null}
|
|
129
|
-
|
|
165
|
+
<div class="name">${tab.name}</div>
|
|
130
166
|
${tab.hasBadge()
|
|
131
167
|
? html `
|
|
132
168
|
<div class="badge">
|
|
@@ -145,6 +181,9 @@ export class TabPane extends RapidElement {
|
|
|
145
181
|
`;
|
|
146
182
|
}
|
|
147
183
|
}
|
|
184
|
+
__decorate([
|
|
185
|
+
property({ type: Boolean })
|
|
186
|
+
], TabPane.prototype, "collapses", void 0);
|
|
148
187
|
__decorate([
|
|
149
188
|
property({ type: Number })
|
|
150
189
|
], TabPane.prototype, "index", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabPane.js","sourceRoot":"","sources":["../../../src/tabpane/TabPane.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"TabPane.js","sourceRoot":"","sources":["../../../src/tabpane/TabPane.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators';\nimport { CustomEventType } from '../interfaces';\nimport { RapidElement } from '../RapidElement';\nimport { getClasses } from '../utils';\nimport { Tab } from './Tab';\n\nexport class TabPane extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n }\n\n .tabs {\n display: flex;\n }\n\n .tab {\n user-select: none;\n padding: 0.5em 1em;\n margin: 0em 0em;\n cursor: pointer;\n display: flex;\n align-items: center;\n border-radius: var(--curvature);\n border-bottom-right-radius: 0px;\n border-bottom-left-radius: 0px;\n border: 0px solid rgba(0, 0, 0, 0.45);\n color: var(--color-text-dark);\n --icon-color: var(--color-text-dark);\n white-space: nowrap;\n }\n\n .tab.hidden {\n display: none;\n }\n\n .tab temba-icon {\n }\n\n .tab .name {\n margin-left: 0.4em;\n max-width: 80px;\n margin-right: 0.4em;\n overflow: hidden;\n transition: max-width 500ms ease-in-out;\n }\n\n .tab .badge {\n margin-left: 0.4em;\n }\n\n @media (max-width: 900px) {\n .collapses .tab .name {\n max-width: 0px;\n margin: 0;\n }\n }\n\n @media (max-width: 600px) {\n .collapses .tab .badge {\n display: none;\n }\n }\n\n .tab.selected {\n cursor: default;\n box-shadow: 2px 1px 3px 2px rgba(0, 0, 0, 0.07);\n background: #fff;\n }\n\n .pane {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n background: #fff;\n border-radius: var(--curvature);\n box-shadow: 2px 5px 12px 2px rgba(0, 0, 0, 0.09),\n 3px 3px 2px 1px rgba(0, 0, 0, 0.05);\n min-height: 0;\n }\n\n .pane.first {\n border-top-left-radius: 0px;\n }\n\n .badge {\n }\n\n .count {\n border-radius: 99px;\n background: rgba(0, 0, 0, 0.05);\n color: rgba(0, 0, 0, 0.5);\n font-size: 0.6em;\n font-weight: 400;\n padding: 0.1em 0.4em;\n min-width: 1em;\n text-align: center;\n }\n\n .notify .count {\n background: var(--color-alert);\n color: #fff;\n }\n `;\n }\n\n @property({ type: Boolean })\n collapses = false;\n\n @property({ type: Number })\n index = 0;\n\n private handleTabClick(event: MouseEvent): void {\n this.index = parseInt(\n (event.currentTarget as HTMLDivElement).dataset.index\n );\n this.requestUpdate('index');\n this.fireEvent(CustomEventType.ContextChanged);\n }\n\n public updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n if (changedProperties.has('index')) {\n if (this.children.length > this.index) {\n for (let i = 0; i < this.children.length; i++) {\n const tab = this.children[i] as Tab;\n tab.selected = i == this.index;\n\n if (tab.selected) {\n tab.style.display = 'flex';\n } else {\n tab.style.display = 'none';\n }\n }\n }\n }\n }\n\n public getTab(index: number): Tab {\n return this.children.item(index) as Tab;\n }\n\n public render(): TemplateResult {\n const tabs: Tab[] = [];\n for (const tab of this.children) {\n tabs.push(tab as Tab);\n }\n\n return html`\n <div\n class=\"tabs ${getClasses({ tabs: true, collapses: this.collapses })}\"\n >\n ${tabs.map(\n (tab, index) => html`\n <div\n @click=${this.handleTabClick}\n data-index=${index}\n class=\"${getClasses({\n tab: true,\n selected: index == this.index,\n hidden: tab.hidden,\n notify: tab.notify,\n })}\"\n style=\"${tab.selectionColor && index == this.index\n ? `color:${tab.selectionColor};--icon-color:${tab.selectionColor};`\n : ''} ${tab.selectionBackground && index == this.index\n ? `background-color:${tab.selectionBackground};`\n : ''}\"\n >\n ${tab.icon ? html`<temba-icon name=${tab.icon} />` : null}\n <div class=\"name\">${tab.name}</div>\n ${tab.hasBadge()\n ? html`\n <div class=\"badge\">\n ${tab.count > 0\n ? html`<div class=\"count\">${tab.count}</div>`\n : null}\n </div>\n `\n : null}\n </div>\n `\n )}\n </div>\n <div class=\"pane ${this.index === 0 ? 'first' : null}\">\n <slot></slot>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// import { html, fixture, expect } from '@open-wc/testing';
|
|
2
|
+
// import { TembaSlider } from '../src/slider/TembaSlider';
|
|
3
|
+
// import { assertScreenshot, getClip } from './utils.test';
|
|
4
|
+
describe('temba-slider', () => {
|
|
5
|
+
// it('renders default slider', async () => {});
|
|
6
|
+
// it('renders a slider with visible ranges', async () => {});
|
|
7
|
+
// it('updates slider position on element value change', async () => {});
|
|
8
|
+
// it('updates slider position on when track clicked', async () => {});
|
|
9
|
+
// it('updates slider position on circle drag', async () => {});
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=temba-slider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temba-slider.test.js","sourceRoot":"","sources":["../../test/temba-slider.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2DAA2D;AAC3D,4DAA4D;AAE5D,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,gDAAgD;IAChD,8DAA8D;IAC9D,yEAAyE;IACzE,uEAAuE;IACvE,gEAAgE;AAClE,CAAC,CAAC,CAAC","sourcesContent":["// import { html, fixture, expect } from '@open-wc/testing';\n// import { TembaSlider } from '../src/slider/TembaSlider';\n// import { assertScreenshot, getClip } from './utils.test';\n\ndescribe('temba-slider', () => {\n // it('renders default slider', async () => {});\n // it('renders a slider with visible ranges', async () => {});\n // it('updates slider position on element value change', async () => {});\n // it('updates slider position on when track clicked', async () => {});\n // it('updates slider position on circle drag', async () => {});\n});\n"]}
|
package/package.json
CHANGED
|
@@ -13,17 +13,16 @@ export class ContactTickets extends StoreElement {
|
|
|
13
13
|
static get styles() {
|
|
14
14
|
return css`
|
|
15
15
|
:host {
|
|
16
|
-
|
|
17
|
-
color: #fff;
|
|
18
|
-
--icon-color: #fff;
|
|
19
|
-
border-radius: var(--curvature);
|
|
16
|
+
padding: 1em;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
:hover {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ticket:hover {
|
|
26
23
|
cursor: pointer;
|
|
24
|
+
box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.055),
|
|
25
|
+
0 0 0px 2px var(--color-link-primary);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
.tickets {
|
|
@@ -56,24 +55,17 @@ export class ContactTickets extends StoreElement {
|
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
.ticket > div {
|
|
59
|
-
padding: 1em;
|
|
58
|
+
padding: 0.5em 1em;
|
|
59
|
+
pointer-events: none;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
border-top-right-radius: var(--curvature);
|
|
65
|
-
border-bottom-right-radius: var(--curvature);
|
|
66
|
-
padding: 1.5em;
|
|
67
|
-
--icon-color: rgba(0, 0, 0, 0.4);
|
|
68
|
-
white-space: nowrap;
|
|
62
|
+
.status {
|
|
63
|
+
--icon-color: #999;
|
|
69
64
|
}
|
|
70
65
|
|
|
71
|
-
.
|
|
72
|
-
background:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.closed .action {
|
|
76
|
-
background: #fff;
|
|
66
|
+
.ticket.closed {
|
|
67
|
+
background: #f9f9f9;
|
|
68
|
+
color: #888;
|
|
77
69
|
}
|
|
78
70
|
`;
|
|
79
71
|
}
|
|
@@ -81,8 +73,25 @@ export class ContactTickets extends StoreElement {
|
|
|
81
73
|
prepareData(data: any): any {
|
|
82
74
|
if (data && data.length) {
|
|
83
75
|
data.sort((a: Ticket, b: Ticket) => {
|
|
76
|
+
if (a.status == TicketStatus.Open && b.status == TicketStatus.Closed) {
|
|
77
|
+
return -1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (b.status == TicketStatus.Open && a.status == TicketStatus.Closed) {
|
|
81
|
+
return 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
a.status == TicketStatus.Closed &&
|
|
86
|
+
b.status == TicketStatus.Closed
|
|
87
|
+
) {
|
|
88
|
+
return (
|
|
89
|
+
new Date(b.closed_on).getTime() - new Date(a.closed_on).getTime()
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
return (
|
|
85
|
-
new Date(
|
|
94
|
+
new Date(b.opened_on).getTime() - new Date(a.opened_on).getTime()
|
|
86
95
|
);
|
|
87
96
|
});
|
|
88
97
|
}
|
|
@@ -120,43 +129,24 @@ export class ContactTickets extends StoreElement {
|
|
|
120
129
|
</temba-tip>
|
|
121
130
|
</div>
|
|
122
131
|
|
|
123
|
-
${ticket.status === TicketStatus.
|
|
124
|
-
? html
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
`
|
|
129
|
-
: html`
|
|
130
|
-
<div class="action">
|
|
131
|
-
<temba-icon name="check" size="1.5"></temba-icon>
|
|
132
|
-
</div>
|
|
133
|
-
`}
|
|
132
|
+
${ticket.status === TicketStatus.Closed
|
|
133
|
+
? html`<div class="status">
|
|
134
|
+
<temba-icon name="check"></temba-icon>
|
|
135
|
+
</div>`
|
|
136
|
+
: null}
|
|
134
137
|
</div>
|
|
135
138
|
`;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
public render(): TemplateResult {
|
|
139
142
|
if (this.data && this.data.length > 0) {
|
|
140
|
-
const
|
|
141
|
-
(ticket
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
<div
|
|
146
|
-
class="tickets"
|
|
147
|
-
href="/ticket/all/open/${ticket.uuid}"
|
|
148
|
-
onclick="goto(event)"
|
|
149
|
-
>
|
|
150
|
-
<div style="flex-grow:1"></div>
|
|
151
|
-
<temba-icon name="agent" style="pointer-events: none;"></temba-icon>
|
|
152
|
-
<div class="count" style="pointer-events: none;">
|
|
153
|
-
${this.data.filter(
|
|
154
|
-
(ticket: Ticket) => ticket.status === TicketStatus.Open
|
|
155
|
-
).length}
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
`;
|
|
159
|
-
}
|
|
143
|
+
const tickets = this.data.map(ticket => {
|
|
144
|
+
return this.renderTicket(ticket);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return html`${tickets}`;
|
|
160
148
|
}
|
|
149
|
+
|
|
150
|
+
return html`<slot name="empty"></slot>`;
|
|
161
151
|
}
|
|
162
152
|
}
|
package/src/list/TembaMenu.ts
CHANGED
|
@@ -164,6 +164,7 @@ export class TembaMenu extends RapidElement {
|
|
|
164
164
|
|
|
165
165
|
.level-0 {
|
|
166
166
|
padding: 0px;
|
|
167
|
+
z-index: 500;
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
.item {
|
|
@@ -261,7 +262,7 @@ export class TembaMenu extends RapidElement {
|
|
|
261
262
|
.level-1 {
|
|
262
263
|
transition: opacity 100ms linear, margin 200ms linear;
|
|
263
264
|
overflow-y: scroll;
|
|
264
|
-
z-index:
|
|
265
|
+
z-index: 150;
|
|
265
266
|
}
|
|
266
267
|
|
|
267
268
|
.level-2 {
|
|
@@ -394,9 +395,14 @@ export class TembaMenu extends RapidElement {
|
|
|
394
395
|
}
|
|
395
396
|
|
|
396
397
|
.fully-collapsed .level-1 {
|
|
397
|
-
margin-left: -
|
|
398
|
-
|
|
398
|
+
margin-left: -217px;
|
|
399
|
+
pointer-events: none;
|
|
399
400
|
border: none;
|
|
401
|
+
overflow: hidden;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.fully-collapsed .level-1 > * {
|
|
405
|
+
opacity: 0;
|
|
400
406
|
}
|
|
401
407
|
|
|
402
408
|
.fully-collapsed .level-1 .item,
|
|
@@ -12,19 +12,21 @@ export class TembaSlider extends FormElement {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.track {
|
|
15
|
-
height:
|
|
16
|
-
border:
|
|
15
|
+
height: 2px;
|
|
16
|
+
border-top: 0.5em solid #fff;
|
|
17
|
+
border-bottom: 0.5em solid #fff;
|
|
17
18
|
background: #ddd;
|
|
19
|
+
flex-grow: 1;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
.circle {
|
|
21
|
-
margin-
|
|
22
|
-
margin-left:
|
|
23
|
+
margin-bottom: -1.05em;
|
|
24
|
+
margin-left: -0.5em;
|
|
23
25
|
width: 0.75em;
|
|
24
26
|
height: 0.75em;
|
|
25
27
|
border: 2px solid #999;
|
|
26
28
|
border-radius: 999px;
|
|
27
|
-
position:
|
|
29
|
+
position: relative;
|
|
28
30
|
background: #fff;
|
|
29
31
|
box-shadow: 0 0 0 4px rgb(255, 255, 255);
|
|
30
32
|
transition: transform 200ms ease-in-out;
|
|
@@ -39,10 +41,6 @@ export class TembaSlider extends FormElement {
|
|
|
39
41
|
cursor: pointer;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
.grabbed .circle {
|
|
43
|
-
// border-color: #777;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
44
|
.grabbed .circle {
|
|
47
45
|
border-color: var(--color-primary-dark);
|
|
48
46
|
background: #fff;
|
|
@@ -51,9 +49,24 @@ export class TembaSlider extends FormElement {
|
|
|
51
49
|
.grabbed .circle {
|
|
52
50
|
transform: scale(1.2);
|
|
53
51
|
}
|
|
52
|
+
|
|
53
|
+
.wrapper {
|
|
54
|
+
display: flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.pre,
|
|
59
|
+
.post {
|
|
60
|
+
font-size: 0.9em;
|
|
61
|
+
color: #999;
|
|
62
|
+
padding: 0em 1em;
|
|
63
|
+
}
|
|
54
64
|
`;
|
|
55
65
|
}
|
|
56
66
|
|
|
67
|
+
@property({ type: Boolean })
|
|
68
|
+
range = false;
|
|
69
|
+
|
|
57
70
|
@property({ type: Number })
|
|
58
71
|
min = 0;
|
|
59
72
|
|
|
@@ -62,32 +75,28 @@ export class TembaSlider extends FormElement {
|
|
|
62
75
|
|
|
63
76
|
circleX = 0;
|
|
64
77
|
grabbed = false;
|
|
65
|
-
left = 0;
|
|
66
|
-
gap = 0;
|
|
67
78
|
|
|
68
79
|
public firstUpdated(changes: Map<string, any>) {
|
|
69
80
|
super.firstUpdated(changes);
|
|
70
81
|
this.handleMouseMove = this.handleMouseMove.bind(this);
|
|
71
82
|
this.handleMouseUp = this.handleMouseUp.bind(this);
|
|
72
|
-
this.left = Math.round(this.getBoundingClientRect().left);
|
|
73
|
-
const circle = this.shadowRoot.querySelector('.circle').clientWidth - 4;
|
|
74
|
-
this.left = Math.round(this.getBoundingClientRect().left + circle);
|
|
75
|
-
this.gap = this.offsetWidth * 0.035;
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
public updated(changedProperties: Map<string, any>): void {
|
|
79
86
|
if (changedProperties.has('value')) {
|
|
80
|
-
|
|
81
|
-
const total = this.offsetWidth - this.gap;
|
|
82
|
-
this.updateCircle(total * pct);
|
|
87
|
+
this.updateCircle();
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
public updateValue(evt: MouseEvent) {
|
|
87
|
-
const
|
|
88
|
-
const
|
|
92
|
+
const track = this.shadowRoot.querySelector('.track') as HTMLDivElement;
|
|
93
|
+
const left = evt.pageX - track.offsetLeft;
|
|
94
|
+
const pct = left / track.offsetWidth;
|
|
95
|
+
|
|
96
|
+
const range = this.max - this.min;
|
|
97
|
+
const pctAsValue = range * pct + this.min;
|
|
89
98
|
this.value =
|
|
90
|
-
'' + Math.max(this.min, Math.min(Math.round(
|
|
99
|
+
'' + Math.max(this.min, Math.min(Math.round(pctAsValue), this.max));
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
public handleMouseMove(evt: MouseEvent) {
|
|
@@ -102,14 +111,12 @@ export class TembaSlider extends FormElement {
|
|
|
102
111
|
document.addEventListener('mouseup', this.handleMouseUp);
|
|
103
112
|
document.querySelector('html').classList.add('dragging');
|
|
104
113
|
this.updateValue(evt);
|
|
105
|
-
|
|
106
114
|
this.requestUpdate();
|
|
107
115
|
}
|
|
108
116
|
|
|
109
117
|
public handleMouseUp(evt: MouseEvent) {
|
|
110
118
|
this.grabbed = false;
|
|
111
119
|
this.updateValue(evt);
|
|
112
|
-
|
|
113
120
|
this.requestUpdate();
|
|
114
121
|
|
|
115
122
|
document.removeEventListener('mousemove', this.handleMouseMove);
|
|
@@ -117,14 +124,14 @@ export class TembaSlider extends FormElement {
|
|
|
117
124
|
document.querySelector('html').classList.remove('dragging');
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
public updateCircle(
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
127
|
+
public updateCircle() {
|
|
128
|
+
const track = this.shadowRoot.querySelector('.track') as HTMLDivElement;
|
|
129
|
+
const pre = this.shadowRoot.querySelector('.pre') as HTMLDivElement;
|
|
130
|
+
const range = this.max - this.min;
|
|
131
|
+
const pct = (parseInt(this.value) - this.min) / range;
|
|
132
|
+
const pctAsPixels = track.offsetWidth * pct;
|
|
133
|
+
|
|
134
|
+
this.circleX = pctAsPixels + (pre ? pre.offsetWidth : 0);
|
|
128
135
|
this.requestUpdate();
|
|
129
136
|
}
|
|
130
137
|
|
|
@@ -135,7 +142,11 @@ export class TembaSlider extends FormElement {
|
|
|
135
142
|
class="circle"
|
|
136
143
|
@mousedown=${this.handleTrackDown}
|
|
137
144
|
></div>
|
|
138
|
-
<div class="
|
|
145
|
+
<div class="wrapper">
|
|
146
|
+
${this.range ? html`<div class="pre">${this.min}</div>` : null}
|
|
147
|
+
<div class="track" @mousedown=${this.handleTrackDown}></div>
|
|
148
|
+
${this.range ? html`<div class="post">${this.max}</div>` : null}
|
|
149
|
+
</div>
|
|
139
150
|
</div>`;
|
|
140
151
|
}
|
|
141
152
|
}
|
package/src/tabpane/Tab.ts
CHANGED
package/src/tabpane/TabPane.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { css, html, TemplateResult } from 'lit';
|
|
|
2
2
|
import { property } from 'lit/decorators';
|
|
3
3
|
import { CustomEventType } from '../interfaces';
|
|
4
4
|
import { RapidElement } from '../RapidElement';
|
|
5
|
+
import { getClasses } from '../utils';
|
|
5
6
|
import { Tab } from './Tab';
|
|
6
7
|
|
|
7
8
|
export class TabPane extends RapidElement {
|
|
@@ -18,6 +19,7 @@ export class TabPane extends RapidElement {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
.tab {
|
|
22
|
+
user-select: none;
|
|
21
23
|
padding: 0.5em 1em;
|
|
22
24
|
margin: 0em 0em;
|
|
23
25
|
cursor: pointer;
|
|
@@ -29,10 +31,39 @@ export class TabPane extends RapidElement {
|
|
|
29
31
|
border: 0px solid rgba(0, 0, 0, 0.45);
|
|
30
32
|
color: var(--color-text-dark);
|
|
31
33
|
--icon-color: var(--color-text-dark);
|
|
34
|
+
white-space: nowrap;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.tab.hidden {
|
|
38
|
+
display: none;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
.tab temba-icon {
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.tab .name {
|
|
45
|
+
margin-left: 0.4em;
|
|
46
|
+
max-width: 80px;
|
|
35
47
|
margin-right: 0.4em;
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
transition: max-width 500ms ease-in-out;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.tab .badge {
|
|
53
|
+
margin-left: 0.4em;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media (max-width: 900px) {
|
|
57
|
+
.collapses .tab .name {
|
|
58
|
+
max-width: 0px;
|
|
59
|
+
margin: 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media (max-width: 600px) {
|
|
64
|
+
.collapses .tab .badge {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
36
67
|
}
|
|
37
68
|
|
|
38
69
|
.tab.selected {
|
|
@@ -57,7 +88,6 @@ export class TabPane extends RapidElement {
|
|
|
57
88
|
}
|
|
58
89
|
|
|
59
90
|
.badge {
|
|
60
|
-
margin-left: 0.4em;
|
|
61
91
|
}
|
|
62
92
|
|
|
63
93
|
.count {
|
|
@@ -78,6 +108,9 @@ export class TabPane extends RapidElement {
|
|
|
78
108
|
`;
|
|
79
109
|
}
|
|
80
110
|
|
|
111
|
+
@property({ type: Boolean })
|
|
112
|
+
collapses = false;
|
|
113
|
+
|
|
81
114
|
@property({ type: Number })
|
|
82
115
|
index = 0;
|
|
83
116
|
|
|
@@ -118,15 +151,20 @@ export class TabPane extends RapidElement {
|
|
|
118
151
|
}
|
|
119
152
|
|
|
120
153
|
return html`
|
|
121
|
-
<div
|
|
154
|
+
<div
|
|
155
|
+
class="tabs ${getClasses({ tabs: true, collapses: this.collapses })}"
|
|
156
|
+
>
|
|
122
157
|
${tabs.map(
|
|
123
158
|
(tab, index) => html`
|
|
124
159
|
<div
|
|
125
160
|
@click=${this.handleTabClick}
|
|
126
161
|
data-index=${index}
|
|
127
|
-
class="
|
|
128
|
-
|
|
129
|
-
:
|
|
162
|
+
class="${getClasses({
|
|
163
|
+
tab: true,
|
|
164
|
+
selected: index == this.index,
|
|
165
|
+
hidden: tab.hidden,
|
|
166
|
+
notify: tab.notify,
|
|
167
|
+
})}"
|
|
130
168
|
style="${tab.selectionColor && index == this.index
|
|
131
169
|
? `color:${tab.selectionColor};--icon-color:${tab.selectionColor};`
|
|
132
170
|
: ''} ${tab.selectionBackground && index == this.index
|
|
@@ -134,7 +172,7 @@ export class TabPane extends RapidElement {
|
|
|
134
172
|
: ''}"
|
|
135
173
|
>
|
|
136
174
|
${tab.icon ? html`<temba-icon name=${tab.icon} />` : null}
|
|
137
|
-
|
|
175
|
+
<div class="name">${tab.name}</div>
|
|
138
176
|
${tab.hasBadge()
|
|
139
177
|
? html`
|
|
140
178
|
<div class="badge">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
```js script
|
|
2
2
|
import { html } from '@open-wc/demoing-storybook';
|
|
3
|
-
import '../dist/
|
|
3
|
+
import '../dist/index.js';
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
6
|
title: 'forms/temba-checkbox',
|
|
@@ -21,19 +21,9 @@ A component for...
|
|
|
21
21
|
|
|
22
22
|
## How to use
|
|
23
23
|
|
|
24
|
-
### Installation
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
yarn add temba-checkbox
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
```js
|
|
31
|
-
import 'temba-checkbox/temba-checkbox.js';
|
|
32
|
-
```
|
|
33
|
-
|
|
34
24
|
```js preview-story
|
|
35
25
|
export const Default = () =>
|
|
36
|
-
html
|
|
26
|
+
html`<temba-checkbox label="Click me for good luck"></temba-checkbox> `;
|
|
37
27
|
```
|
|
38
28
|
|
|
39
29
|
## Variations
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// import { html, fixture, expect } from '@open-wc/testing';
|
|
2
|
+
// import { TembaSlider } from '../src/slider/TembaSlider';
|
|
3
|
+
// import { assertScreenshot, getClip } from './utils.test';
|
|
4
|
+
|
|
5
|
+
describe('temba-slider', () => {
|
|
6
|
+
// it('renders default slider', async () => {});
|
|
7
|
+
// it('renders a slider with visible ranges', async () => {});
|
|
8
|
+
// it('updates slider position on element value change', async () => {});
|
|
9
|
+
// it('updates slider position on when track clicked', async () => {});
|
|
10
|
+
// it('updates slider position on circle drag', async () => {});
|
|
11
|
+
});
|