@api-client/ui 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/.eslintrc +8 -0
- package/demo/elements/index.html +3 -0
- package/demo/elements/store/file-picker.html +15 -0
- package/demo/elements/store/file-picker.ts +134 -0
- package/demo/elements/store/index.html +19 -0
- package/demo/store/StorePlugin.js +1 -0
- package/dist/bindings/base/StoreBindings.d.ts +5 -0
- package/dist/bindings/base/StoreBindings.d.ts.map +1 -1
- package/dist/bindings/base/StoreBindings.js +15 -1
- package/dist/bindings/base/StoreBindings.js.map +1 -1
- package/dist/define/store/file-picker.d.ts +9 -0
- package/dist/define/store/file-picker.d.ts.map +1 -0
- package/dist/define/store/file-picker.js +10 -0
- package/dist/define/store/file-picker.js.map +1 -0
- package/dist/define/{files → store}/share-file.d.ts +1 -1
- package/dist/define/store/share-file.d.ts.map +1 -0
- package/dist/define/{files → store}/share-file.js +2 -2
- package/dist/define/store/share-file.js.map +1 -0
- package/dist/elements/store/FilePicker.element.d.ts +87 -0
- package/dist/elements/store/FilePicker.element.d.ts.map +1 -0
- package/dist/elements/store/FilePicker.element.js +263 -0
- package/dist/elements/store/FilePicker.element.js.map +1 -0
- package/dist/elements/store/FilePicker.styles.d.ts +3 -0
- package/dist/elements/store/FilePicker.styles.d.ts.map +1 -0
- package/dist/elements/store/FilePicker.styles.js +72 -0
- package/dist/elements/store/FilePicker.styles.js.map +1 -0
- package/dist/elements/store/FilesLib.d.ts +10 -0
- package/dist/elements/store/FilesLib.d.ts.map +1 -0
- package/dist/elements/store/FilesLib.js +38 -0
- package/dist/elements/store/FilesLib.js.map +1 -0
- package/dist/elements/{files/ShareFile.d.ts → store/ShareFile.element.d.ts} +1 -1
- package/dist/elements/store/ShareFile.element.d.ts.map +1 -0
- package/dist/elements/{files/ShareFile.js → store/ShareFile.element.js} +1 -1
- package/dist/elements/store/ShareFile.element.js.map +1 -0
- package/dist/elements/store/ShareFile.styles.d.ts.map +1 -0
- package/dist/elements/{files → store}/ShareFile.styles.js.map +1 -1
- package/dist/events/EventTypes.d.ts +1 -0
- package/dist/events/EventTypes.d.ts.map +1 -1
- package/dist/events/EventTypes.js +1 -0
- package/dist/events/EventTypes.js.map +1 -1
- package/dist/events/Events.d.ts +1 -0
- package/dist/events/Events.d.ts.map +1 -1
- package/dist/events/StoreEvents.d.ts +8 -1
- package/dist/events/StoreEvents.d.ts.map +1 -1
- package/dist/events/StoreEvents.js +19 -0
- package/dist/events/StoreEvents.js.map +1 -1
- package/dist/pages/ApplicationScreen.d.ts +1 -1
- package/dist/pages/ApplicationScreen.d.ts.map +1 -1
- package/dist/pages/ApplicationScreen.js +4 -2
- package/dist/pages/ApplicationScreen.js.map +1 -1
- package/dist/pages/api-client/ApiClient.screen.d.ts +0 -6
- package/dist/pages/api-client/ApiClient.screen.d.ts.map +1 -1
- package/dist/pages/api-client/ApiClient.screen.js +16 -29
- package/dist/pages/api-client/ApiClient.screen.js.map +1 -1
- package/dist/pages/api-client/Authenticate.screen.d.ts +1 -1
- package/dist/pages/api-client/Authenticate.screen.d.ts.map +1 -1
- package/dist/pages/api-client/Authenticate.screen.js +2 -2
- package/dist/pages/api-client/Authenticate.screen.js.map +1 -1
- package/dist/pages/api-client/pages/Files.page.d.ts +6 -35
- package/dist/pages/api-client/pages/Files.page.d.ts.map +1 -1
- package/dist/pages/api-client/pages/Files.page.js +32 -141
- package/dist/pages/api-client/pages/Files.page.js.map +1 -1
- package/dist/pages/api-client/pages/Shared.page.d.ts +1 -5
- package/dist/pages/api-client/pages/Shared.page.d.ts.map +1 -1
- package/dist/pages/api-client/pages/Shared.page.js +1 -40
- package/dist/pages/api-client/pages/Shared.page.js.map +1 -1
- package/dist/pages/demo/DemoPage.d.ts +7 -0
- package/dist/pages/demo/DemoPage.d.ts.map +1 -1
- package/dist/pages/demo/DemoPage.js +14 -0
- package/dist/pages/demo/DemoPage.js.map +1 -1
- package/dist/store/FileSystem.d.ts +90 -0
- package/dist/store/FileSystem.d.ts.map +1 -0
- package/dist/store/FileSystem.js +260 -0
- package/dist/store/FileSystem.js.map +1 -0
- package/dist/styles/global-styles.d.ts.map +1 -1
- package/dist/styles/global-styles.js +7 -0
- package/dist/styles/global-styles.js.map +1 -1
- package/dist/ui/icons/Icons.d.ts +2 -1
- package/dist/ui/icons/Icons.d.ts.map +1 -1
- package/dist/ui/icons/Icons.js +1 -0
- package/dist/ui/icons/Icons.js.map +1 -1
- package/dist/ui/list/UiDropdownList.d.ts +9 -1
- package/dist/ui/list/UiDropdownList.d.ts.map +1 -1
- package/dist/ui/list/UiDropdownList.js +39 -17
- package/dist/ui/list/UiDropdownList.js.map +1 -1
- package/dist/ui/list/UiList.d.ts +6 -1
- package/dist/ui/list/UiList.d.ts.map +1 -1
- package/dist/ui/list/UiList.js +24 -9
- package/dist/ui/list/UiList.js.map +1 -1
- package/dist/ui/table/DataTable.d.ts +4 -0
- package/dist/ui/table/DataTable.d.ts.map +1 -1
- package/dist/ui/table/DataTable.js +23 -1
- package/dist/ui/table/DataTable.js.map +1 -1
- package/package.json +1 -1
- package/src/bindings/base/StoreBindings.ts +16 -1
- package/src/define/store/file-picker.ts +12 -0
- package/src/define/{files → store}/share-file.ts +2 -2
- package/src/elements/store/FilePicker.element.ts +297 -0
- package/src/elements/store/FilePicker.styles.ts +72 -0
- package/src/elements/store/FilesLib.ts +32 -0
- package/src/events/EventTypes.ts +1 -0
- package/src/events/StoreEvents.ts +21 -1
- package/src/pages/ApplicationScreen.ts +5 -3
- package/src/pages/api-client/ApiClient.screen.ts +16 -31
- package/src/pages/api-client/Authenticate.screen.ts +2 -2
- package/src/pages/api-client/pages/Files.page.ts +37 -164
- package/src/pages/api-client/pages/Shared.page.ts +2 -40
- package/src/pages/demo/DemoPage.ts +17 -0
- package/src/store/FileSystem.ts +325 -0
- package/src/styles/global-styles.ts +7 -0
- package/src/ui/icons/Icons.ts +2 -1
- package/src/ui/list/UiDropdownList.ts +44 -17
- package/src/ui/list/UiList.ts +26 -10
- package/src/ui/table/DataTable.ts +29 -3
- package/test/elements/store/FilePicker.test.ts +241 -0
- package/test/env.js +3 -0
- package/test/helpers/StoreHelper.ts +390 -0
- package/tsconfig.eslint.json +3 -1
- package/web-test-runner.config.mjs +49 -3
- package/dist/define/files/share-file.d.ts.map +0 -1
- package/dist/define/files/share-file.js.map +0 -1
- package/dist/elements/files/ShareFile.d.ts.map +0 -1
- package/dist/elements/files/ShareFile.js.map +0 -1
- package/dist/elements/files/ShareFile.styles.d.ts.map +0 -1
- /package/dist/elements/{files → store}/ShareFile.styles.d.ts +0 -0
- /package/dist/elements/{files → store}/ShareFile.styles.js +0 -0
- /package/src/elements/{files/ShareFile.ts → store/ShareFile.element.ts} +0 -0
- /package/src/elements/{files → store}/ShareFile.styles.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/ui/table/DataTable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,SAAS,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAI3D,OAAO,+BAA+B,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,cAAc,EAAE,CAAC;AAIvE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,cAAc,EAAE,CAAC;AACrD,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AAC7C,KAAK,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/ui/table/DataTable.ts"],"names":[],"mappings":"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"}
|
|
@@ -158,6 +158,7 @@ export class DataTable {
|
|
|
158
158
|
this.handleClick = this.handleClick.bind(this);
|
|
159
159
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
160
160
|
this.handleFocus = this.handleFocus.bind(this);
|
|
161
|
+
this.handleListScroll = this.handleListScroll.bind(this);
|
|
161
162
|
}
|
|
162
163
|
addEventListener(type, listener) {
|
|
163
164
|
this.#listeners[type] = listener;
|
|
@@ -492,6 +493,14 @@ export class DataTable {
|
|
|
492
493
|
this.handleMultiSelection(row.dataset.key);
|
|
493
494
|
}
|
|
494
495
|
}
|
|
496
|
+
handleListScroll(e) {
|
|
497
|
+
const list = e.target;
|
|
498
|
+
const { scrollTop, offsetHeight, scrollHeight } = list;
|
|
499
|
+
const bottom = scrollTop + offsetHeight >= scrollHeight - 20; // 20 is the offset which qualifies as the end. An arbitrary number.
|
|
500
|
+
if (bottom) {
|
|
501
|
+
this.dispatchScrollEnd();
|
|
502
|
+
}
|
|
503
|
+
}
|
|
495
504
|
renderHeader() {
|
|
496
505
|
const cells = this.dispatchHeader();
|
|
497
506
|
return html `
|
|
@@ -508,7 +517,7 @@ export class DataTable {
|
|
|
508
517
|
const contents = !!items && !!items.length ? items.map(item => this.renderItem(item)) : this.renderEmpty();
|
|
509
518
|
const dbListener = active ? this.dblclickHandler : undefined;
|
|
510
519
|
return html `
|
|
511
|
-
<div class="data-table-body" role="rowgroup" @dblclick="${dbListener}">
|
|
520
|
+
<div class="data-table-body" role="rowgroup" @dblclick="${dbListener}" @scroll="${{ handleEvent: this.handleListScroll, passive: true }}">
|
|
512
521
|
${contents}
|
|
513
522
|
</div>`;
|
|
514
523
|
}
|
|
@@ -620,5 +629,18 @@ export class DataTable {
|
|
|
620
629
|
console.warn(e);
|
|
621
630
|
}
|
|
622
631
|
}
|
|
632
|
+
dispatchScrollEnd() {
|
|
633
|
+
const callback = this.#listeners.scrollend;
|
|
634
|
+
if (!callback) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
try {
|
|
638
|
+
callback();
|
|
639
|
+
}
|
|
640
|
+
catch (e) {
|
|
641
|
+
// eslint-disable-next-line no-console
|
|
642
|
+
console.warn(e);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
623
645
|
}
|
|
624
646
|
//# sourceMappingURL=DataTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../../src/ui/table/DataTable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAa,IAAI,EAAkB,MAAM,KAAK,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAa,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,+BAA+B,CAAC;AAwDvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,SAAS;IACpB,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8FT,CAAC;IACJ,CAAC;IAED,YAAY,CAAO;IAEnB,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,KAAK,CAAC,KAA+B;QACvC,IAAI,CAAC,KAAK,EAAE;YACV,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;YAC9B,OAAO;SACR;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC;IAC1B,CAAC;IAID,UAAU,CAAwB;IAElC,SAAS,CAAqB;IAc9B,YAAY,aAAiC,EAAE,UAA6B,EAAE;QAhB9E,eAAU,GAAqB,EAAE,CAAC;QAIlC;;;WAGG;QACH,aAAQ,GAAa,EAAE,CAAC;QAStB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAcD,gBAAgB,CAAC,IAAgB,EAAE,QAAsJ;QACvL,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAsB,EAAE,UAAwB,EAAE;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QAChC,OAAO,IAAI,CAAA;;sDAEuC,OAAO,CAAC,KAAK,IAAI,EAAE;oBACrD,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC;OACf,OAAO,SAAS,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,OAAsB,EAAE,UAAwB,EAAE;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QAChC,OAAO,IAAI,CAAA;;;oDAGqC,OAAO,CAAC,KAAK,IAAI,EAAE;QAC/D,QAAQ,CAAC,IAAI,CAAC;OACf,OAAO;KACT,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QACvE,OAAO,IAAI,CAAA;;;;oBAIK,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;8BAClB,OAAO,CAAC,SAAS,KAAK,OAAO;;;;gBAI3C,IAAI,CAAC,WAAW;gBAChB,aAAa;kBACX,IAAI,CAAC,aAAa;;QAE5B,IAAI,CAAC,YAAY,EAAE;;QAEnB,IAAI,CAAC,UAAU,EAAE;;KAEpB,CAAC;IACJ,CAAC;IAES,YAAY,CAAC,CAAQ;QAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAC9B,MAAM,OAAO,GAAG,OAAkB,CAAC;YACnC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;gBACrE,OAAO,IAAI,CAAC;aACb;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAA4B,CAAC;QAC9B,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;YAC5B,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAES,cAAc,CAAC,CAAQ;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;YAChC,MAAM,OAAO,GAAG,OAAkB,CAAC;YACnC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;gBACjE,OAAO,IAAI,CAAC;aACb;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAA4B,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IAES,qBAAqB,CAAC,CAAQ;QACtC,MAAM,MAAM,GAAiB;YAC3B,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;SACP,CAAC;QACF,IAAI,GAA4B,CAAC;QACjC,IAAI,MAA+B,CAAC;QACpC,IAAI,KAA8B,CAAC;QACnC,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE;YACnC,MAAM,OAAO,GAAG,OAAsB,CAAC;YACvC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;gBACrE,GAAG,GAAG,OAAO,CAAC;aACf;iBAAM,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;gBAC7E,MAAM,GAAG,OAAO,CAAC;aAClB;iBAAM,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;gBACxE,KAAK,GAAG,OAAO,CAAC;gBAChB,MAAM;aACP;SACF;QACD,IAAI,CAAC,KAAK,EAAE;YACV,OAAO,MAAM,CAAC;SACf;QACD,IAAI,GAAG,EAAE;YACP,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,IAAI,CAAC,EAAE;gBACjB,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC;aACvB;YACD,IAAI,MAAM,EAAE;gBACV,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC;gBACrE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,SAAS,IAAI,CAAC,EAAE;oBAClB,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;iBACzB;aACF;SACF;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAES,gBAAgB,CAAC,CAAQ;QACjC,IAAI,GAA4B,CAAC;QACjC,IAAI,MAA+B,CAAC;QACpC,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE;YACnC,MAAM,OAAO,GAAG,OAAsB,CAAC;YACvC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;gBACrE,GAAG,GAAG,OAAO,CAAC;gBACd,MAAM;aACP;iBAAM,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;gBAC7E,MAAM,GAAG,OAAO,CAAC;aAClB;SACF;QACD,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;YACnB,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;IACxB,CAAC;IAES,WAAW,CAAC,CAAQ;QAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAqB,CAAC;QACvC,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;YAC3C,0DAA0D;YAC1D,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;SAC7B;IACH,CAAC;IAES,eAAe,CAAC,CAAQ;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAA6B,CAAC;QAC/D,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO;SACR;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,CAAC,GAAG,EAAE;YACR,OAAO;SACR;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAE,CAAyC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC;QAC3G,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QACD,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAES,WAAW,CAAC,CAAQ;QAC5B,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,CAAC,GAAG,EAAE;YACR,OAAO;SACR;QACD,IAAI,SAAS,KAAK,QAAQ,EAAE;YAC1B,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAa,CAAC,CAAC;SACvD;aAAM,IAAI,SAAS,KAAK,OAAO,EAAE;YAChC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAa,CAAC,CAAC;SACtD;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAgB,CAAC;QACpD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAES,aAAa,CAAC,CAAgB;QACtC,IAAI,CAAC,CAAC,gBAAgB,EAAE;YACtB,OAAO;SACR;QACD,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;YACvC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;SAC7B;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE;YAClC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;SACxB;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE;YACjC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACvB;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE;YAC/B,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;SACrB;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE;YACjC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACvB;IACH,CAAC;IAES,qBAAqB,CAAC,GAAW;QACzC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC/B,OAAO;SACR;QACD,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAES,oBAAoB,CAAC,GAAW;QACxC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC1B,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC1B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SAC3B;aAAM;YACL,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACpB;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAES,cAAc,CAAC,KAAkB;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,uBAAuB,CAAuB,CAAC;QAChF,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QACD,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACrC,CAAC;IAES,SAAS,CAAC,KAAkB,EAAE,QAAgB,EAAE,QAAgB;QACxE,MAAM,GAAG,GAAG,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,EAAE;YACR,OAAO,KAAK,CAAC;SACd;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAuB,CAAC;QACtF,IAAI,CAAC,IAAI,EAAE;YACT,OAAO,KAAK,CAAC;SACd;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;SACrC;QACD,IAAI,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE;YAClC,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;SACnC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAES,cAAc,CAAC,CAAQ;QAC/B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE;YACV,OAAO;SACR;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3B,OAAO;SACR;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE;YACxD,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;SACnB;IACH,CAAC;IAES,aAAa,CAAC,CAAQ;QAC9B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE;YACV,OAAO;SACR;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3B,OAAO;SACR;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE;YACxD,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;SACnB;IACH,CAAC;IAES,aAAa,CAAC,CAAQ;QAC9B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE;YACV,OAAO;SACR;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3B,OAAO;SACR;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;YACxD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;SAClB;IACH,CAAC;IAES,WAAW,CAAC,CAAQ;QAC5B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE;YACV,OAAO;SACR;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3B,OAAO;SACR;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;YACxD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;SAClB;IACH,CAAC;IAES,mBAAmB,CAAC,CAAQ;QACpC,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QACD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAC7B,gFAAgF;QAChF,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAuB,CAAC;QAC/E,IAAI,SAAS,EAAE;YACb,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO;SACR;QACD,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,SAAS,KAAK,QAAQ,EAAE;YAC1B,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAa,CAAC,CAAC;SACvD;aAAM,IAAI,SAAS,KAAK,OAAO,EAAE;YAChC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAa,CAAC,CAAC;SACtD;IACH,CAAC;IAES,YAAY;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,OAAO,IAAI,CAAA;;;UAGL,KAAK;;;KAGV,CAAC;IACJ,CAAC;IAES,UAAU;QAClB,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAChC,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3G,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7D,OAAO,IAAI,CAAA;8DAC+C,UAAU;QAChE,QAAQ;WACL,CAAC;IACV,CAAC;IAES,UAAU,CAAC,IAAO;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACnC,MAAM,KAAK,GAAG,IAAyC,CAAC;QACxD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC;QACxC,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE;YAClC,MAAM,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC;YAC/B,IAAI,WAAW,KAAK,GAAG,EAAE;gBACvB,UAAU,GAAG,IAAI,CAAC;aACnB;SACF;aAAM,IAAI,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE;YACxC,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;SACrC;QACD,MAAM,OAAO,GAAc;YACzB,gBAAgB,EAAE,IAAI;YACtB,QAAQ,EAAE,UAAU;SACrB,CAAC;QACF,OAAO,IAAI,CAAA;6BACc,QAAQ,CAAC,OAAO,CAAC,eAAe,GAAG,oBAAoB,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;UAEvG,KAAK;;;KAGV,CAAC;IACJ,CAAC;IAES,WAAW;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACrC,OAAO,IAAI,CAAA;;;QAGP,OAAO;;;KAGV,CAAC;IACJ,CAAC;IAES,cAAc;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAA4C,CAAC;QAC9E,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,SAAS,CAAC;SAClB;QACD,IAAI,OAAqC,CAAC;QAC1C,IAAI;YACF,OAAO,GAAG,QAAQ,EAAE,CAAC;SACtB;QAAC,OAAO,CAAC,EAAE;YACV,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,YAAY,CAAC,IAAO;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,IAAmC,CAAC;QACrE,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,SAAS,CAAC;SAClB;QACD,IAAI,OAAqC,CAAC;QAC1C,IAAI;YACF,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;SAC1B;QAAC,OAAO,CAAC,EAAE;YACV,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,aAAa;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,KAAyC,CAAC;QAC3E,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,SAAS,CAAC;SAClB;QACD,IAAI,OAAmC,CAAC;QACxC,IAAI;YACF,OAAO,GAAG,QAAQ,EAAE,CAAC;SACtB;QAAC,OAAO,CAAC,EAAE;YACV,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,cAAc;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAoB,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO;SACR;QACD,IAAI;YACF,QAAQ,EAAE,CAAC;SACZ;QAAC,OAAO,CAAC,EAAE;YACV,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;IACH,CAAC;IAES,gBAAgB,CAAC,SAA4B;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAwB,CAAC;QAC1D,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO;SACR;QACD,IAAI;YACF,QAAQ,CAAC,SAAS,CAAC,CAAC;SACrB;QAAC,OAAO,CAAC,EAAE;YACV,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;IACH,CAAC;CACF","sourcesContent":["import { css, CSSResult, html, TemplateResult } from \"lit\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { ClassInfo, classMap } from \"lit/directives/class-map.js\";\nimport { dataAttr } from \"../../directives/data-attr.js\";\nimport '../../define/ui/ui-divider.js';\n\nexport interface IDataTableOptions {\n /**\n * The name of the property that identifies the key. The key is inserted into each row as `data-key`.\n * Default to `key`.\n */\n key?: string;\n /**\n * The value of the aria-label to render on the table.\n */\n ariaLabel?: string;\n\n /**\n * When true it dispatches `activate` event when the user double click on a row.\n */\n active?: boolean;\n /**\n * When set it allows a single selection. A list item is highlighted and the `select` event is dispatched when the selection change.\n */\n selection?: 'single' | 'multi';\n}\n\nexport type RenderContent = string | TemplateResult | TemplateResult[];\n\ntype DataEvents = 'header' | 'item' | 'empty' | 'activate' | 'select' | 'render';\n\ntype CellCallback<T> = (item: T) => TemplateResult[];\ntype ActivateCallback<T> = (item: T) => void;\ntype SelectCallback = (item: string | string[]) => void;\n\ntype DataEventsMap<T> = {\n [key in DataEvents]?: SelectCallback | CellCallback<T> | CellCallback<T[]> | ActivateCallback<T> | ActivateCallback<T[]> | {(): TemplateResult | TemplateResult[]};\n};\n\nexport interface ICellOptions {\n /**\n * The list of CSS class names to add to the cell.\n */\n class?: string;\n\n /**\n * The list of data attributes to set on the cell.\n */\n data?: { [key: string]: number | string | boolean };\n /**\n * The value of the aria-label to render on the cell.\n */\n ariaLabel?: string;\n}\n\ninterface CellPosition { \n row: number; \n cell: number; \n}\n\n/**\n * A helper class that allows to build a data table in a programmatic way.\n * \n * Usage:\n * \n * const dt = new DataTable(arrayOfItems, { key: 'key' });\n * // or dt.items = arrayOfItems;\n * dt.addEventListener('header', () => { \n * const c1 = dt.header('name', { class: 'name-column', data: {a: b} });\n * const c2 = dt.header('created', { class: 'created-column', data: {a: b} });\n * return [c1, c2];\n * });\n * dt.addEventListener('item', (item) => { \n * const c1 = dt.cell(html`cell template content`, { class: 'a b c', data: {a: b} });\n * const c2 = dt.cell(`cell text content`, { class: 'xyz', data: {key: 'value'} });\n * return [c1, c2];\n * });\n * dt.addEventListener('empty', () => { \n * return html`<p>The table has no records.</p>`;\n * });\n * \n * const template = dt.render();\n * \n * @fires header - An event dispatched when a table header row is being rendered.\n * @fires item - An event dispatched when a table item row is being rendered.\n * @fires empty - An event dispatched when a table has no rows to render.\n * @fires activate - An event dispatched when the user double click on a row.\n * @fires select - An event dispatched when the user selected a table item in a single or multi selection table.\n * @fires render - An event dispatched when the internal state changed and the table must be rendered again.\n */\nexport class DataTable<T> {\n static get styles(): CSSResult {\n return css`\n .data-table {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .data-table-body {\n flex: 1;\n overflow: auto;\n }\n\n .data-table-row {\n height: 44px;\n position: relative;\n\n display: flex;\n align-items: center;\n\n font-family: var(--md-sys-typescale-body-medium-font-family-name);\n font-style: var(--md-sys-typescale-body-medium-font-family-style);\n font-weight: var(--md-sys-typescale-body-medium-font-weight);\n font-size: var(--md-sys-typescale-body-medium-font-size);\n letter-spacing: var(--md-sys-typescale-body-medium-tracking);\n line-height: var(--md-sys-typescale-body-medium-height);\n text-transform: var(--md-sys-typescale-body-medium-text-transform);\n text-decoration: var(--md-sys-typescale-body-medium-text-decoration);\n }\n\n .data-table-row-body {\n height: inherit;\n display: flex;\n align-items: center;\n flex: 1;\n }\n\n .data-table-body .data-table-row:not(.data-table-empty-row):hover::before {\n content: '';\n background-color: var(--md-sys-color-on-surface);\n opacity: var(--md-sys-state-hover-state-layer-opacity);\n position: absolute;\n inset: 0;\n z-index: -1;\n }\n\n .data-table-header {\n font-family: var(--md-sys-typescale-label-large-font-family-name);\n font-style: var(--md-sys-typescale-label-large-font-family-style);\n font-weight: var(--md-sys-typescale-label-large-font-weight);\n font-size: var(--md-sys-typescale-label-large-font-size);\n letter-spacing: var(--md-sys-typescale-label-large-tracking);\n line-height: var(--md-sys-typescale-label-large-height);\n text-transform: var(--md-sys-typescale-label-large-text-transform);\n text-decoration: var(--md-sys-typescale-label-large-text-decoration);\n }\n\n .data-table-cell {\n display: flex;\n align-items: center;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n height: inherit;\n padding: 12px;\n box-sizing: border-box;\n position: relative;\n }\n\n .data-table-row.data-table-empty-row {\n height: auto;\n display: block;\n }\n\n .data-table-row.data-table-empty-row > [role=cell] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n }\n\n .selected {\n background-color: var(--md-sys-color-secondary-container);\n border-radius: 8px;\n }\n\n .data-table-cell:focus-visible::before {\n content: '';\n background-color: var(--md-sys-color-on-surface);\n opacity: var(--md-sys-state-focus-state-layer-opacity);\n position: absolute;\n inset: 0;\n z-index: -1;\n }\n `;\n }\n\n #renderItems?: T[];\n\n get items(): ArrayLike<T> | undefined {\n return this.#renderItems;\n }\n\n set items(value: ArrayLike<T> | undefined) {\n if (!value) {\n this.#renderItems = undefined;\n return;\n }\n const arr = Array.from(value);\n this.#renderItems = arr;\n }\n\n options: IDataTableOptions;\n \n #listeners: DataEventsMap<T> = {};\n\n #getItems: () => ArrayLike<T>;\n\n /**\n * The list of keys that correspond to the `key` set on the options of items that are currently selected.\n * Note, this is a common list for single and multi selection. In a single selection only the first is taken into account.\n */\n selected: string[] = [];\n\n /**\n * Describes currently focused cell.\n * The `row` is the index of the focused row (starting with the header) and the `cell` is the index of the focused cell.\n */\n protected focused?: CellPosition;\n\n constructor(itemsCallback: () => ArrayLike<T>, options: IDataTableOptions = {}) {\n this.options = options;\n this.#getItems = itemsCallback;\n this.dblclickHandler = this.dblclickHandler.bind(this);\n this.handleClick = this.handleClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleFocus = this.handleFocus.bind(this);\n }\n\n addEventListener(type: 'header', listener: () => TemplateResult[]): void;\n\n addEventListener(type: 'render', listener: () => void): void;\n\n addEventListener(type: 'item', listener: CellCallback<T>): void;\n\n addEventListener(type: 'empty', listener: () => TemplateResult): void;\n\n addEventListener(type: 'activate', listener: ActivateCallback<T>): void;\n\n addEventListener(type: 'select', listener: SelectCallback): void;\n\n addEventListener(type: DataEvents, listener: SelectCallback | CellCallback<T> | CellCallback<T[]> | ActivateCallback<T> | ActivateCallback<T[]> | {(): TemplateResult | TemplateResult[]}): void {\n this.#listeners[type] = listener;\n }\n\n /**\n * Renders a header cell.\n * \n * @param content The content of the header cell to render.\n * @param options Cell rendering options\n */\n header(content: RenderContent, options: ICellOptions = {}): TemplateResult {\n const data = options.data || {};\n return html`<span \n role=\"columnheader\" \n class=\"data-table-cell data-table-header-cell ${options.class || ''}\"\n aria-label=\"${ifDefined(options.ariaLabel)}\"\n ${dataAttr(data)}\n >${content}</span>`;\n }\n\n /**\n * Renders a body cell.\n * \n * @param content The content of the header cell to render.\n * @param options Cell rendering options\n */\n cell(content: RenderContent, options: ICellOptions = {}): TemplateResult {\n const data = options.data || {};\n return html`\n <span \n role=\"gridcell\" \n class=\"data-table-cell data-table-body-cell ${options.class || ''}\"\n ${dataAttr(data)}\n >${content}</span>\n `;\n }\n\n render(): TemplateResult {\n this.items = this.#getItems();\n const { options } = this;\n const clickListener = options.selection ? this.handleClick : undefined;\n return html`\n <div \n class=\"data-table\" \n role=\"grid\" \n aria-label=\"${ifDefined(options.ariaLabel)}\"\n aria-multiselectable=\"${options.selection === 'multi'}\"\n aria-readonly=\"true\"\n aria-rowcount=\"-1\"\n tabindex=\"0\"\n @focus=\"${this.handleFocus}\"\n @click=\"${clickListener}\" \n @keydown=\"${this.handleKeyDown}\"\n >\n ${this.renderHeader()}\n <ui-divider></ui-divider>\n ${this.renderBody()}\n </div>\n `;\n }\n\n protected rowFromEvent(e: Event): HTMLElement | undefined {\n const path = e.composedPath();\n const row = path.find(current => {\n const element = current as Element;\n if (element.classList && element.classList.contains('data-table-row')) {\n return true;\n }\n return false;\n }) as HTMLElement | undefined;\n if (!row || !row.dataset.key) {\n return undefined;\n }\n return row;\n }\n\n protected tableFromEvent(e: Event): HTMLElement | undefined {\n const path = e.composedPath();\n const row = path.find((current) => {\n const element = current as Element;\n if (element.classList && element.classList.contains('data-table')) {\n return true;\n }\n return false;\n }) as HTMLElement | undefined;\n return row;\n }\n\n protected cellPositionFromEvent(e: Event): CellPosition {\n const result: CellPosition = {\n cell: 0,\n row: 0,\n };\n let row: HTMLElement | undefined;\n let column: HTMLElement | undefined;\n let table: HTMLElement | undefined;\n const path = e.composedPath();\n for (const current of path.values()) {\n const element = current as HTMLElement;\n if (element.classList && element.classList.contains('data-table-row')) {\n row = element;\n } else if (element.classList && element.classList.contains('data-table-cell')) {\n column = element;\n } else if (element.classList && element.classList.contains('data-table')) {\n table = element;\n break;\n }\n }\n if (!table) {\n return result;\n }\n if (row) {\n const rows = Array.from(table.querySelectorAll(`.data-table-row`));\n const rowIndex = rows.indexOf(row);\n if (rowIndex >= 0) {\n result.row = rowIndex;\n }\n if (column) {\n const columns = Array.from(row.querySelectorAll(`.data-table-cell`));\n const cellIndex = columns.indexOf(column);\n if (cellIndex >= 0) {\n result.cell = cellIndex;\n }\n }\n }\n return result;\n }\n\n protected cellRowFromEvent(e: Event): { column: HTMLElement, row: HTMLElement } | undefined {\n let row: HTMLElement | undefined;\n let column: HTMLElement | undefined;\n const path = e.composedPath();\n for (const current of path.values()) {\n const element = current as HTMLElement;\n if (element.classList && element.classList.contains('data-table-row')) {\n row = element;\n break;\n } else if (element.classList && element.classList.contains('data-table-cell')) {\n column = element;\n }\n }\n if (!row || !column) {\n return undefined;\n }\n return { row, column }\n }\n\n protected handleFocus(e: Event): void {\n const target = e.target as HTMLElement;\n if (target.classList.contains('data-table')) {\n // focusing on the table, move the focus to the first cell\n this.focusFirstCell(target);\n }\n }\n\n protected dblclickHandler(e: Event): void {\n const callback = this.#listeners.activate as (item: T) => void;\n if (!callback) {\n return;\n }\n const row = this.rowFromEvent(e)\n if (!row) {\n return;\n }\n const { key } = row.dataset;\n const keyProperty = this.options.key || 'key';\n const item = this.#renderItems?.find(i => (i as unknown as {[key: string]: unknown})[keyProperty] === key);\n if (!item) {\n return;\n }\n callback(item);\n }\n\n protected handleClick(e: Event): void {\n const { selection } = this.options;\n const row = this.rowFromEvent(e)\n if (!row) {\n return;\n }\n if (selection === 'single') {\n this.handleSingleSelection(row.dataset.key as string);\n } else if (selection === 'multi') {\n this.handleMultiSelection(row.dataset.key as string);\n }\n const table = this.tableFromEvent(e) as HTMLElement;\n this.focused = this.cellPositionFromEvent(e);\n this.focusCell(table, this.focused.row, this.focused.cell);\n }\n\n protected handleKeyDown(e: KeyboardEvent): void {\n if (e.defaultPrevented) {\n return;\n }\n if (['Space', 'Enter'].includes(e.code)) {\n this.handlePrimaryAction(e);\n } else if (e.code === 'ArrowRight') {\n this.moveFocusRight(e);\n } else if (e.code === 'ArrowDown') {\n this.moveFocusDown(e);\n } else if (e.code === 'ArrowUp') {\n this.moveFocusUp(e);\n } else if (e.code === 'ArrowLeft') {\n this.moveFocusLeft(e);\n }\n }\n\n protected handleSingleSelection(key: string): void {\n if (this.selected.includes(key)) {\n return;\n }\n this.selected = [key];\n this.dispatchRender();\n this.dispatchSelected(key);\n }\n\n protected handleMultiSelection(key: string): void {\n const { selected } = this;\n if (selected.includes(key)) {\n const index = selected.indexOf(key);\n selected.splice(index, 1);\n } else {\n selected.push(key);\n }\n this.dispatchRender();\n this.dispatchSelected(selected);\n }\n\n protected focusFirstCell(table: HTMLElement): void {\n const cell = table.querySelector('[role=\"columnheader\"]') as HTMLElement | null;\n if (!cell) {\n return;\n }\n cell.setAttribute('tabindex', '0');\n cell.focus();\n table.removeAttribute('tabindex');\n this.focused = { cell: 0, row: 0 };\n }\n\n protected focusCell(table: HTMLElement, rowIndex: number, colIndex: number): boolean {\n const row = table.querySelectorAll('[role=\"row\"]')[rowIndex];\n if (!row) {\n return false;\n }\n const cell = row.querySelectorAll(`.data-table-cell`)[colIndex] as HTMLElement | null;\n if (!cell) {\n return false;\n }\n const current = table.querySelector(`.data-table-cell[tabindex]`);\n cell.setAttribute('tabindex', '0');\n cell.focus();\n if (current) {\n current.removeAttribute('tabindex');\n } \n if (table.hasAttribute('tabindex')) {\n table.removeAttribute('tabindex');\n }\n return true;\n }\n\n protected moveFocusRight(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row, focused.cell + 1)) {\n focused.cell += 1;\n }\n }\n\n protected moveFocusLeft(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row, focused.cell - 1)) {\n focused.cell -= 1;\n }\n }\n\n protected moveFocusDown(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row + 1, focused.cell)) {\n focused.row += 1;\n }\n }\n\n protected moveFocusUp(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row - 1, focused.cell)) {\n focused.row -= 1;\n }\n }\n\n protected handlePrimaryAction(e: Event): void {\n e.preventDefault();\n const info = this.cellRowFromEvent(e);\n if (!info) {\n return;\n }\n const { row, column } = info;\n // first check if the cell has an focusable element. If so trigger action on it.\n const focusable = column.querySelector('[tabindex=\"0\"]') as HTMLElement | null;\n if (focusable) {\n focusable.click();\n return;\n }\n const { selection } = this.options;\n if (selection === 'single') {\n this.handleSingleSelection(row.dataset.key as string);\n } else if (selection === 'multi') {\n this.handleMultiSelection(row.dataset.key as string);\n }\n }\n\n protected renderHeader(): TemplateResult {\n const cells = this.dispatchHeader();\n return html`\n <div role=\"rowgroup\">\n <div role=\"row\" class=\"data-table-row data-table-header\">\n ${cells}\n </div>\n </div>\n `;\n }\n\n protected renderBody(): TemplateResult {\n const { active = false } = this.options;\n const items = this.#renderItems;\n const contents = !!items && !!items.length ? items.map(item => this.renderItem(item)) : this.renderEmpty();\n const dbListener = active ? this.dblclickHandler : undefined;\n return html`\n <div class=\"data-table-body\" role=\"rowgroup\" @dblclick=\"${dbListener}\">\n ${contents}\n </div>`;\n }\n\n protected renderItem(item: T): TemplateResult {\n const cells = this.dispatchItem(item);\n const { selected, options } = this;\n const typed = item as unknown as Record<string, string>;\n const key = typed[options.key || 'key'];\n let isSelected = false;\n if (options.selection === 'single') {\n const [selectedKey] = selected;\n if (selectedKey === key) {\n isSelected = true;\n }\n } else if (options.selection === 'multi') {\n isSelected = selected.includes(key);\n }\n const classes: ClassInfo = {\n 'data-table-row': true,\n selected: isSelected,\n };\n return html`\n <div role=\"row\" class=\"${classMap(classes)}\" data-key=\"${key}\" aria-selected=\"${isSelected ? 'true' : 'false'}\">\n <div class=\"data-table-row-body\" role=\"presentation\">\n ${cells}\n </div>\n </div>\n `;\n }\n\n protected renderEmpty(): TemplateResult {\n const content = this.dispatchEmpty();\n return html`\n <div role=\"row\" class=\"data-table-row data-table-empty-row\">\n <div role=\"cell\">\n ${content}\n </div>\n </div>\n `;\n }\n\n protected dispatchHeader(): TemplateResult[] | undefined {\n const callback = this.#listeners.header as () => TemplateResult[] | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult[] | undefined;\n try {\n content = callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchItem(item: T): TemplateResult[] | undefined {\n const callback = this.#listeners.item as CellCallback<T> | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult[] | undefined;\n try {\n content = callback(item);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchEmpty(): TemplateResult | undefined {\n const callback = this.#listeners.empty as () => TemplateResult | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult | undefined;\n try {\n content = callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchRender(): void {\n const callback = this.#listeners.render as () => void;\n if (!callback) {\n return;\n }\n try {\n callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n }\n\n protected dispatchSelected(selection: string | string[]): void {\n const callback = this.#listeners.select as SelectCallback;\n if (!callback) {\n return;\n }\n try {\n callback(selection);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../../src/ui/table/DataTable.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, CSSResult, html, TemplateResult } from \"lit\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { ClassInfo, classMap } from \"lit/directives/class-map.js\";\nimport { dataAttr } from \"../../directives/data-attr.js\";\nimport '../../define/ui/ui-divider.js';\n\nexport interface IDataTableOptions {\n /**\n * The name of the property that identifies the key. The key is inserted into each row as `data-key`.\n * Default to `key`.\n */\n key?: string;\n /**\n * The value of the aria-label to render on the table.\n */\n ariaLabel?: string;\n\n /**\n * When true it dispatches `activate` event when the user double click on a row.\n */\n active?: boolean;\n /**\n * When set it allows a single selection. A list item is highlighted and the `select` event is dispatched when the selection change.\n */\n selection?: 'single' | 'multi';\n}\n\nexport type RenderContent = string | TemplateResult | TemplateResult[];\n\ntype DataEvents = 'header' | 'item' | 'empty' | 'activate' | 'select' | 'render' | 'scrollend';\n\ntype CellCallback<T> = (item: T) => TemplateResult[];\ntype ActivateCallback<T> = (item: T) => void;\ntype SelectCallback = (item: string | string[]) => void;\ntype Callback = () => void;\n\ntype DataEventsMap<T> = {\n [key in DataEvents]?: Callback | SelectCallback | CellCallback<T> | CellCallback<T[]> | ActivateCallback<T> | ActivateCallback<T[]> | {(): TemplateResult | TemplateResult[]};\n};\n\nexport interface ICellOptions {\n /**\n * The list of CSS class names to add to the cell.\n */\n class?: string;\n\n /**\n * The list of data attributes to set on the cell.\n */\n data?: { [key: string]: number | string | boolean };\n /**\n * The value of the aria-label to render on the cell.\n */\n ariaLabel?: string;\n}\n\ninterface CellPosition { \n row: number; \n cell: number; \n}\n\n/**\n * A helper class that allows to build a data table in a programmatic way.\n * \n * Usage:\n * \n * const dt = new DataTable(arrayOfItems, { key: 'key' });\n * // or dt.items = arrayOfItems;\n * dt.addEventListener('header', () => { \n * const c1 = dt.header('name', { class: 'name-column', data: {a: b} });\n * const c2 = dt.header('created', { class: 'created-column', data: {a: b} });\n * return [c1, c2];\n * });\n * dt.addEventListener('item', (item) => { \n * const c1 = dt.cell(html`cell template content`, { class: 'a b c', data: {a: b} });\n * const c2 = dt.cell(`cell text content`, { class: 'xyz', data: {key: 'value'} });\n * return [c1, c2];\n * });\n * dt.addEventListener('empty', () => { \n * return html`<p>The table has no records.</p>`;\n * });\n * \n * const template = dt.render();\n * \n * @fires header - An event dispatched when a table header row is being rendered.\n * @fires item - An event dispatched when a table item row is being rendered.\n * @fires empty - An event dispatched when a table has no rows to render.\n * @fires activate - An event dispatched when the user double click on a row.\n * @fires select - An event dispatched when the user selected a table item in a single or multi selection table.\n * @fires render - An event dispatched when the internal state changed and the table must be rendered again.\n */\nexport class DataTable<T> {\n static get styles(): CSSResult {\n return css`\n .data-table {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .data-table-body {\n flex: 1;\n overflow: auto;\n }\n\n .data-table-row {\n height: 44px;\n position: relative;\n\n display: flex;\n align-items: center;\n\n font-family: var(--md-sys-typescale-body-medium-font-family-name);\n font-style: var(--md-sys-typescale-body-medium-font-family-style);\n font-weight: var(--md-sys-typescale-body-medium-font-weight);\n font-size: var(--md-sys-typescale-body-medium-font-size);\n letter-spacing: var(--md-sys-typescale-body-medium-tracking);\n line-height: var(--md-sys-typescale-body-medium-height);\n text-transform: var(--md-sys-typescale-body-medium-text-transform);\n text-decoration: var(--md-sys-typescale-body-medium-text-decoration);\n }\n\n .data-table-row-body {\n height: inherit;\n display: flex;\n align-items: center;\n flex: 1;\n }\n\n .data-table-body .data-table-row:not(.data-table-empty-row):hover::before {\n content: '';\n background-color: var(--md-sys-color-on-surface);\n opacity: var(--md-sys-state-hover-state-layer-opacity);\n position: absolute;\n inset: 0;\n z-index: -1;\n }\n\n .data-table-header {\n font-family: var(--md-sys-typescale-label-large-font-family-name);\n font-style: var(--md-sys-typescale-label-large-font-family-style);\n font-weight: var(--md-sys-typescale-label-large-font-weight);\n font-size: var(--md-sys-typescale-label-large-font-size);\n letter-spacing: var(--md-sys-typescale-label-large-tracking);\n line-height: var(--md-sys-typescale-label-large-height);\n text-transform: var(--md-sys-typescale-label-large-text-transform);\n text-decoration: var(--md-sys-typescale-label-large-text-decoration);\n }\n\n .data-table-cell {\n display: flex;\n align-items: center;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n height: inherit;\n padding: 12px;\n box-sizing: border-box;\n position: relative;\n }\n\n .data-table-row.data-table-empty-row {\n height: auto;\n display: block;\n }\n\n .data-table-row.data-table-empty-row > [role=cell] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n }\n\n .selected {\n background-color: var(--md-sys-color-secondary-container);\n border-radius: 8px;\n }\n\n .data-table-cell:focus-visible::before {\n content: '';\n background-color: var(--md-sys-color-on-surface);\n opacity: var(--md-sys-state-focus-state-layer-opacity);\n position: absolute;\n inset: 0;\n z-index: -1;\n }\n `;\n }\n\n #renderItems?: T[];\n\n get items(): ArrayLike<T> | undefined {\n return this.#renderItems;\n }\n\n set items(value: ArrayLike<T> | undefined) {\n if (!value) {\n this.#renderItems = undefined;\n return;\n }\n const arr = Array.from(value);\n this.#renderItems = arr;\n }\n\n options: IDataTableOptions;\n \n #listeners: DataEventsMap<T> = {};\n\n #getItems: () => ArrayLike<T>;\n\n /**\n * The list of keys that correspond to the `key` set on the options of items that are currently selected.\n * Note, this is a common list for single and multi selection. In a single selection only the first is taken into account.\n */\n selected: string[] = [];\n\n /**\n * Describes currently focused cell.\n * The `row` is the index of the focused row (starting with the header) and the `cell` is the index of the focused cell.\n */\n protected focused?: CellPosition;\n\n constructor(itemsCallback: () => ArrayLike<T>, options: IDataTableOptions = {}) {\n this.options = options;\n this.#getItems = itemsCallback;\n this.dblclickHandler = this.dblclickHandler.bind(this);\n this.handleClick = this.handleClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleFocus = this.handleFocus.bind(this);\n this.handleListScroll = this.handleListScroll.bind(this);\n }\n\n addEventListener(type: 'header', listener: () => TemplateResult[]): void;\n\n addEventListener(type: 'render', listener: () => void): void;\n\n addEventListener(type: 'item', listener: CellCallback<T>): void;\n\n addEventListener(type: 'empty', listener: () => TemplateResult): void;\n\n addEventListener(type: 'activate', listener: ActivateCallback<T>): void;\n\n addEventListener(type: 'select', listener: SelectCallback): void;\n\n addEventListener(type: 'scrollend', listener: Callback): void;\n\n addEventListener(type: DataEvents, listener: SelectCallback | CellCallback<T> | CellCallback<T[]> | ActivateCallback<T> | ActivateCallback<T[]> | {(): TemplateResult | TemplateResult[]}): void {\n this.#listeners[type] = listener;\n }\n\n /**\n * Renders a header cell.\n * \n * @param content The content of the header cell to render.\n * @param options Cell rendering options\n */\n header(content: RenderContent, options: ICellOptions = {}): TemplateResult {\n const data = options.data || {};\n return html`<span \n role=\"columnheader\" \n class=\"data-table-cell data-table-header-cell ${options.class || ''}\"\n aria-label=\"${ifDefined(options.ariaLabel)}\"\n ${dataAttr(data)}\n >${content}</span>`;\n }\n\n /**\n * Renders a body cell.\n * \n * @param content The content of the header cell to render.\n * @param options Cell rendering options\n */\n cell(content: RenderContent, options: ICellOptions = {}): TemplateResult {\n const data = options.data || {};\n return html`\n <span \n role=\"gridcell\" \n class=\"data-table-cell data-table-body-cell ${options.class || ''}\"\n ${dataAttr(data)}\n >${content}</span>\n `;\n }\n\n render(): TemplateResult {\n this.items = this.#getItems();\n const { options } = this;\n const clickListener = options.selection ? this.handleClick : undefined;\n return html`\n <div \n class=\"data-table\" \n role=\"grid\" \n aria-label=\"${ifDefined(options.ariaLabel)}\"\n aria-multiselectable=\"${options.selection === 'multi'}\"\n aria-readonly=\"true\"\n aria-rowcount=\"-1\"\n tabindex=\"0\"\n @focus=\"${this.handleFocus}\"\n @click=\"${clickListener}\" \n @keydown=\"${this.handleKeyDown}\"\n >\n ${this.renderHeader()}\n <ui-divider></ui-divider>\n ${this.renderBody()}\n </div>\n `;\n }\n\n protected rowFromEvent(e: Event): HTMLElement | undefined {\n const path = e.composedPath();\n const row = path.find(current => {\n const element = current as Element;\n if (element.classList && element.classList.contains('data-table-row')) {\n return true;\n }\n return false;\n }) as HTMLElement | undefined;\n if (!row || !row.dataset.key) {\n return undefined;\n }\n return row;\n }\n\n protected tableFromEvent(e: Event): HTMLElement | undefined {\n const path = e.composedPath();\n const row = path.find((current) => {\n const element = current as Element;\n if (element.classList && element.classList.contains('data-table')) {\n return true;\n }\n return false;\n }) as HTMLElement | undefined;\n return row;\n }\n\n protected cellPositionFromEvent(e: Event): CellPosition {\n const result: CellPosition = {\n cell: 0,\n row: 0,\n };\n let row: HTMLElement | undefined;\n let column: HTMLElement | undefined;\n let table: HTMLElement | undefined;\n const path = e.composedPath();\n for (const current of path.values()) {\n const element = current as HTMLElement;\n if (element.classList && element.classList.contains('data-table-row')) {\n row = element;\n } else if (element.classList && element.classList.contains('data-table-cell')) {\n column = element;\n } else if (element.classList && element.classList.contains('data-table')) {\n table = element;\n break;\n }\n }\n if (!table) {\n return result;\n }\n if (row) {\n const rows = Array.from(table.querySelectorAll(`.data-table-row`));\n const rowIndex = rows.indexOf(row);\n if (rowIndex >= 0) {\n result.row = rowIndex;\n }\n if (column) {\n const columns = Array.from(row.querySelectorAll(`.data-table-cell`));\n const cellIndex = columns.indexOf(column);\n if (cellIndex >= 0) {\n result.cell = cellIndex;\n }\n }\n }\n return result;\n }\n\n protected cellRowFromEvent(e: Event): { column: HTMLElement, row: HTMLElement } | undefined {\n let row: HTMLElement | undefined;\n let column: HTMLElement | undefined;\n const path = e.composedPath();\n for (const current of path.values()) {\n const element = current as HTMLElement;\n if (element.classList && element.classList.contains('data-table-row')) {\n row = element;\n break;\n } else if (element.classList && element.classList.contains('data-table-cell')) {\n column = element;\n }\n }\n if (!row || !column) {\n return undefined;\n }\n return { row, column }\n }\n\n protected handleFocus(e: Event): void {\n const target = e.target as HTMLElement;\n if (target.classList.contains('data-table')) {\n // focusing on the table, move the focus to the first cell\n this.focusFirstCell(target);\n }\n }\n\n protected dblclickHandler(e: Event): void {\n const callback = this.#listeners.activate as (item: T) => void;\n if (!callback) {\n return;\n }\n const row = this.rowFromEvent(e)\n if (!row) {\n return;\n }\n const { key } = row.dataset;\n const keyProperty = this.options.key || 'key';\n const item = this.#renderItems?.find(i => (i as unknown as {[key: string]: unknown})[keyProperty] === key);\n if (!item) {\n return;\n }\n callback(item);\n }\n\n protected handleClick(e: Event): void {\n const { selection } = this.options;\n const row = this.rowFromEvent(e)\n if (!row) {\n return;\n }\n if (selection === 'single') {\n this.handleSingleSelection(row.dataset.key as string);\n } else if (selection === 'multi') {\n this.handleMultiSelection(row.dataset.key as string);\n }\n const table = this.tableFromEvent(e) as HTMLElement;\n this.focused = this.cellPositionFromEvent(e);\n this.focusCell(table, this.focused.row, this.focused.cell);\n }\n\n protected handleKeyDown(e: KeyboardEvent): void {\n if (e.defaultPrevented) {\n return;\n }\n if (['Space', 'Enter'].includes(e.code)) {\n this.handlePrimaryAction(e);\n } else if (e.code === 'ArrowRight') {\n this.moveFocusRight(e);\n } else if (e.code === 'ArrowDown') {\n this.moveFocusDown(e);\n } else if (e.code === 'ArrowUp') {\n this.moveFocusUp(e);\n } else if (e.code === 'ArrowLeft') {\n this.moveFocusLeft(e);\n }\n }\n\n protected handleSingleSelection(key: string): void {\n if (this.selected.includes(key)) {\n return;\n }\n this.selected = [key];\n this.dispatchRender();\n this.dispatchSelected(key);\n }\n\n protected handleMultiSelection(key: string): void {\n const { selected } = this;\n if (selected.includes(key)) {\n const index = selected.indexOf(key);\n selected.splice(index, 1);\n } else {\n selected.push(key);\n }\n this.dispatchRender();\n this.dispatchSelected(selected);\n }\n\n protected focusFirstCell(table: HTMLElement): void {\n const cell = table.querySelector('[role=\"columnheader\"]') as HTMLElement | null;\n if (!cell) {\n return;\n }\n cell.setAttribute('tabindex', '0');\n cell.focus();\n table.removeAttribute('tabindex');\n this.focused = { cell: 0, row: 0 };\n }\n\n protected focusCell(table: HTMLElement, rowIndex: number, colIndex: number): boolean {\n const row = table.querySelectorAll('[role=\"row\"]')[rowIndex];\n if (!row) {\n return false;\n }\n const cell = row.querySelectorAll(`.data-table-cell`)[colIndex] as HTMLElement | null;\n if (!cell) {\n return false;\n }\n const current = table.querySelector(`.data-table-cell[tabindex]`);\n cell.setAttribute('tabindex', '0');\n cell.focus();\n if (current) {\n current.removeAttribute('tabindex');\n } \n if (table.hasAttribute('tabindex')) {\n table.removeAttribute('tabindex');\n }\n return true;\n }\n\n protected moveFocusRight(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row, focused.cell + 1)) {\n focused.cell += 1;\n }\n }\n\n protected moveFocusLeft(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row, focused.cell - 1)) {\n focused.cell -= 1;\n }\n }\n\n protected moveFocusDown(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row + 1, focused.cell)) {\n focused.row += 1;\n }\n }\n\n protected moveFocusUp(e: Event): void {\n e.preventDefault();\n const table = this.tableFromEvent(e);\n if (!table) {\n return;\n }\n const { focused } = this;\n if (!focused) {\n this.focusFirstCell(table);\n return;\n }\n if (this.focusCell(table, focused.row - 1, focused.cell)) {\n focused.row -= 1;\n }\n }\n\n protected handlePrimaryAction(e: Event): void {\n e.preventDefault();\n const info = this.cellRowFromEvent(e);\n if (!info) {\n return;\n }\n const { row, column } = info;\n // first check if the cell has an focusable element. If so trigger action on it.\n const focusable = column.querySelector('[tabindex=\"0\"]') as HTMLElement | null;\n if (focusable) {\n focusable.click();\n return;\n }\n const { selection } = this.options;\n if (selection === 'single') {\n this.handleSingleSelection(row.dataset.key as string);\n } else if (selection === 'multi') {\n this.handleMultiSelection(row.dataset.key as string);\n }\n }\n\n protected handleListScroll(e: Event): void {\n const list = e.target as HTMLElement;\n const { scrollTop, offsetHeight, scrollHeight } = list;\n const bottom = scrollTop + offsetHeight >= scrollHeight - 20; // 20 is the offset which qualifies as the end. An arbitrary number.\n if (bottom) {\n this.dispatchScrollEnd();\n }\n }\n\n protected renderHeader(): TemplateResult {\n const cells = this.dispatchHeader();\n return html`\n <div role=\"rowgroup\">\n <div role=\"row\" class=\"data-table-row data-table-header\">\n ${cells}\n </div>\n </div>\n `;\n }\n\n protected renderBody(): TemplateResult {\n const { active = false } = this.options;\n const items = this.#renderItems;\n const contents = !!items && !!items.length ? items.map(item => this.renderItem(item)) : this.renderEmpty();\n const dbListener = active ? this.dblclickHandler : undefined;\n return html`\n <div class=\"data-table-body\" role=\"rowgroup\" @dblclick=\"${dbListener}\" @scroll=\"${{ handleEvent: this.handleListScroll, passive: true }}\">\n ${contents}\n </div>`;\n }\n\n protected renderItem(item: T): TemplateResult {\n const cells = this.dispatchItem(item);\n const { selected, options } = this;\n const typed = item as unknown as Record<string, string>;\n const key = typed[options.key || 'key'];\n let isSelected = false;\n if (options.selection === 'single') {\n const [selectedKey] = selected;\n if (selectedKey === key) {\n isSelected = true;\n }\n } else if (options.selection === 'multi') {\n isSelected = selected.includes(key);\n }\n const classes: ClassInfo = {\n 'data-table-row': true,\n selected: isSelected,\n };\n return html`\n <div role=\"row\" class=\"${classMap(classes)}\" data-key=\"${key}\" aria-selected=\"${isSelected ? 'true' : 'false'}\">\n <div class=\"data-table-row-body\" role=\"presentation\">\n ${cells}\n </div>\n </div>\n `;\n }\n\n protected renderEmpty(): TemplateResult {\n const content = this.dispatchEmpty();\n return html`\n <div role=\"row\" class=\"data-table-row data-table-empty-row\">\n <div role=\"cell\">\n ${content}\n </div>\n </div>\n `;\n }\n\n protected dispatchHeader(): TemplateResult[] | undefined {\n const callback = this.#listeners.header as () => TemplateResult[] | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult[] | undefined;\n try {\n content = callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchItem(item: T): TemplateResult[] | undefined {\n const callback = this.#listeners.item as CellCallback<T> | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult[] | undefined;\n try {\n content = callback(item);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchEmpty(): TemplateResult | undefined {\n const callback = this.#listeners.empty as () => TemplateResult | undefined;\n if (!callback) {\n return undefined;\n }\n let content: TemplateResult | undefined;\n try {\n content = callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n return content;\n }\n\n protected dispatchRender(): void {\n const callback = this.#listeners.render as () => void;\n if (!callback) {\n return;\n }\n try {\n callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n }\n\n protected dispatchSelected(selection: string | string[]): void {\n const callback = this.#listeners.select as SelectCallback;\n if (!callback) {\n return;\n }\n try {\n callback(selection);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n }\n\n protected dispatchScrollEnd(): void {\n const callback = this.#listeners.scrollend as Callback;\n if (!callback) {\n return;\n }\n try {\n callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(e);\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -129,11 +129,17 @@ export abstract class StoreBindings extends PlatformBindings {
|
|
|
129
129
|
|
|
130
130
|
certificatesChannel = new BroadcastChannel(StoreBroadcast.certificates);
|
|
131
131
|
|
|
132
|
+
initialized = false;
|
|
133
|
+
|
|
132
134
|
async initializeStore(): Promise<void> {
|
|
133
135
|
// ...
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
async initialize(): Promise<void> {
|
|
139
|
+
if (this.initialized) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.initialized = true;
|
|
137
143
|
const target = document.body;
|
|
138
144
|
|
|
139
145
|
window.addEventListener(EventTypes.Store.initEnvironment, this.handleInitializeEnvironment.bind(this));
|
|
@@ -156,6 +162,7 @@ export abstract class StoreBindings extends PlatformBindings {
|
|
|
156
162
|
window.addEventListener(EventTypes.Store.File.delete, this.handleFileDelete.bind(this) as EventListener);
|
|
157
163
|
window.addEventListener(EventTypes.Store.File.patchUsers, this.handleFilePatchUser.bind(this) as EventListener);
|
|
158
164
|
window.addEventListener(EventTypes.Store.File.listUsers, this.handleListFileUsers.bind(this) as EventListener);
|
|
165
|
+
window.addEventListener(EventTypes.Store.File.breadcrumbs, this.handleFileBreadcrumbs.bind(this) as EventListener);
|
|
159
166
|
|
|
160
167
|
// User
|
|
161
168
|
window.addEventListener(EventTypes.Store.User.me, this.handlerMe.bind(this));
|
|
@@ -372,6 +379,11 @@ export abstract class StoreBindings extends PlatformBindings {
|
|
|
372
379
|
event.detail.result = this.getStore().sdk.file.listUsers(this.space, event.detail.key);
|
|
373
380
|
}
|
|
374
381
|
|
|
382
|
+
protected handleFileBreadcrumbs(event: CustomEvent<{ key: string, result: Promise<ContextListResult<FileBreadcrumb>> }>): void {
|
|
383
|
+
event.preventDefault();
|
|
384
|
+
event.detail.result = this.files.breadcrumbs(event.detail.key)
|
|
385
|
+
// this.getStore().sdk.file.breadcrumbs(this.space, event.detail.key);
|
|
386
|
+
}
|
|
375
387
|
|
|
376
388
|
protected handlerMe(input: Event): void {
|
|
377
389
|
const e = input as CustomEvent<{ result: Promise<IUser> }>;
|
|
@@ -822,10 +834,13 @@ export abstract class StoreBindings extends PlatformBindings {
|
|
|
822
834
|
protected storeEventHandler(e: MessageEvent): void {
|
|
823
835
|
const event = JSON.parse(e.data) as BroadcastEvent | BackendErrorEvent;
|
|
824
836
|
if (event.type === 'error') {
|
|
825
|
-
// TODO: Report an error somehow
|
|
826
837
|
throw new Error(event.cause);
|
|
827
838
|
}
|
|
828
839
|
if (event.space && event.space !== this.space) {
|
|
840
|
+
// we allow files here to support shared files.
|
|
841
|
+
if (event.path === RouteBuilder.files()) {
|
|
842
|
+
this.filesChannel.postMessage(event);
|
|
843
|
+
}
|
|
829
844
|
return;
|
|
830
845
|
}
|
|
831
846
|
if (event.path === RouteBuilder.spaces()) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { customElement } from "lit/decorators.js";
|
|
2
|
+
import Element from "../../elements/store/FilePicker.element.js";
|
|
3
|
+
|
|
4
|
+
@customElement('file-picker')
|
|
5
|
+
export class FilePickerElement extends Element {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
'file-picker': Element;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { customElement } from 'lit/decorators.js';
|
|
2
|
-
import Element from "../../elements/
|
|
3
|
-
import styles from "../../elements/
|
|
2
|
+
import Element from "../../elements/store/ShareFile.element.js";
|
|
3
|
+
import styles from "../../elements/store/ShareFile.styles.js";
|
|
4
4
|
import dialogStyles from '../../ui/dialog/UiDialog.styles.js';
|
|
5
5
|
|
|
6
6
|
@customElement('share-file')
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FolderKind, IFile,
|
|
3
|
+
ListFileKind
|
|
4
|
+
} from "@api-client/core/build/browser.js";
|
|
5
|
+
import { CSSResult, html, nothing, TemplateResult } from "lit";
|
|
6
|
+
import { eventOptions, property, query, state } from "lit/decorators.js";
|
|
7
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
8
|
+
import ApiElement from "../ApiElement.js";
|
|
9
|
+
import styles from './FilePicker.styles.js';
|
|
10
|
+
import { fileIcon } from "./FilesLib.js";
|
|
11
|
+
import type UiList from "../../ui/list/UiList.js";
|
|
12
|
+
import type { UiListSelection } from "../../ui/list/UiList.js";
|
|
13
|
+
import { FileSystem } from "../../store/FileSystem.js";
|
|
14
|
+
import '../../define/ui/ui-divider.js';
|
|
15
|
+
import '../../define/ui/ui-button.js';
|
|
16
|
+
import '../../define/ui/ui-icon-button.js';
|
|
17
|
+
import '../../define/ui/ui-icon.js';
|
|
18
|
+
import '../../define/ui/ui-list.js';
|
|
19
|
+
import '../../define/ui/ui-list-item.js';
|
|
20
|
+
import '../../define/ui/ui-progress.js';
|
|
21
|
+
|
|
22
|
+
export interface FilePickerClosingReason {
|
|
23
|
+
/**
|
|
24
|
+
* Whether the picker was canceled.
|
|
25
|
+
*/
|
|
26
|
+
canceled: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The file selected by the user. This is always and only selected when the `canceled` is false.
|
|
29
|
+
*/
|
|
30
|
+
file?: IFile;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A portable element that allow to pick a file from the Store.
|
|
35
|
+
*
|
|
36
|
+
* @fires close - When a file is selected or the user cancelled the dialog. The detail object is the picked file object. Note, this event bubbles.
|
|
37
|
+
* @fires querycomplete - When the page of results was loaded.
|
|
38
|
+
*/
|
|
39
|
+
export default class FilePicker extends ApiElement {
|
|
40
|
+
static override get styles(): CSSResult[] {
|
|
41
|
+
return styles;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The key of the parent folder to query for files.
|
|
46
|
+
* @attribute
|
|
47
|
+
*/
|
|
48
|
+
@property({ type: String, hasChanged: () => false })
|
|
49
|
+
get folder(): string | undefined {
|
|
50
|
+
return this.fs.parent;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
set folder(value: string | undefined) {
|
|
54
|
+
this.fs.selectFolder(value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The page limit. Defaults to the store defaults.
|
|
59
|
+
* @attribute
|
|
60
|
+
*/
|
|
61
|
+
@property({ type: Number, hasChanged: () => false })
|
|
62
|
+
set limit(value: number | undefined) {
|
|
63
|
+
this.fs.limit = value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get limit(): number | undefined {
|
|
67
|
+
return this.fs.limit;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The timeout for the page query debouncer.
|
|
72
|
+
* @attribute
|
|
73
|
+
*/
|
|
74
|
+
@property({ type: Number, hasChanged: () => false })
|
|
75
|
+
get debounceTimeout(): number {
|
|
76
|
+
return this.fs.debounceTimeout;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set debounceTimeout(value: number) {
|
|
80
|
+
this.fs.debounceTimeout = value || 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The list of file kinds to list.
|
|
85
|
+
* Folders are always included.
|
|
86
|
+
*/
|
|
87
|
+
@property({ type: Array, hasChanged: () => false })
|
|
88
|
+
get kinds(): ListFileKind[] | undefined {
|
|
89
|
+
return this.fs.kinds;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
set kinds(value: ListFileKind[] | undefined) {
|
|
93
|
+
this.fs.kinds = value;
|
|
94
|
+
this.fs.resetList();
|
|
95
|
+
this.fs.debounceQuery();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@query('ui-list') protected list?: UiList;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The currently selected in the picker file.
|
|
102
|
+
*/
|
|
103
|
+
@state() protected selectedFile?: IFile;
|
|
104
|
+
|
|
105
|
+
@state() errorMessage?: string;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* When set it does not query for files when attached to the DOM.
|
|
109
|
+
* It will still query for files when attributes change. This is primarily used in tests.
|
|
110
|
+
* @attribute
|
|
111
|
+
*/
|
|
112
|
+
@property({ type: Boolean }) manualQuery?: boolean;
|
|
113
|
+
|
|
114
|
+
get selectedKey(): string | undefined {
|
|
115
|
+
return this.selectedFile?.key;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fs = new FileSystem();
|
|
119
|
+
|
|
120
|
+
constructor() {
|
|
121
|
+
super();
|
|
122
|
+
this.fs.eventsTarget = this;
|
|
123
|
+
this.fs.addEventListener('change', () => this.requestUpdate());
|
|
124
|
+
this.fs.addEventListener('error', (e: Event) => {
|
|
125
|
+
const event = e as CustomEvent<string>;
|
|
126
|
+
this.errorMessage = event.detail;
|
|
127
|
+
});
|
|
128
|
+
this.fs.addEventListener('querycomplete', () => {
|
|
129
|
+
this.dispatchEvent(new Event('querycomplete'));
|
|
130
|
+
});
|
|
131
|
+
this.fs.addEventListener('delete', (e: Event) => {
|
|
132
|
+
const event = e as CustomEvent<string>;
|
|
133
|
+
if (this.selectedFile && this.selectedFile.key === event.detail) {
|
|
134
|
+
this.selectedFile = undefined;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
override connectedCallback(): void {
|
|
140
|
+
super.connectedCallback();
|
|
141
|
+
this.fs.observe();
|
|
142
|
+
if (!this.manualQuery) {
|
|
143
|
+
this.fs.debounceQuery();
|
|
144
|
+
}
|
|
145
|
+
if (!this.hasAttribute('tabindex')) {
|
|
146
|
+
this.setAttribute('tabindex', '0');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
override disconnectedCallback(): void {
|
|
151
|
+
super.disconnectedCallback();
|
|
152
|
+
this.fs.unobserve();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
override focus(options?: FocusOptions | undefined): void {
|
|
156
|
+
const { list } = this;
|
|
157
|
+
if (list) {
|
|
158
|
+
list.focus(options);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
protected handleFileSelect(e: CustomEvent<UiListSelection>): void {
|
|
163
|
+
// this prevents the dropdown list to close the UI.
|
|
164
|
+
e.preventDefault();
|
|
165
|
+
const file = this.fs.files[e.detail.index];
|
|
166
|
+
if (!file) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (file.kind === FolderKind) {
|
|
170
|
+
this.fs.selectFolder(file.key);
|
|
171
|
+
this.selectedFile = undefined;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this.selectedFile = file;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
protected handleParentUp(): void {
|
|
178
|
+
this.fs.parentUp();
|
|
179
|
+
this.selectedFile = undefined;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
protected notifyClose(canceled: boolean): void {
|
|
183
|
+
if (!canceled && !this.selectedFile) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const detail: FilePickerClosingReason = {
|
|
187
|
+
canceled,
|
|
188
|
+
};
|
|
189
|
+
if (!canceled) {
|
|
190
|
+
detail.file = this.selectedFile;
|
|
191
|
+
}
|
|
192
|
+
// this event bubbles so any dropdown on the way can close itself.
|
|
193
|
+
const e = new CustomEvent<FilePickerClosingReason>('close', {
|
|
194
|
+
bubbles: true,
|
|
195
|
+
cancelable: true,
|
|
196
|
+
composed: true,
|
|
197
|
+
detail,
|
|
198
|
+
});
|
|
199
|
+
this.dispatchEvent(e);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
protected handleSelect(): void {
|
|
203
|
+
this.notifyClose(false);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
protected handleCancel(): void {
|
|
207
|
+
this.notifyClose(true);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@eventOptions({ passive: true })
|
|
211
|
+
protected handleListScroll(e: Event): void {
|
|
212
|
+
const list = e.target as UiList;
|
|
213
|
+
if (this.fs.isListEnd(list)) {
|
|
214
|
+
this.fs.debounceQuery();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
protected override render(): TemplateResult {
|
|
219
|
+
return html`
|
|
220
|
+
<div class="content">
|
|
221
|
+
${this.renderHeader()}
|
|
222
|
+
<ui-divider></ui-divider>
|
|
223
|
+
${this.renderFiles()}
|
|
224
|
+
${this.errorMessage ? html`<p class="error">${this.errorMessage}</p>` : nothing}
|
|
225
|
+
<ui-divider></ui-divider>
|
|
226
|
+
${this.renderActions()}
|
|
227
|
+
</div>
|
|
228
|
+
`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
protected renderHeader(): TemplateResult {
|
|
232
|
+
const { breadcrumbs = [], reading } = this.fs;
|
|
233
|
+
let content: TemplateResult;
|
|
234
|
+
let withIcon = false;
|
|
235
|
+
if (!breadcrumbs.length) {
|
|
236
|
+
content = html`<span class="title-large label">My files</span>`;
|
|
237
|
+
} else {
|
|
238
|
+
withIcon = true;
|
|
239
|
+
const [parent] = breadcrumbs;
|
|
240
|
+
content = html`
|
|
241
|
+
<ui-icon-button aria-label="Open parent folder" @click="${this.handleParentUp}" class="back-button">
|
|
242
|
+
<ui-icon role="presentation" icon="arrowBack"></ui-icon>
|
|
243
|
+
</ui-icon-button>
|
|
244
|
+
<span class="title-large label">${parent.name}</span>
|
|
245
|
+
`;
|
|
246
|
+
}
|
|
247
|
+
const classes = {
|
|
248
|
+
header: true,
|
|
249
|
+
withIcon,
|
|
250
|
+
}
|
|
251
|
+
return html`
|
|
252
|
+
<div class="${classMap(classes)}">
|
|
253
|
+
${content}
|
|
254
|
+
${reading ? html`<ui-progress indeterminate class="progress"></ui-progress>` : nothing}
|
|
255
|
+
</div>
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected renderFiles(): TemplateResult {
|
|
260
|
+
const { files } = this.fs;
|
|
261
|
+
if (!files || !files.length) {
|
|
262
|
+
return this.renderEmptyList();
|
|
263
|
+
}
|
|
264
|
+
return html`
|
|
265
|
+
<ui-list class="list" role="menu" @select="${this.handleFileSelect}" selectActive @scroll="${this.handleListScroll}">
|
|
266
|
+
${files.map(item => this.renderFileItem(item))}
|
|
267
|
+
</ui-list>
|
|
268
|
+
`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
protected renderEmptyList(): TemplateResult {
|
|
272
|
+
return html`
|
|
273
|
+
<p class="no-files body-large">No files in this view.</p>
|
|
274
|
+
`;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
protected renderFileItem(item: IFile): TemplateResult {
|
|
278
|
+
const icon = fileIcon(item);
|
|
279
|
+
return html`
|
|
280
|
+
<ui-list-item role="menuitem" data-key="${item.key}" data-kind="${item.kind}">
|
|
281
|
+
${icon ? html`<ui-icon icon="${icon}" class="file-icon"></ui-icon>` : nothing}
|
|
282
|
+
${item.info.name || 'Unnamed file'}
|
|
283
|
+
</ui-list-item>
|
|
284
|
+
`;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
protected renderActions(): TemplateResult {
|
|
288
|
+
const { selectedFile } = this;
|
|
289
|
+
const disableSelect = !selectedFile;
|
|
290
|
+
return html`
|
|
291
|
+
<div class="actions">
|
|
292
|
+
<ui-button type="text" @click="${this.handleCancel}" value="cancel">Cancel</ui-button>
|
|
293
|
+
<ui-button type="tonal" ?disabled="${disableSelect}" @click="${this.handleSelect}" value="select">Select</ui-button>
|
|
294
|
+
</div>
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
}
|