@3t-transform/threeteeui 0.0.11 → 0.0.12
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/dist/cjs/{index-bf39be87.js → index-61cd741f.js} +2 -88
- package/dist/cjs/loader.cjs.js +3 -4
- package/dist/cjs/tttx-button.cjs.entry.js +1 -1
- package/dist/cjs/tttx-checkbox.cjs.entry.js +1 -1
- package/dist/cjs/tttx-form.cjs.entry.js +1 -1
- package/dist/cjs/tttx-icon.cjs.entry.js +1 -1
- package/dist/cjs/tttx-list.cjs.entry.js +198 -0
- package/dist/cjs/tttx-loading-spinner.cjs.entry.js +1 -1
- package/dist/cjs/tttx-popover-content.cjs.entry.js +1 -1
- package/dist/cjs/tttx-standalone-input.cjs.entry.js +1 -1
- package/dist/cjs/tttx.cjs.js +3 -7
- package/dist/collection/collection-manifest.json +4 -3
- package/dist/collection/components/molecules/tttx-list/tttx-list.css +56 -0
- package/dist/collection/components/molecules/tttx-list/tttx-list.js +311 -0
- package/dist/collection/components/molecules/tttx-list/tttx-list.stories.js +37 -0
- package/dist/components/index.d.ts +1 -9
- package/dist/components/index.js +2 -1
- package/dist/components/tttx-list.d.ts +11 -0
- package/dist/components/tttx-list.js +225 -0
- package/dist/components/tttx-loading-spinner.js +1 -38
- package/dist/components/tttx-loading-spinner2.js +40 -0
- package/dist/esm/{index-63c4d25e.js → index-d8718abe.js} +3 -88
- package/dist/esm/loader.js +3 -4
- package/dist/esm/polyfills/css-shim.js +1 -1
- package/dist/esm/tttx-button.entry.js +1 -1
- package/dist/esm/tttx-checkbox.entry.js +1 -1
- package/dist/esm/tttx-form.entry.js +1 -1
- package/dist/esm/tttx-icon.entry.js +1 -1
- package/dist/esm/tttx-list.entry.js +194 -0
- package/dist/esm/tttx-loading-spinner.entry.js +1 -1
- package/dist/esm/tttx-popover-content.entry.js +1 -1
- package/dist/esm/tttx-standalone-input.entry.js +1 -1
- package/dist/esm/tttx.js +3 -4
- package/dist/tttx/p-1b6b4223.entry.js +1 -0
- package/dist/tttx/{p-338b3976.entry.js → p-1ea7e424.entry.js} +1 -1
- package/dist/tttx/{p-1a4eb1f3.entry.js → p-629411bc.entry.js} +1 -1
- package/dist/tttx/{p-2d54f8aa.entry.js → p-7d84c410.entry.js} +1 -1
- package/dist/tttx/p-80bbe164.js +2 -0
- package/dist/tttx/{p-ad0c3fe4.entry.js → p-daa82b1b.entry.js} +1 -1
- package/dist/tttx/{p-95a29e09.entry.js → p-db1f56ba.entry.js} +1 -1
- package/dist/tttx/p-dee50f14.entry.js +1 -0
- package/dist/tttx/{p-4c57bcbd.entry.js → p-e5c02c27.entry.js} +1 -1
- package/dist/tttx/tttx.esm.js +1 -1
- package/dist/types/components/molecules/tttx-list/tttx-list.d.ts +51 -0
- package/dist/types/components/molecules/tttx-list/tttx-list.stories.d.ts +13 -0
- package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.d.ts +6 -6
- package/dist/types/components.d.ts +24 -0
- package/dist/types/stencil-public-runtime.d.ts +3 -59
- package/loader/index.d.ts +0 -9
- package/package.json +1 -1
- package/dist/tttx/p-709246f5.entry.js +0 -1
- package/dist/tttx/p-bec472d8.js +0 -2
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { h, Host } from "@stencil/core";
|
|
2
|
+
export class TttxList {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.rowCount = 0;
|
|
5
|
+
this.name = undefined;
|
|
6
|
+
this.selectable = undefined;
|
|
7
|
+
this.items = [];
|
|
8
|
+
this.selectedIds = [];
|
|
9
|
+
this.loading = true;
|
|
10
|
+
this.lastPage = false;
|
|
11
|
+
}
|
|
12
|
+
listLoadHandler(event) {
|
|
13
|
+
if (event.detail.name !== this.name)
|
|
14
|
+
return;
|
|
15
|
+
this.items = [...this.items, ...event.detail.items];
|
|
16
|
+
this.loading = false;
|
|
17
|
+
this.lastPage = event.detail.lastPage;
|
|
18
|
+
this.renderRows(event.detail.items);
|
|
19
|
+
if (this.scrollableParent.clientHeight === this.scrollableParent.scrollHeight)
|
|
20
|
+
this.listPaginateHandler();
|
|
21
|
+
}
|
|
22
|
+
listPaginateHandler() {
|
|
23
|
+
// We don't want to emit an event to load the next page if this is the last page, or if we're already loading
|
|
24
|
+
if (this.lastPage || this.loading)
|
|
25
|
+
return;
|
|
26
|
+
this.loading = true;
|
|
27
|
+
this.listPaginate.emit({ name: this.name });
|
|
28
|
+
}
|
|
29
|
+
listClearDataCacheHandler(event) {
|
|
30
|
+
if (event.detail.name !== this.name)
|
|
31
|
+
return;
|
|
32
|
+
this.items = [];
|
|
33
|
+
this.selectedIds = [];
|
|
34
|
+
this.listItemContainer()
|
|
35
|
+
.querySelectorAll(".tttx-list__row")
|
|
36
|
+
.forEach((node) => {
|
|
37
|
+
node.remove();
|
|
38
|
+
});
|
|
39
|
+
this.rowCount = 0;
|
|
40
|
+
this.lastPage = false;
|
|
41
|
+
this.loading = false;
|
|
42
|
+
}
|
|
43
|
+
listActionSelectedEventHandler(event) {
|
|
44
|
+
if (event.detail.name !== this.name || !this.selectable || this.selectedIds.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
const selectedRows = this.selectedIds.map(id => {
|
|
47
|
+
return this.items[id];
|
|
48
|
+
});
|
|
49
|
+
if (event.detail.removeRows)
|
|
50
|
+
this.removeSelectedRows();
|
|
51
|
+
this.listSelectedEvent.emit({
|
|
52
|
+
name: this.name,
|
|
53
|
+
eventName: event.detail.eventName,
|
|
54
|
+
selectedRows,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
removeSelectedRows() {
|
|
58
|
+
const orderedSelectedIds = [...this.selectedIds].sort((a, b) => {
|
|
59
|
+
return b - a;
|
|
60
|
+
});
|
|
61
|
+
orderedSelectedIds.forEach(itemIndex => {
|
|
62
|
+
this.items.splice(itemIndex, 1);
|
|
63
|
+
this.listItemContainer().removeChild(this.listItemContainer().querySelector(`[data-row-id="${itemIndex}"]`));
|
|
64
|
+
// If this removes the scrollbar and we're not on the last page, load in a new page
|
|
65
|
+
if (this.scrollableParent.clientHeight === this.scrollableParent.scrollHeight)
|
|
66
|
+
this.listPaginateHandler();
|
|
67
|
+
});
|
|
68
|
+
// Empty selected ids with mutation rather than assignment to avoid unecessary component rerender
|
|
69
|
+
this.selectedIds.splice(0, this.selectedIds.length);
|
|
70
|
+
}
|
|
71
|
+
listItemClickHandler(itemData) {
|
|
72
|
+
if (this.selectedIds.length !== 0)
|
|
73
|
+
return;
|
|
74
|
+
this.listItemClick.emit({ itemData, name: this.name });
|
|
75
|
+
}
|
|
76
|
+
componentWillLoad() {
|
|
77
|
+
this.template = this.host.querySelector("template");
|
|
78
|
+
this.scrollableParent = this.getScrollableParent(this.host);
|
|
79
|
+
const scrollableContext = this.scrollableParent === document.scrollingElement ? document : this.scrollableParent;
|
|
80
|
+
scrollableContext.addEventListener("scroll", this.scrollHandler.bind(this));
|
|
81
|
+
window.addEventListener("resize", this.scrollHandler.bind(this));
|
|
82
|
+
}
|
|
83
|
+
componentDidLoad() {
|
|
84
|
+
// Emit event to load first page
|
|
85
|
+
this.listPaginate.emit({ name: this.name });
|
|
86
|
+
}
|
|
87
|
+
listItemContainer() {
|
|
88
|
+
return this.host.shadowRoot.querySelector(".list-item-container");
|
|
89
|
+
}
|
|
90
|
+
async scrollHandler() {
|
|
91
|
+
const { clientHeight, scrollTop, scrollHeight } = this.scrollableParent;
|
|
92
|
+
if (Math.abs(scrollHeight - clientHeight - scrollTop) < 26)
|
|
93
|
+
this.listPaginateHandler();
|
|
94
|
+
}
|
|
95
|
+
isScrollable(node) {
|
|
96
|
+
const hasScrollbar = ["scroll", "auto"].includes(node.style.overflowY);
|
|
97
|
+
return hasScrollbar;
|
|
98
|
+
}
|
|
99
|
+
getScrollableParent(node) {
|
|
100
|
+
if (!node || node === document.body) {
|
|
101
|
+
return document.scrollingElement;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return this.isScrollable(node) ? node : this.getScrollableParent(node.parentElement);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
appendRowCheckbox(rowContainer) {
|
|
108
|
+
if (!this.selectable)
|
|
109
|
+
return;
|
|
110
|
+
const rowId = this.rowCount;
|
|
111
|
+
const checkbox = document.createElement("input");
|
|
112
|
+
checkbox.setAttribute("type", "checkbox");
|
|
113
|
+
checkbox.addEventListener("click", e => {
|
|
114
|
+
e.stopPropagation();
|
|
115
|
+
if (e.target.checked) {
|
|
116
|
+
this.selectedIds = [...this.selectedIds, rowId];
|
|
117
|
+
rowContainer.classList.add("selected");
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.selectedIds = this.selectedIds.filter(id => {
|
|
121
|
+
return id !== rowId;
|
|
122
|
+
});
|
|
123
|
+
rowContainer.classList.remove("selected");
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
rowContainer.setAttribute("data-row-id", `${rowId}`);
|
|
127
|
+
this.rowCount++;
|
|
128
|
+
rowContainer.appendChild(checkbox);
|
|
129
|
+
}
|
|
130
|
+
appendSeededTemplate(rowData, rowContainer) {
|
|
131
|
+
this.template.childNodes.forEach(child => {
|
|
132
|
+
const clone = child.cloneNode(false);
|
|
133
|
+
if (clone.getAttribute("data-fields")) {
|
|
134
|
+
const fields = clone.getAttribute("data-fields").replace(/\s/g, "").split(",");
|
|
135
|
+
const filteredRowData = Object.fromEntries(fields.map((field) => {
|
|
136
|
+
return [field, rowData[field]];
|
|
137
|
+
}));
|
|
138
|
+
clone.setAttribute("row-data", JSON.stringify(filteredRowData));
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
clone.setAttribute("row-data", JSON.stringify(rowData));
|
|
142
|
+
}
|
|
143
|
+
rowContainer.appendChild(clone);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
appendGenericTemplate(rowData, rowContainer) {
|
|
147
|
+
const row = document.createElement("div");
|
|
148
|
+
row.classList.add("generic-template__content");
|
|
149
|
+
row.textContent = rowData.text;
|
|
150
|
+
rowContainer.appendChild(row);
|
|
151
|
+
if (!rowData.icon)
|
|
152
|
+
return;
|
|
153
|
+
const icon = document.createElement("span");
|
|
154
|
+
icon.classList.add("material-symbols-rounded");
|
|
155
|
+
icon.textContent = rowData.icon;
|
|
156
|
+
if (rowData.iconColor)
|
|
157
|
+
icon.style["color"] = rowData.iconColor;
|
|
158
|
+
row.prepend(icon);
|
|
159
|
+
}
|
|
160
|
+
row(rowData) {
|
|
161
|
+
const rowContainer = document.createElement("div");
|
|
162
|
+
rowContainer.classList.add("tttx-list__row");
|
|
163
|
+
rowContainer.addEventListener("click", () => {
|
|
164
|
+
this.listItemClickHandler(rowData);
|
|
165
|
+
});
|
|
166
|
+
this.appendRowCheckbox(rowContainer);
|
|
167
|
+
this.template ? this.appendSeededTemplate(rowData, rowContainer) : this.appendGenericTemplate(rowData, rowContainer);
|
|
168
|
+
return rowContainer;
|
|
169
|
+
}
|
|
170
|
+
renderRows(batchData) {
|
|
171
|
+
batchData.forEach(rowData => {
|
|
172
|
+
this.listItemContainer().appendChild(this.row(rowData));
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
loadIndicator() {
|
|
176
|
+
if (!this.loading)
|
|
177
|
+
return;
|
|
178
|
+
return h("div", { class: "load-indicator" }, h("tttx-loading-spinner", { size: 'large' }));
|
|
179
|
+
}
|
|
180
|
+
render() {
|
|
181
|
+
return (h(Host, null, h("div", { class: "list-item-container", tabindex: "0" }, !this.loading && this.items.length === 0 ? "No data to display" : undefined), this.loadIndicator()));
|
|
182
|
+
}
|
|
183
|
+
static get is() { return "tttx-list"; }
|
|
184
|
+
static get encapsulation() { return "shadow"; }
|
|
185
|
+
static get originalStyleUrls() {
|
|
186
|
+
return {
|
|
187
|
+
"$": ["tttx-list.scss"]
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
static get styleUrls() {
|
|
191
|
+
return {
|
|
192
|
+
"$": ["tttx-list.css"]
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
static get properties() {
|
|
196
|
+
return {
|
|
197
|
+
"name": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"mutable": false,
|
|
200
|
+
"complexType": {
|
|
201
|
+
"original": "string",
|
|
202
|
+
"resolved": "string",
|
|
203
|
+
"references": {}
|
|
204
|
+
},
|
|
205
|
+
"required": false,
|
|
206
|
+
"optional": false,
|
|
207
|
+
"docs": {
|
|
208
|
+
"tags": [],
|
|
209
|
+
"text": ""
|
|
210
|
+
},
|
|
211
|
+
"attribute": "name",
|
|
212
|
+
"reflect": false
|
|
213
|
+
},
|
|
214
|
+
"selectable": {
|
|
215
|
+
"type": "boolean",
|
|
216
|
+
"mutable": false,
|
|
217
|
+
"complexType": {
|
|
218
|
+
"original": "boolean",
|
|
219
|
+
"resolved": "boolean",
|
|
220
|
+
"references": {}
|
|
221
|
+
},
|
|
222
|
+
"required": false,
|
|
223
|
+
"optional": false,
|
|
224
|
+
"docs": {
|
|
225
|
+
"tags": [],
|
|
226
|
+
"text": ""
|
|
227
|
+
},
|
|
228
|
+
"attribute": "selectable",
|
|
229
|
+
"reflect": false
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
static get states() {
|
|
234
|
+
return {
|
|
235
|
+
"items": {},
|
|
236
|
+
"selectedIds": {},
|
|
237
|
+
"loading": {},
|
|
238
|
+
"lastPage": {}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
static get events() {
|
|
242
|
+
return [{
|
|
243
|
+
"method": "listPaginate",
|
|
244
|
+
"name": "listPaginate",
|
|
245
|
+
"bubbles": true,
|
|
246
|
+
"cancelable": true,
|
|
247
|
+
"composed": true,
|
|
248
|
+
"docs": {
|
|
249
|
+
"tags": [],
|
|
250
|
+
"text": ""
|
|
251
|
+
},
|
|
252
|
+
"complexType": {
|
|
253
|
+
"original": "any",
|
|
254
|
+
"resolved": "any",
|
|
255
|
+
"references": {}
|
|
256
|
+
}
|
|
257
|
+
}, {
|
|
258
|
+
"method": "listSelectedEvent",
|
|
259
|
+
"name": "listSelectedEvent",
|
|
260
|
+
"bubbles": true,
|
|
261
|
+
"cancelable": true,
|
|
262
|
+
"composed": true,
|
|
263
|
+
"docs": {
|
|
264
|
+
"tags": [],
|
|
265
|
+
"text": ""
|
|
266
|
+
},
|
|
267
|
+
"complexType": {
|
|
268
|
+
"original": "any",
|
|
269
|
+
"resolved": "any",
|
|
270
|
+
"references": {}
|
|
271
|
+
}
|
|
272
|
+
}, {
|
|
273
|
+
"method": "listItemClick",
|
|
274
|
+
"name": "listItemClick",
|
|
275
|
+
"bubbles": true,
|
|
276
|
+
"cancelable": true,
|
|
277
|
+
"composed": true,
|
|
278
|
+
"docs": {
|
|
279
|
+
"tags": [],
|
|
280
|
+
"text": ""
|
|
281
|
+
},
|
|
282
|
+
"complexType": {
|
|
283
|
+
"original": "any",
|
|
284
|
+
"resolved": "any",
|
|
285
|
+
"references": {}
|
|
286
|
+
}
|
|
287
|
+
}];
|
|
288
|
+
}
|
|
289
|
+
static get elementRef() { return "host"; }
|
|
290
|
+
static get listeners() {
|
|
291
|
+
return [{
|
|
292
|
+
"name": "listPageLoad",
|
|
293
|
+
"method": "listLoadHandler",
|
|
294
|
+
"target": "document",
|
|
295
|
+
"capture": false,
|
|
296
|
+
"passive": false
|
|
297
|
+
}, {
|
|
298
|
+
"name": "listClearDataCache",
|
|
299
|
+
"method": "listClearDataCacheHandler",
|
|
300
|
+
"target": "document",
|
|
301
|
+
"capture": false,
|
|
302
|
+
"passive": false
|
|
303
|
+
}, {
|
|
304
|
+
"name": "listActionSelectedEvent",
|
|
305
|
+
"method": "listActionSelectedEventHandler",
|
|
306
|
+
"target": "document",
|
|
307
|
+
"capture": false,
|
|
308
|
+
"passive": false
|
|
309
|
+
}];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
title: "molecules/List",
|
|
3
|
+
component: "tttx-list",
|
|
4
|
+
argTypes: {
|
|
5
|
+
selectable: {
|
|
6
|
+
control: {
|
|
7
|
+
type: "boolean"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const ListWithGenericTemplate = (args) => {
|
|
13
|
+
return `
|
|
14
|
+
<script>
|
|
15
|
+
function loadPage (event) {
|
|
16
|
+
const page = new CustomEvent('listPageLoad', {
|
|
17
|
+
detail: {
|
|
18
|
+
name: 'listWithGenericTemplate',
|
|
19
|
+
lastPage: true,
|
|
20
|
+
items: [
|
|
21
|
+
{ text: 'Row with only text' },
|
|
22
|
+
{ text: 'Row with text and an icon', icon: 'sentiment_calm' },
|
|
23
|
+
{ text: 'Row with text and a coloured icon', icon: 'check_circle', iconColor: 'blue' },
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
document.dispatchEvent(page);
|
|
28
|
+
|
|
29
|
+
// Stop this event handler from being duplicated every time the storybook iframe is reloaded
|
|
30
|
+
document.removeEventListener("listPaginate", loadPage);
|
|
31
|
+
}
|
|
32
|
+
document.addEventListener("listPaginate", loadPage);
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<tttx-list ${args.selectable ? "selectable" : ""} name='listWithGenericTemplate' />
|
|
36
|
+
`;
|
|
37
|
+
};
|
|
@@ -3,6 +3,7 @@ export { TttxButton as TttxButton } from '../types/components/atoms/tttx-button/
|
|
|
3
3
|
export { TttxCheckbox as TttxCheckbox } from '../types/components/atoms/ttx-checkbox/tttx-checkbox';
|
|
4
4
|
export { TttxForm as TttxForm } from '../types/components/molecules/tttx-form/tttx-form';
|
|
5
5
|
export { TttxIcon as TttxIcon } from '../types/components/atoms/tttx-icon/tttx-icon';
|
|
6
|
+
export { TttxList as TttxList } from '../types/components/molecules/tttx-list/tttx-list';
|
|
6
7
|
export { TttxLoadingSpinner as TttxLoadingSpinner } from '../types/components/atoms/tttx-loading-spinner/tttx-loading-spinner';
|
|
7
8
|
export { TttxPopoverContent as TttxPopoverContent } from '../types/components/atoms/tttx-popover-content/tttx-popover-content';
|
|
8
9
|
export { TttxInput as TttxStandaloneInput } from '../types/components/molecules/tttx-standalone-input/tttx-standalone-input';
|
|
@@ -19,15 +20,6 @@ export { TttxInput as TttxStandaloneInput } from '../types/components/molecules/
|
|
|
19
20
|
*/
|
|
20
21
|
export declare const setAssetPath: (path: string) => void;
|
|
21
22
|
|
|
22
|
-
/**
|
|
23
|
-
* Used to specify a nonce value that corresponds with an application's CSP.
|
|
24
|
-
* When set, the nonce will be added to all dynamically created script and style tags at runtime.
|
|
25
|
-
* Alternatively, the nonce value can be set on a meta tag in the DOM head
|
|
26
|
-
* (<meta name="csp-nonce" content="{ nonce value here }" />) which
|
|
27
|
-
* will result in the same behavior.
|
|
28
|
-
*/
|
|
29
|
-
export declare const setNonce: (nonce: string) => void
|
|
30
|
-
|
|
31
23
|
export interface SetPlatformOptions {
|
|
32
24
|
raf?: (c: FrameRequestCallback) => number;
|
|
33
25
|
ael?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
|
package/dist/components/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export { setAssetPath,
|
|
1
|
+
export { setAssetPath, setPlatformOptions } from '@stencil/core/internal/client';
|
|
2
2
|
export { TttxButton, defineCustomElement as defineCustomElementTttxButton } from './tttx-button.js';
|
|
3
3
|
export { TttxCheckbox, defineCustomElement as defineCustomElementTttxCheckbox } from './tttx-checkbox.js';
|
|
4
4
|
export { TttxForm, defineCustomElement as defineCustomElementTttxForm } from './tttx-form.js';
|
|
5
5
|
export { TttxIcon, defineCustomElement as defineCustomElementTttxIcon } from './tttx-icon.js';
|
|
6
|
+
export { TttxList, defineCustomElement as defineCustomElementTttxList } from './tttx-list.js';
|
|
6
7
|
export { TttxLoadingSpinner, defineCustomElement as defineCustomElementTttxLoadingSpinner } from './tttx-loading-spinner.js';
|
|
7
8
|
export { TttxPopoverContent, defineCustomElement as defineCustomElementTttxPopoverContent } from './tttx-popover-content.js';
|
|
8
9
|
export { TttxStandaloneInput, defineCustomElement as defineCustomElementTttxStandaloneInput } from './tttx-standalone-input.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Components, JSX } from "../types/components";
|
|
2
|
+
|
|
3
|
+
interface TttxList extends Components.TttxList, HTMLElement {}
|
|
4
|
+
export const TttxList: {
|
|
5
|
+
prototype: TttxList;
|
|
6
|
+
new (): TttxList;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Used to define this component and all nested components recursively.
|
|
10
|
+
*/
|
|
11
|
+
export const defineCustomElement: () => void;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
|
|
2
|
+
import { d as defineCustomElement$2 } from './tttx-loading-spinner2.js';
|
|
3
|
+
|
|
4
|
+
const tttxListCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-family:\"Material Symbols Rounded\", sans-serif;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:#9e9e9e}:host{display:flex;flex-direction:column}.tttx-list__row{min-height:52px;line-height:36px;padding:8px;display:flex;flex-direction:row;align-items:center;cursor:pointer;border-bottom:1px solid #d5d5d5}.tttx-list__row .generic-template__content{width:100%;display:flex;align-items:center;gap:8px}.tttx-list__row:first-of-type{border-top:1px solid #d5d5d5}.tttx-list__row:focus,.tttx-list__row:active{background-color:#e6e6e6}.tttx-list__row.selected{background-color:#e7f1f9}.load-indicator{display:flex;justify-content:center}";
|
|
5
|
+
|
|
6
|
+
const TttxList$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.__registerHost();
|
|
10
|
+
this.__attachShadow();
|
|
11
|
+
this.listPaginate = createEvent(this, "listPaginate", 7);
|
|
12
|
+
this.listSelectedEvent = createEvent(this, "listSelectedEvent", 7);
|
|
13
|
+
this.listItemClick = createEvent(this, "listItemClick", 7);
|
|
14
|
+
this.rowCount = 0;
|
|
15
|
+
this.name = undefined;
|
|
16
|
+
this.selectable = undefined;
|
|
17
|
+
this.items = [];
|
|
18
|
+
this.selectedIds = [];
|
|
19
|
+
this.loading = true;
|
|
20
|
+
this.lastPage = false;
|
|
21
|
+
}
|
|
22
|
+
listLoadHandler(event) {
|
|
23
|
+
if (event.detail.name !== this.name)
|
|
24
|
+
return;
|
|
25
|
+
this.items = [...this.items, ...event.detail.items];
|
|
26
|
+
this.loading = false;
|
|
27
|
+
this.lastPage = event.detail.lastPage;
|
|
28
|
+
this.renderRows(event.detail.items);
|
|
29
|
+
if (this.scrollableParent.clientHeight === this.scrollableParent.scrollHeight)
|
|
30
|
+
this.listPaginateHandler();
|
|
31
|
+
}
|
|
32
|
+
listPaginateHandler() {
|
|
33
|
+
// We don't want to emit an event to load the next page if this is the last page, or if we're already loading
|
|
34
|
+
if (this.lastPage || this.loading)
|
|
35
|
+
return;
|
|
36
|
+
this.loading = true;
|
|
37
|
+
this.listPaginate.emit({ name: this.name });
|
|
38
|
+
}
|
|
39
|
+
listClearDataCacheHandler(event) {
|
|
40
|
+
if (event.detail.name !== this.name)
|
|
41
|
+
return;
|
|
42
|
+
this.items = [];
|
|
43
|
+
this.selectedIds = [];
|
|
44
|
+
this.listItemContainer()
|
|
45
|
+
.querySelectorAll(".tttx-list__row")
|
|
46
|
+
.forEach((node) => {
|
|
47
|
+
node.remove();
|
|
48
|
+
});
|
|
49
|
+
this.rowCount = 0;
|
|
50
|
+
this.lastPage = false;
|
|
51
|
+
this.loading = false;
|
|
52
|
+
}
|
|
53
|
+
listActionSelectedEventHandler(event) {
|
|
54
|
+
if (event.detail.name !== this.name || !this.selectable || this.selectedIds.length === 0)
|
|
55
|
+
return;
|
|
56
|
+
const selectedRows = this.selectedIds.map(id => {
|
|
57
|
+
return this.items[id];
|
|
58
|
+
});
|
|
59
|
+
if (event.detail.removeRows)
|
|
60
|
+
this.removeSelectedRows();
|
|
61
|
+
this.listSelectedEvent.emit({
|
|
62
|
+
name: this.name,
|
|
63
|
+
eventName: event.detail.eventName,
|
|
64
|
+
selectedRows,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
removeSelectedRows() {
|
|
68
|
+
const orderedSelectedIds = [...this.selectedIds].sort((a, b) => {
|
|
69
|
+
return b - a;
|
|
70
|
+
});
|
|
71
|
+
orderedSelectedIds.forEach(itemIndex => {
|
|
72
|
+
this.items.splice(itemIndex, 1);
|
|
73
|
+
this.listItemContainer().removeChild(this.listItemContainer().querySelector(`[data-row-id="${itemIndex}"]`));
|
|
74
|
+
// If this removes the scrollbar and we're not on the last page, load in a new page
|
|
75
|
+
if (this.scrollableParent.clientHeight === this.scrollableParent.scrollHeight)
|
|
76
|
+
this.listPaginateHandler();
|
|
77
|
+
});
|
|
78
|
+
// Empty selected ids with mutation rather than assignment to avoid unecessary component rerender
|
|
79
|
+
this.selectedIds.splice(0, this.selectedIds.length);
|
|
80
|
+
}
|
|
81
|
+
listItemClickHandler(itemData) {
|
|
82
|
+
if (this.selectedIds.length !== 0)
|
|
83
|
+
return;
|
|
84
|
+
this.listItemClick.emit({ itemData, name: this.name });
|
|
85
|
+
}
|
|
86
|
+
componentWillLoad() {
|
|
87
|
+
this.template = this.host.querySelector("template");
|
|
88
|
+
this.scrollableParent = this.getScrollableParent(this.host);
|
|
89
|
+
const scrollableContext = this.scrollableParent === document.scrollingElement ? document : this.scrollableParent;
|
|
90
|
+
scrollableContext.addEventListener("scroll", this.scrollHandler.bind(this));
|
|
91
|
+
window.addEventListener("resize", this.scrollHandler.bind(this));
|
|
92
|
+
}
|
|
93
|
+
componentDidLoad() {
|
|
94
|
+
// Emit event to load first page
|
|
95
|
+
this.listPaginate.emit({ name: this.name });
|
|
96
|
+
}
|
|
97
|
+
listItemContainer() {
|
|
98
|
+
return this.host.shadowRoot.querySelector(".list-item-container");
|
|
99
|
+
}
|
|
100
|
+
async scrollHandler() {
|
|
101
|
+
const { clientHeight, scrollTop, scrollHeight } = this.scrollableParent;
|
|
102
|
+
if (Math.abs(scrollHeight - clientHeight - scrollTop) < 26)
|
|
103
|
+
this.listPaginateHandler();
|
|
104
|
+
}
|
|
105
|
+
isScrollable(node) {
|
|
106
|
+
const hasScrollbar = ["scroll", "auto"].includes(node.style.overflowY);
|
|
107
|
+
return hasScrollbar;
|
|
108
|
+
}
|
|
109
|
+
getScrollableParent(node) {
|
|
110
|
+
if (!node || node === document.body) {
|
|
111
|
+
return document.scrollingElement;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return this.isScrollable(node) ? node : this.getScrollableParent(node.parentElement);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
appendRowCheckbox(rowContainer) {
|
|
118
|
+
if (!this.selectable)
|
|
119
|
+
return;
|
|
120
|
+
const rowId = this.rowCount;
|
|
121
|
+
const checkbox = document.createElement("input");
|
|
122
|
+
checkbox.setAttribute("type", "checkbox");
|
|
123
|
+
checkbox.addEventListener("click", e => {
|
|
124
|
+
e.stopPropagation();
|
|
125
|
+
if (e.target.checked) {
|
|
126
|
+
this.selectedIds = [...this.selectedIds, rowId];
|
|
127
|
+
rowContainer.classList.add("selected");
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.selectedIds = this.selectedIds.filter(id => {
|
|
131
|
+
return id !== rowId;
|
|
132
|
+
});
|
|
133
|
+
rowContainer.classList.remove("selected");
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
rowContainer.setAttribute("data-row-id", `${rowId}`);
|
|
137
|
+
this.rowCount++;
|
|
138
|
+
rowContainer.appendChild(checkbox);
|
|
139
|
+
}
|
|
140
|
+
appendSeededTemplate(rowData, rowContainer) {
|
|
141
|
+
this.template.childNodes.forEach(child => {
|
|
142
|
+
const clone = child.cloneNode(false);
|
|
143
|
+
if (clone.getAttribute("data-fields")) {
|
|
144
|
+
const fields = clone.getAttribute("data-fields").replace(/\s/g, "").split(",");
|
|
145
|
+
const filteredRowData = Object.fromEntries(fields.map((field) => {
|
|
146
|
+
return [field, rowData[field]];
|
|
147
|
+
}));
|
|
148
|
+
clone.setAttribute("row-data", JSON.stringify(filteredRowData));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
clone.setAttribute("row-data", JSON.stringify(rowData));
|
|
152
|
+
}
|
|
153
|
+
rowContainer.appendChild(clone);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
appendGenericTemplate(rowData, rowContainer) {
|
|
157
|
+
const row = document.createElement("div");
|
|
158
|
+
row.classList.add("generic-template__content");
|
|
159
|
+
row.textContent = rowData.text;
|
|
160
|
+
rowContainer.appendChild(row);
|
|
161
|
+
if (!rowData.icon)
|
|
162
|
+
return;
|
|
163
|
+
const icon = document.createElement("span");
|
|
164
|
+
icon.classList.add("material-symbols-rounded");
|
|
165
|
+
icon.textContent = rowData.icon;
|
|
166
|
+
if (rowData.iconColor)
|
|
167
|
+
icon.style["color"] = rowData.iconColor;
|
|
168
|
+
row.prepend(icon);
|
|
169
|
+
}
|
|
170
|
+
row(rowData) {
|
|
171
|
+
const rowContainer = document.createElement("div");
|
|
172
|
+
rowContainer.classList.add("tttx-list__row");
|
|
173
|
+
rowContainer.addEventListener("click", () => {
|
|
174
|
+
this.listItemClickHandler(rowData);
|
|
175
|
+
});
|
|
176
|
+
this.appendRowCheckbox(rowContainer);
|
|
177
|
+
this.template ? this.appendSeededTemplate(rowData, rowContainer) : this.appendGenericTemplate(rowData, rowContainer);
|
|
178
|
+
return rowContainer;
|
|
179
|
+
}
|
|
180
|
+
renderRows(batchData) {
|
|
181
|
+
batchData.forEach(rowData => {
|
|
182
|
+
this.listItemContainer().appendChild(this.row(rowData));
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
loadIndicator() {
|
|
186
|
+
if (!this.loading)
|
|
187
|
+
return;
|
|
188
|
+
return h("div", { class: "load-indicator" }, h("tttx-loading-spinner", { size: 'large' }));
|
|
189
|
+
}
|
|
190
|
+
render() {
|
|
191
|
+
return (h(Host, null, h("div", { class: "list-item-container", tabindex: "0" }, !this.loading && this.items.length === 0 ? "No data to display" : undefined), this.loadIndicator()));
|
|
192
|
+
}
|
|
193
|
+
get host() { return this; }
|
|
194
|
+
static get style() { return tttxListCss; }
|
|
195
|
+
}, [1, "tttx-list", {
|
|
196
|
+
"name": [1],
|
|
197
|
+
"selectable": [4],
|
|
198
|
+
"items": [32],
|
|
199
|
+
"selectedIds": [32],
|
|
200
|
+
"loading": [32],
|
|
201
|
+
"lastPage": [32]
|
|
202
|
+
}, [[4, "listPageLoad", "listLoadHandler"], [4, "listClearDataCache", "listClearDataCacheHandler"], [4, "listActionSelectedEvent", "listActionSelectedEventHandler"]]]);
|
|
203
|
+
function defineCustomElement$1() {
|
|
204
|
+
if (typeof customElements === "undefined") {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const components = ["tttx-list", "tttx-loading-spinner"];
|
|
208
|
+
components.forEach(tagName => { switch (tagName) {
|
|
209
|
+
case "tttx-list":
|
|
210
|
+
if (!customElements.get(tagName)) {
|
|
211
|
+
customElements.define(tagName, TttxList$1);
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
case "tttx-loading-spinner":
|
|
215
|
+
if (!customElements.get(tagName)) {
|
|
216
|
+
defineCustomElement$2();
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
} });
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const TttxList = TttxList$1;
|
|
223
|
+
const defineCustomElement = defineCustomElement$1;
|
|
224
|
+
|
|
225
|
+
export { TttxList, defineCustomElement };
|
|
@@ -1,41 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const tttxLoadingSpinnerCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.spinner-container{position:absolute}.loading-box{display:flex;align-items:center;justify-content:center}.loading-text{font-size:16px;font-weight:400;padding-top:10px;text-align:center}.spinner{border:solid #1479c6;border-bottom-color:#d5d5d5;border-radius:50%;position:relative;box-sizing:border-box;animation:rotation 1s linear infinite}.spinner.small{height:20px;width:20px;border-width:4px}.spinner.large{height:60px;width:60px;border-width:8px}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";
|
|
4
|
-
|
|
5
|
-
const TttxLoadingSpinner$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
this.__registerHost();
|
|
9
|
-
this.__attachShadow();
|
|
10
|
-
this.loadingMessage = undefined;
|
|
11
|
-
this.size = 'large';
|
|
12
|
-
}
|
|
13
|
-
renderLoadingMessage() {
|
|
14
|
-
if (!this.loadingMessage)
|
|
15
|
-
return '';
|
|
16
|
-
return h("div", { class: "loading-text" }, "Loading, please wait...");
|
|
17
|
-
}
|
|
18
|
-
render() {
|
|
19
|
-
return (h("div", { class: "spinner-container" }, h("div", { class: "loading-box" }, h("span", { class: `spinner ${this.size}` })), this.renderLoadingMessage()));
|
|
20
|
-
}
|
|
21
|
-
static get style() { return tttxLoadingSpinnerCss; }
|
|
22
|
-
}, [1, "tttx-loading-spinner", {
|
|
23
|
-
"loadingMessage": [1028, "loading-message"],
|
|
24
|
-
"size": [1025]
|
|
25
|
-
}]);
|
|
26
|
-
function defineCustomElement$1() {
|
|
27
|
-
if (typeof customElements === "undefined") {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const components = ["tttx-loading-spinner"];
|
|
31
|
-
components.forEach(tagName => { switch (tagName) {
|
|
32
|
-
case "tttx-loading-spinner":
|
|
33
|
-
if (!customElements.get(tagName)) {
|
|
34
|
-
customElements.define(tagName, TttxLoadingSpinner$1);
|
|
35
|
-
}
|
|
36
|
-
break;
|
|
37
|
-
} });
|
|
38
|
-
}
|
|
1
|
+
import { T as TttxLoadingSpinner$1, d as defineCustomElement$1 } from './tttx-loading-spinner2.js';
|
|
39
2
|
|
|
40
3
|
const TttxLoadingSpinner = TttxLoadingSpinner$1;
|
|
41
4
|
const defineCustomElement = defineCustomElement$1;
|