@eclipse-lyra/extension-dataviewer 0.7.28 → 0.7.30

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.
@@ -2,7 +2,6 @@ import { LyraPart } from '@eclipse-lyra/core';
2
2
  import { DataView } from './api';
3
3
  export declare class DataViewPart extends LyraPart {
4
4
  dataview: DataView | null;
5
- standalone: boolean;
6
5
  private persistedList;
7
6
  private selectedStorageKey;
8
7
  private selectedView;
@@ -12,7 +11,6 @@ export declare class DataViewPart extends LyraPart {
12
11
  private get hasData();
13
12
  private toCsv;
14
13
  private onExportCsv;
15
- private chooseExportDirectory;
16
14
  protected doInitUI(): Promise<void>;
17
15
  private refreshPersistedList;
18
16
  private selectStorageKey;
@@ -1 +1 @@
1
- {"version":3,"file":"dataview-part.d.ts","sourceRoot":"","sources":["../src/dataview-part.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAiC,MAAM,oBAAoB,CAAC;AAE7E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,mBAAmB,CAAC;AAE3B,qBACa,YAAa,SAAQ,QAAQ;IAExC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAGjC,UAAU,UAAS;IAGnB,OAAO,CAAC,aAAa,CAA2B;IAGhD,OAAO,CAAC,kBAAkB,CAAM;IAGhC,OAAO,CAAC,YAAY,CAAyB;IAG7C,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,eAAe,CAAQ;IAE/B,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,OAAO,GAKlB;IAED,OAAO,CAAC,KAAK;YAaC,WAAW;YAoBX,qBAAqB;cAInB,QAAQ;YAUV,oBAAoB;YAyBpB,gBAAgB;YAkBhB,oBAAoB;YAQpB,eAAe;YAQf,YAAY;YAgBZ,cAAc;IAW5B,SAAS,CAAC,aAAa;IAiGvB,OAAO,CAAC,WAAW;IAOnB,MAAM;IAMN,MAAM,CAAC,MAAM,0BAaX;CAEH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,YAAY,CAAC;KAC/B;CACF"}
1
+ {"version":3,"file":"dataview-part.d.ts","sourceRoot":"","sources":["../src/dataview-part.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAiC,MAAM,oBAAoB,CAAC;AAE7E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,mBAAmB,CAAC;AAE3B,qBACa,YAAa,SAAQ,QAAQ;IAExC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAGjC,OAAO,CAAC,aAAa,CAA2B;IAGhD,OAAO,CAAC,kBAAkB,CAAM;IAGhC,OAAO,CAAC,YAAY,CAAyB;IAG7C,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,eAAe,CAAQ;IAE/B,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,OAAO,GAKlB;IAED,OAAO,CAAC,KAAK;YAaC,WAAW;cAmBT,QAAQ;YAUV,oBAAoB;YAyBpB,gBAAgB;YAkBhB,oBAAoB;YAQpB,eAAe;YAQf,YAAY;YAgBZ,cAAc;IAW5B,SAAS,CAAC,aAAa;IAgGvB,OAAO,CAAC,WAAW;IAOnB,MAAM;IAMN,MAAM,CAAC,MAAM,0BAaX;CAEH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,YAAY,CAAC;KAC/B;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { css, LitElement, html } from "lit";
2
- import { subscribe, persistenceService, publish, LyraPart, toastError, filebrowserDialog, rootContext, contributionRegistry, PANEL_BOTTOM, editorRegistry, File } from "@eclipse-lyra/core";
2
+ import { subscribe, persistenceService, publish, LyraPart, filebrowserDialog, toastError, rootContext, contributionRegistry, PANEL_BOTTOM, editorRegistry, File } from "@eclipse-lyra/core";
3
3
  import { v4 } from "@eclipse-lyra/core/externals/third-party";
4
4
  import { TOPIC_DATAVIEW_PUBLISH, TOPIC_DATAVIEW_ADDED } from "./api.js";
5
5
  import { property, state, customElement } from "lit/decorators.js";
@@ -427,7 +427,6 @@ let DataViewPart = class extends LyraPart {
427
427
  constructor() {
428
428
  super(...arguments);
429
429
  this.dataview = null;
430
- this.standalone = false;
431
430
  this.persistedList = [];
432
431
  this.selectedStorageKey = "";
433
432
  this.selectedView = null;
@@ -464,7 +463,7 @@ ${body}` : header;
464
463
  const safeTitle = dv.title?.trim() || "dataview";
465
464
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
466
465
  const fileName = `${safeTitle.replace(/[^a-zA-Z0-9-_]+/g, "_")}-${timestamp}.csv`;
467
- const targetDir = await this.chooseExportDirectory();
466
+ const targetDir = await filebrowserDialog("directory");
468
467
  if (!targetDir) return;
469
468
  this.executeCommand("touch", {
470
469
  path: `${targetDir}/${fileName}`,
@@ -474,9 +473,6 @@ ${body}` : header;
474
473
  toastError(err instanceof Error ? err.message : String(err));
475
474
  }
476
475
  }
477
- async chooseExportDirectory() {
478
- return filebrowserDialog("directory");
479
- }
480
476
  async doInitUI() {
481
477
  const persisted = await this.getDialogSetting();
482
478
  if (persisted && typeof persisted.autoActivateTab === "boolean") this.autoActivateTab = persisted.autoActivateTab;
@@ -567,7 +563,6 @@ ${body}` : header;
567
563
  }
568
564
  }
569
565
  renderToolbar() {
570
- if (this.standalone) return html``;
571
566
  const current = this.selectedView ?? this.dataview;
572
567
  const selectedMeta = this.persistedList.find((e) => e.storageKey === this.selectedStorageKey);
573
568
  const baseTitle = selectedMeta?.title ?? current?.title ?? (this.persistedList.length > 0 ? "Latest data view" : "No data");
@@ -684,9 +679,6 @@ DataViewPart.styles = css`
684
679
  __decorateClass([
685
680
  property({ attribute: false })
686
681
  ], DataViewPart.prototype, "dataview", 2);
687
- __decorateClass([
688
- property({ type: Boolean })
689
- ], DataViewPart.prototype, "standalone", 2);
690
682
  __decorateClass([
691
683
  state()
692
684
  ], DataViewPart.prototype, "persistedList", 2);
@@ -738,15 +730,15 @@ editorRegistry.registerEditorInputHandler({
738
730
  const name = input.getName();
739
731
  const text = await input.getContents();
740
732
  const { columns, rows } = parseCsv(text ?? "");
741
- const dataView = { title: name, data: { columns, rows } };
733
+ const data = { columns, rows };
742
734
  const editorInput = {
743
735
  title: name,
744
- data: dataView,
736
+ data,
745
737
  key: name,
746
738
  icon: "table",
747
739
  noOverflow: false,
748
740
  state: {},
749
- component: () => html`<lyra-dataview .dataview=${dataView} .standalone=${true}></lyra-dataview>`
741
+ component: () => html`<lyra-data-table .data=${data}></lyra-data-table>`
750
742
  };
751
743
  return editorInput;
752
744
  }
@@ -756,4 +748,4 @@ function dataviewerExtension() {
756
748
  export {
757
749
  dataviewerExtension as default
758
750
  };
759
- //# sourceMappingURL=dataviewer-extension-DhaSMapU.js.map
751
+ //# sourceMappingURL=dataviewer-extension-BY-0AspL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataviewer-extension-BY-0AspL.js","sources":["../src/dataviewer-service.ts","../src/lyra-data-table.ts","../src/dataview-part.ts","../src/parse-csv.ts","../src/dataviewer-extension.ts"],"sourcesContent":["import { persistenceService, subscribe, publish } from '@eclipse-lyra/core';\nimport { v4 } from '@eclipse-lyra/core/externals/third-party';\nimport type { DataView } from './api';\nimport { TOPIC_DATAVIEW_PUBLISH, TOPIC_DATAVIEW_ADDED } from './api';\n\nconst KEY_PREFIX = 'dataview/';\nconst KEY_INDEX = KEY_PREFIX + 'index';\n\nexport interface DataviewListEntry {\n storageKey: string;\n title: string;\n source?: string;\n createdAt: number;\n}\n\ntype IndexEntry = DataviewListEntry;\n\nexport class DataviewerService {\n private subscriptionToken?: string;\n\n init(): void {\n if (this.subscriptionToken !== undefined) return;\n this.subscriptionToken = subscribe(TOPIC_DATAVIEW_PUBLISH, (payload: DataView) => {\n void this.handlePublish(payload);\n });\n }\n\n private async handlePublish(payload: DataView): Promise<void> {\n const storageKey = v4();\n const createdAt = Date.now();\n const entry: DataView = {\n id: payload.id ?? storageKey,\n title: payload.title,\n data: payload.data,\n source: payload.source,\n createdAt,\n };\n await persistenceService.persistObject(KEY_PREFIX + storageKey, entry);\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index : [];\n list.push({ storageKey, title: payload.title, source: payload.source, createdAt });\n await persistenceService.persistObject(KEY_INDEX, list);\n publish(TOPIC_DATAVIEW_ADDED, { storageKey, title: payload.title, createdAt });\n }\n\n async listViews(): Promise<DataviewListEntry[]> {\n const raw = await persistenceService.getObject(KEY_INDEX);\n if (!Array.isArray(raw) || raw.length === 0) return [];\n if (typeof raw[0] === 'string') {\n return (raw as string[]).map((storageKey) => ({\n storageKey,\n title: storageKey,\n createdAt: 0,\n }));\n }\n const list = raw as IndexEntry[];\n return [...list].sort((a, b) => a.createdAt - b.createdAt);\n }\n\n async getView(storageKey: string): Promise<DataView | null> {\n const entry = await persistenceService.getObject(KEY_PREFIX + storageKey);\n return entry ?? null;\n }\n\n async deleteView(storageKey: string): Promise<void> {\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index.filter((e) => e.storageKey !== storageKey) : [];\n await persistenceService.persistObject(KEY_INDEX, list);\n await persistenceService.persistObject(KEY_PREFIX + storageKey, null);\n }\n\n async clearAllViews(): Promise<void> {\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index : [];\n await Promise.all(list.map((entry) => persistenceService.persistObject(KEY_PREFIX + entry.storageKey, null)));\n await persistenceService.persistObject(KEY_INDEX, []);\n }\n}\n\nexport const dataviewerService = new DataviewerService();\n","import { LitElement } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { css, html } from 'lit';\nimport type { TabularData } from './api';\n\ntype SortDirection = 'asc' | 'desc';\n\nfunction cellString(value: unknown): string {\n if (value === null || value === undefined) return '';\n return String(value);\n}\n\nfunction isNumericColumn(rows: unknown[][], colIndex: number): boolean {\n if (rows.length === 0) return false;\n return rows.every((row) => {\n const v = row[colIndex];\n if (v === null || v === undefined) return true;\n const n = Number(v);\n return Number.isFinite(n);\n });\n}\n\nfunction compareCells(a: unknown, b: unknown, numeric: boolean): number {\n if (numeric) {\n const na = Number(a);\n const nb = Number(b);\n if (!Number.isFinite(na)) return Number.isFinite(nb) ? 1 : 0;\n if (!Number.isFinite(nb)) return -1;\n return na - nb;\n }\n return cellString(a).localeCompare(cellString(b), undefined, { numeric: true });\n}\n\n@customElement('lyra-data-table')\nexport class LyraDataTable extends LitElement {\n @property({ attribute: false })\n data: TabularData = { columns: [], rows: [] };\n\n @property({ type: String })\n emptyMessage = 'No data.';\n\n @state()\n private sortColumnIndex: number | null = null;\n\n @state()\n private sortDirection: SortDirection = 'asc';\n\n @state()\n private filterQuery = '';\n\n @state()\n private pageSize = 25;\n\n @state()\n private currentPage = 0;\n\n private static readonly PAGE_SIZE_OPTIONS = [10, 25, 50, 100];\n\n private get columns(): string[] {\n return Array.isArray(this.data?.columns) ? this.data.columns : [];\n }\n\n private get rows(): unknown[][] {\n return Array.isArray(this.data?.rows) ? this.data.rows : [];\n }\n\n private get filteredRows(): unknown[][] {\n const q = this.filterQuery.trim().toLowerCase();\n if (!q) return this.rows;\n return this.rows.filter((row) =>\n row.some((cell) => cellString(cell).toLowerCase().includes(q))\n );\n }\n\n private get sortedRows(): unknown[][] {\n const filtered = this.filteredRows;\n if (this.sortColumnIndex == null || this.sortColumnIndex < 0) return filtered;\n const col = this.sortColumnIndex;\n const numeric = isNumericColumn(filtered, col);\n const dir = this.sortDirection === 'asc' ? 1 : -1;\n return [...filtered].sort((rowA, rowB) => {\n const a = rowA[col];\n const b = rowB[col];\n return dir * compareCells(a, b, numeric);\n });\n }\n\n private get totalRows(): number {\n return this.sortedRows.length;\n }\n\n private get pageCount(): number {\n const total = this.totalRows;\n if (total === 0) return 1;\n return Math.ceil(total / this.pageSize);\n }\n\n private get pagedRows(): unknown[][] {\n const all = this.sortedRows;\n const page = this.clampedPage;\n const start = page * this.pageSize;\n return all.slice(start, start + this.pageSize);\n }\n\n private get clampedPage(): number {\n const count = this.pageCount;\n return count <= 0 ? 0 : Math.min(this.currentPage, count - 1);\n }\n\n private goToPage(page: number): void {\n const last = Math.max(0, this.pageCount - 1);\n this.currentPage = Math.max(0, Math.min(page, last));\n this.requestUpdate();\n }\n\n private onPageSizeChange(e: Event): void {\n const val = (e.target as HTMLSelectElement).value;\n const n = parseInt(val, 10);\n if (!Number.isFinite(n) || n < 1) return;\n this.pageSize = n;\n this.currentPage = 0;\n this.requestUpdate();\n }\n\n private onSort(colIndex: number): void {\n if (this.sortColumnIndex === colIndex) {\n this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n this.sortColumnIndex = colIndex;\n this.sortDirection = 'asc';\n }\n this.requestUpdate();\n }\n\n private onFilterInput(e: Event): void {\n this.filterQuery = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }\n\n private clearFilter(): void {\n this.filterQuery = '';\n this.requestUpdate();\n }\n\n private getSortAria(colIndex: number): string {\n if (this.sortColumnIndex !== colIndex) return 'none';\n return this.sortDirection === 'asc' ? 'ascending' : 'descending';\n }\n\n render() {\n const { columns } = this;\n const total = this.totalRows;\n const displayRows = this.pagedRows;\n const page = this.clampedPage;\n const count = this.pageCount;\n const start = total === 0 ? 0 : page * this.pageSize + 1;\n const end = Math.min((page + 1) * this.pageSize, total);\n\n if (columns.length === 0 && total === 0 && this.rows.length === 0) {\n return html`<div class=\"table-empty\">${this.emptyMessage}</div>`;\n }\n\n return html`\n <div class=\"table-toolbar\">\n <wa-input\n class=\"filter-input\"\n placeholder=\"Filter…\"\n .value=${this.filterQuery}\n @input=${this.onFilterInput}\n @wa-clear=${this.clearFilter}\n with-clear\n size=\"small\"\n aria-label=\"Filter rows\"\n >\n <wa-icon slot=\"start\" name=\"magnifying-glass\" label=\"Filter\"></wa-icon>\n </wa-input>\n <div class=\"paging-controls\">\n <wa-select\n class=\"page-size-select\"\n size=\"small\"\n .value=${String(this.pageSize)}\n title=\"Rows per page\"\n @change=${this.onPageSizeChange}\n >\n ${LyraDataTable.PAGE_SIZE_OPTIONS.map(\n (n) => html`<wa-option value=${String(n)}>${n}</wa-option>`\n )}\n </wa-select>\n <span class=\"paging-summary\" aria-live=\"polite\">\n ${total === 0 ? '0 rows' : `${start}–${end} of ${total}`}\n </span>\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Previous page\"\n ?disabled=${count <= 1 || page <= 0}\n @click=${() => this.goToPage(page - 1)}\n >\n <wa-icon name=\"chevron-left\" label=\"Previous\"></wa-icon>\n </wa-button>\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Next page\"\n ?disabled=${count <= 1 || page >= count - 1}\n @click=${() => this.goToPage(page + 1)}\n >\n <wa-icon name=\"chevron-right\" label=\"Next\"></wa-icon>\n </wa-button>\n </div>\n </div>\n <div class=\"table-wrap\">\n <table class=\"result-table\">\n <thead>\n <tr>\n ${columns.map(\n (col, i) => html`\n <th scope=\"col\" role=\"columnheader\" aria-sort=${this.getSortAria(i)}>\n <button\n type=\"button\"\n class=\"th-sort\"\n @click=${() => this.onSort(i)}\n title=\"Sort by ${col}\"\n >\n <span class=\"th-label\">${col}</span>\n ${this.sortColumnIndex === i\n ? html`<wa-icon\n name=${this.sortDirection === 'asc' ? 'arrow-up' : 'arrow-down'}\n label=${this.sortDirection}\n ></wa-icon>`\n : html`<wa-icon name=\"arrows-up-down\" label=\"Sort\"></wa-icon>`}\n </button>\n </th>\n `\n )}\n </tr>\n </thead>\n <tbody>\n ${displayRows.length === 0\n ? html`<tr><td colspan=${columns.length} class=\"table-empty-cell\">No matching rows.</td></tr>`\n : displayRows.map(\n (row) => html`\n <tr>\n ${row.map((cell) => html`<td>${cellString(cell)}</td>`)}\n </tr>\n `\n )}\n </tbody>\n </table>\n </div>\n `;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n }\n .table-empty {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n }\n .table-toolbar {\n flex: none;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.25rem 0;\n flex-wrap: wrap;\n }\n .filter-input {\n max-width: 280px;\n }\n .paging-controls {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-left: auto;\n }\n .page-size-select {\n }\n .paging-summary {\n font-size: 0.8125rem;\n color: var(--wa-color-text-quiet);\n min-width: 5rem;\n }\n .table-wrap {\n flex: 1;\n min-height: 0;\n overflow: auto;\n border: 1px solid var(--wa-color-neutral-border-quiet);\n border-radius: var(--wa-border-radius-medium, 0.25rem);\n }\n .result-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.875rem;\n color: var(--wa-color-text-normal);\n }\n .result-table th,\n .result-table td {\n padding: 0.5rem 0.75rem;\n text-align: left;\n border-bottom: 1px solid var(--wa-color-neutral-border-quiet);\n }\n .result-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--wa-color-surface-lowered);\n font-weight: 600;\n white-space: nowrap;\n color: var(--wa-color-text-normal);\n box-shadow: 0 1px 0 0 var(--wa-color-neutral-border-quiet);\n }\n .result-table tbody tr:nth-child(even) td {\n background: var(--wa-color-surface-default);\n }\n .result-table tbody tr:nth-child(odd) td {\n background: var(--wa-color-surface-lowered);\n }\n .result-table tbody tr:hover td {\n background: var(--wa-color-neutral-fill-normal);\n }\n .th-sort {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n width: 100%;\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n cursor: pointer;\n color: inherit;\n text-align: left;\n }\n .th-sort:hover {\n opacity: 0.85;\n }\n .th-label {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .th-sort wa-icon {\n flex-shrink: 0;\n opacity: 0.7;\n font-size: 0.75em;\n }\n .table-empty-cell {\n color: var(--wa-color-text-quiet);\n font-style: italic;\n text-align: center;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'lyra-data-table': LyraDataTable;\n }\n}\n","import { customElement, property, state } from 'lit/decorators.js';\nimport { css, html } from 'lit';\nimport { LyraPart, toastError, filebrowserDialog } from '@eclipse-lyra/core';\nimport { dataviewerService, type DataviewListEntry } from './dataviewer-service';\nimport type { DataView } from './api';\nimport { TOPIC_DATAVIEW_ADDED } from './api';\nimport { when } from '@eclipse-lyra/core/externals/lit';\nimport './lyra-data-table';\n\n@customElement('lyra-dataview')\nexport class DataViewPart extends LyraPart {\n @property({ attribute: false })\n dataview: DataView | null = null;\n\n @state()\n private persistedList: DataviewListEntry[] = [];\n\n @state()\n private selectedStorageKey = '';\n\n @state()\n private selectedView: DataView | null = null;\n\n @state()\n private loadingList = true;\n\n @state()\n private autoActivateTab = true;\n\n private get displayed(): DataView | null {\n return this.selectedView ?? this.dataview;\n }\n\n private get hasData(): boolean {\n const dv = this.displayed;\n if (!dv) return false;\n const { columns, rows } = dv.data;\n return Array.isArray(columns) && Array.isArray(rows) && (columns.length > 0 || rows.length > 0);\n }\n\n private toCsv(dv: DataView): string {\n const { columns, rows } = dv.data;\n const escapeCell = (value: unknown): string => {\n if (value === null || value === undefined) return '';\n const str = String(value);\n if (!/[\",\\n]/.test(str)) return str;\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n };\n const header = columns.map(escapeCell).join(',');\n const body = rows.map((row) => row.map(escapeCell).join(',')).join('\\n');\n return body ? `${header}\\n${body}` : header;\n }\n\n private async onExportCsv(): Promise<void> {\n const dv = this.displayed;\n if (!dv || !this.hasData) return;\n try {\n const csv = this.toCsv(dv);\n const safeTitle = dv.title?.trim() || 'dataview';\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const fileName = `${safeTitle.replace(/[^a-zA-Z0-9-_]+/g, '_')}-${timestamp}.csv`;\n const targetDir = await filebrowserDialog('directory');\n if (!targetDir) return;\n this.executeCommand('touch', {\n path: `${targetDir}/${fileName}`,\n contents: csv,\n });\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n protected async doInitUI() {\n const persisted = await this.getDialogSetting();\n if (persisted && typeof persisted.autoActivateTab === 'boolean') this.autoActivateTab = persisted.autoActivateTab;\n this.subscribe(TOPIC_DATAVIEW_ADDED, async () => {\n await this.refreshPersistedList(true);\n if (this.autoActivateTab) this.activateContainingTab();\n });\n await this.refreshPersistedList(false);\n }\n\n private async refreshPersistedList(selectLatest: boolean): Promise<void> {\n this.loadingList = true;\n this.requestUpdate();\n try {\n this.persistedList = await dataviewerService.listViews();\n if (selectLatest && this.persistedList.length > 0) {\n const latest = this.persistedList[this.persistedList.length - 1];\n this.selectedStorageKey = latest.storageKey;\n this.selectedView = await dataviewerService.getView(latest.storageKey);\n } else if (this.selectedStorageKey) {\n this.selectedView = await dataviewerService.getView(this.selectedStorageKey);\n } else {\n this.selectedView = null;\n }\n } catch (e) {\n toastError(e instanceof Error ? e.message : String(e));\n this.persistedList = [];\n this.selectedView = null;\n } finally {\n this.loadingList = false;\n this.requestUpdate();\n this.updateToolbar();\n }\n }\n\n private async selectStorageKey(key: string): Promise<void> {\n this.selectedStorageKey = key;\n if (!key) {\n this.selectedView = null;\n this.requestUpdate();\n this.updateToolbar();\n return;\n }\n try {\n this.selectedView = await dataviewerService.getView(key);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n this.selectedView = null;\n }\n this.requestUpdate();\n this.updateToolbar();\n }\n\n private async onAutoActivateChange(e: Event): Promise<void> {\n const checked = (e.target as HTMLInputElement).checked;\n this.autoActivateTab = checked;\n const current = (await this.getDialogSetting()) ?? {};\n await this.setDialogSetting({ ...current, autoActivateTab: checked });\n this.updateToolbar();\n }\n\n private async onHistorySelect(e: CustomEvent<{ item?: { value?: string } }>): Promise<void> {\n const value = e.detail?.item?.value ?? '';\n if (!value || value === '__stats__') {\n return;\n }\n await this.selectStorageKey(value);\n }\n\n private async onDeleteView(e: Event, storageKey: string): Promise<void> {\n e.stopPropagation();\n e.preventDefault();\n try {\n await dataviewerService.deleteView(storageKey);\n const deletedWasSelected = this.selectedStorageKey === storageKey;\n if (deletedWasSelected) {\n this.selectedStorageKey = '';\n this.selectedView = null;\n }\n await this.refreshPersistedList(true);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n private async onClearHistory(): Promise<void> {\n try {\n await dataviewerService.clearAllViews();\n this.selectedStorageKey = '';\n this.selectedView = null;\n await this.refreshPersistedList(false);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n protected renderToolbar() {\n const current = this.selectedView ?? this.dataview;\n const selectedMeta = this.persistedList.find((e) => e.storageKey === this.selectedStorageKey);\n const baseTitle = selectedMeta?.title ?? current?.title ?? (this.persistedList.length > 0 ? 'Latest data view' : 'No data');\n const formattedCreatedAt =\n (selectedMeta?.createdAt ?? (current as any)?.createdAt)\n ? new Date(selectedMeta?.createdAt ?? (current as any)?.createdAt).toLocaleString()\n : null;\n const engineLabel = current?.source ?? null;\n const titleWithEngine = engineLabel ? `${baseTitle} · ${engineLabel}` : baseTitle;\n const currentLabel = formattedCreatedAt ? `${titleWithEngine} (${formattedCreatedAt})` : titleWithEngine;\n return html`\n <wa-dropdown\n placement=\"bottom-start\"\n distance=\"4\"\n size=\"small\"\n hoist\n @wa-select=${(e: CustomEvent) => this.onHistorySelect(e as any)}\n >\n <wa-button\n slot=\"trigger\"\n appearance=\"plain\"\n size=\"small\"\n with-caret\n title=\"Data view history\"\n >\n <wa-icon name=\"clock-rotate-left\" label=\"History\"></wa-icon>\n </wa-button>\n\n <wa-dropdown-item value=\"__stats__\" disabled>\n ${this.persistedList.length} data view${this.persistedList.length === 1 ? '' : 's'}\n ${this.persistedList.length > 0\n ? html`\n <wa-button\n slot=\"details\"\n appearance=\"plain\"\n size=\"small\"\n title=\"Clear history\"\n @click=${() => this.onClearHistory()}\n >\n <wa-icon name=\"trash\" label=\"Clear history\"></wa-icon>\n </wa-button>\n `\n : null}\n </wa-dropdown-item>\n\n ${this.persistedList.map(\n (entry) => html`\n <wa-dropdown-item value=${entry.storageKey}>\n ${entry.source ? `${entry.title} · ${entry.source}` : entry.title}\n ${entry.createdAt\n ? html`<span style=\"opacity: 0.7; margin-left: 0.5rem; font-size: 0.75em;\">\n (${new Date(entry.createdAt).toLocaleString()})\n </span>`\n : null}\n <wa-button\n slot=\"details\"\n appearance=\"plain\"\n size=\"small\"\n title=\"Delete data view\"\n @click=${(e: Event) => this.onDeleteView(e, entry.storageKey)}\n >\n <wa-icon name=\"trash\" label=\"Delete\"></wa-icon>\n </wa-button>\n </wa-dropdown-item>\n `\n )}\n\n </wa-dropdown>\n\n <wa-divider orientation=\"vertical\"></wa-divider>\n\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Export current data view to CSV\"\n ?disabled=${!this.hasData}\n @click=${() => this.onExportCsv()}\n >\n <wa-icon name=\"file-csv\" label=\"Export CSV\"></wa-icon>\n </wa-button>\n\n <wa-switch\n ?checked=${this.autoActivateTab}\n size=\"small\"\n title=\"Switch to this tab when new results arrive\"\n @change=${(e: Event) => this.onAutoActivateChange(e)}\n style=\"margin-top: 0.5rem;\"\n >\n Auto-show\n </wa-switch>\n\n ${when(current, () => html`<wa-divider orientation=\"vertical\"></wa-divider><span>${currentLabel}</span>`)}\n `;\n }\n\n private renderTable(dv: DataView) {\n if (!this.hasData) {\n return html`<div class=\"result-empty\">No data.</div>`;\n }\n return html`<lyra-data-table .data=${dv.data}></lyra-data-table>`;\n }\n\n render() {\n const dv = this.displayed;\n if (dv != null) return this.renderTable(dv);\n return html`<div class=\"result-empty\">No data.</div>`;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .result-empty {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n }\n `;\n\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'lyra-dataview': DataViewPart;\n }\n}\n","import Papa from 'papaparse';\n\n/** Parses CSV-like (comma-, tab-, or other delimited) text; delimiter is auto-detected. */\nexport function parseCsv(text: string): { columns: string[]; rows: unknown[][] } {\n const result = Papa.parse<Record<string, unknown>>(text, {\n header: true,\n skipEmptyLines: true,\n });\n const columns = result.meta.fields ?? [];\n const rows = result.data.map((row: Record<string, unknown>) =>\n columns.map((col: string) => row[col])\n );\n return { columns, rows };\n}\n","import { html } from 'lit';\nimport {\n rootContext,\n editorRegistry,\n contributionRegistry,\n File,\n type EditorInput,\n} from '@eclipse-lyra/core';\nimport { PANEL_BOTTOM } from '@eclipse-lyra/core';\nimport { dataviewerService } from './dataviewer-service';\nimport './dataview-part';\nimport type { DataView } from './api';\nimport { parseCsv } from './parse-csv';\n\ndataviewerService.init();\nrootContext.put('dataviewerService', dataviewerService);\n\ncontributionRegistry.registerContribution(PANEL_BOTTOM, {\n name: 'view.dataviewer',\n label: 'Data Views',\n icon: 'table',\n component: (id: string) => html`<lyra-dataview id=\"${id}\"></lyra-dataview>`,\n});\n\neditorRegistry.registerEditorInputHandler({\n editorId: 'system.dataviewer-table',\n label: 'Table',\n icon: 'table',\n ranking: 800,\n canHandle: (input: unknown) => {\n if (!(input instanceof File)) return false;\n const lower = input.getName().toLowerCase();\n return lower.endsWith('.csv') || lower.endsWith('.tsv');\n },\n handle: async (input: File) => {\n const name = input.getName();\n const text = (await input.getContents()) as string;\n const { columns, rows } = parseCsv(text ?? '');\n const data = { columns, rows };\n const editorInput: EditorInput = {\n title: name,\n data,\n key: name,\n icon: 'table',\n noOverflow: false,\n state: {},\n component: () => html`<lyra-data-table .data=${data}></lyra-data-table>`,\n };\n return editorInput;\n },\n});\n\nexport default function () {}\n"],"names":["__decorateClass"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ extensionRegistry.registerExtension({
4
4
  id: pkg.name,
5
5
  name: "Data Viewer",
6
6
  description: "Tabular data views, persistence, and CSV/TSV/DuckDB integration",
7
- loader: () => import("./dataviewer-extension-DhaSMapU.js"),
7
+ loader: () => import("./dataviewer-extension-BY-0AspL.js"),
8
8
  icon: "table"
9
9
  });
10
10
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-lyra/extension-dataviewer",
3
- "version": "0.7.28",
3
+ "version": "0.7.30",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/eclipse-lyra/core"
@@ -1 +0,0 @@
1
- {"version":3,"file":"dataviewer-extension-DhaSMapU.js","sources":["../src/dataviewer-service.ts","../src/lyra-data-table.ts","../src/dataview-part.ts","../src/parse-csv.ts","../src/dataviewer-extension.ts"],"sourcesContent":["import { persistenceService, subscribe, publish } from '@eclipse-lyra/core';\nimport { v4 } from '@eclipse-lyra/core/externals/third-party';\nimport type { DataView } from './api';\nimport { TOPIC_DATAVIEW_PUBLISH, TOPIC_DATAVIEW_ADDED } from './api';\n\nconst KEY_PREFIX = 'dataview/';\nconst KEY_INDEX = KEY_PREFIX + 'index';\n\nexport interface DataviewListEntry {\n storageKey: string;\n title: string;\n source?: string;\n createdAt: number;\n}\n\ntype IndexEntry = DataviewListEntry;\n\nexport class DataviewerService {\n private subscriptionToken?: string;\n\n init(): void {\n if (this.subscriptionToken !== undefined) return;\n this.subscriptionToken = subscribe(TOPIC_DATAVIEW_PUBLISH, (payload: DataView) => {\n void this.handlePublish(payload);\n });\n }\n\n private async handlePublish(payload: DataView): Promise<void> {\n const storageKey = v4();\n const createdAt = Date.now();\n const entry: DataView = {\n id: payload.id ?? storageKey,\n title: payload.title,\n data: payload.data,\n source: payload.source,\n createdAt,\n };\n await persistenceService.persistObject(KEY_PREFIX + storageKey, entry);\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index : [];\n list.push({ storageKey, title: payload.title, source: payload.source, createdAt });\n await persistenceService.persistObject(KEY_INDEX, list);\n publish(TOPIC_DATAVIEW_ADDED, { storageKey, title: payload.title, createdAt });\n }\n\n async listViews(): Promise<DataviewListEntry[]> {\n const raw = await persistenceService.getObject(KEY_INDEX);\n if (!Array.isArray(raw) || raw.length === 0) return [];\n if (typeof raw[0] === 'string') {\n return (raw as string[]).map((storageKey) => ({\n storageKey,\n title: storageKey,\n createdAt: 0,\n }));\n }\n const list = raw as IndexEntry[];\n return [...list].sort((a, b) => a.createdAt - b.createdAt);\n }\n\n async getView(storageKey: string): Promise<DataView | null> {\n const entry = await persistenceService.getObject(KEY_PREFIX + storageKey);\n return entry ?? null;\n }\n\n async deleteView(storageKey: string): Promise<void> {\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index.filter((e) => e.storageKey !== storageKey) : [];\n await persistenceService.persistObject(KEY_INDEX, list);\n await persistenceService.persistObject(KEY_PREFIX + storageKey, null);\n }\n\n async clearAllViews(): Promise<void> {\n const index = (await persistenceService.getObject(KEY_INDEX)) as IndexEntry[] | undefined;\n const list = Array.isArray(index) ? index : [];\n await Promise.all(list.map((entry) => persistenceService.persistObject(KEY_PREFIX + entry.storageKey, null)));\n await persistenceService.persistObject(KEY_INDEX, []);\n }\n}\n\nexport const dataviewerService = new DataviewerService();\n","import { LitElement } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { css, html } from 'lit';\nimport type { TabularData } from './api';\n\ntype SortDirection = 'asc' | 'desc';\n\nfunction cellString(value: unknown): string {\n if (value === null || value === undefined) return '';\n return String(value);\n}\n\nfunction isNumericColumn(rows: unknown[][], colIndex: number): boolean {\n if (rows.length === 0) return false;\n return rows.every((row) => {\n const v = row[colIndex];\n if (v === null || v === undefined) return true;\n const n = Number(v);\n return Number.isFinite(n);\n });\n}\n\nfunction compareCells(a: unknown, b: unknown, numeric: boolean): number {\n if (numeric) {\n const na = Number(a);\n const nb = Number(b);\n if (!Number.isFinite(na)) return Number.isFinite(nb) ? 1 : 0;\n if (!Number.isFinite(nb)) return -1;\n return na - nb;\n }\n return cellString(a).localeCompare(cellString(b), undefined, { numeric: true });\n}\n\n@customElement('lyra-data-table')\nexport class LyraDataTable extends LitElement {\n @property({ attribute: false })\n data: TabularData = { columns: [], rows: [] };\n\n @property({ type: String })\n emptyMessage = 'No data.';\n\n @state()\n private sortColumnIndex: number | null = null;\n\n @state()\n private sortDirection: SortDirection = 'asc';\n\n @state()\n private filterQuery = '';\n\n @state()\n private pageSize = 25;\n\n @state()\n private currentPage = 0;\n\n private static readonly PAGE_SIZE_OPTIONS = [10, 25, 50, 100];\n\n private get columns(): string[] {\n return Array.isArray(this.data?.columns) ? this.data.columns : [];\n }\n\n private get rows(): unknown[][] {\n return Array.isArray(this.data?.rows) ? this.data.rows : [];\n }\n\n private get filteredRows(): unknown[][] {\n const q = this.filterQuery.trim().toLowerCase();\n if (!q) return this.rows;\n return this.rows.filter((row) =>\n row.some((cell) => cellString(cell).toLowerCase().includes(q))\n );\n }\n\n private get sortedRows(): unknown[][] {\n const filtered = this.filteredRows;\n if (this.sortColumnIndex == null || this.sortColumnIndex < 0) return filtered;\n const col = this.sortColumnIndex;\n const numeric = isNumericColumn(filtered, col);\n const dir = this.sortDirection === 'asc' ? 1 : -1;\n return [...filtered].sort((rowA, rowB) => {\n const a = rowA[col];\n const b = rowB[col];\n return dir * compareCells(a, b, numeric);\n });\n }\n\n private get totalRows(): number {\n return this.sortedRows.length;\n }\n\n private get pageCount(): number {\n const total = this.totalRows;\n if (total === 0) return 1;\n return Math.ceil(total / this.pageSize);\n }\n\n private get pagedRows(): unknown[][] {\n const all = this.sortedRows;\n const page = this.clampedPage;\n const start = page * this.pageSize;\n return all.slice(start, start + this.pageSize);\n }\n\n private get clampedPage(): number {\n const count = this.pageCount;\n return count <= 0 ? 0 : Math.min(this.currentPage, count - 1);\n }\n\n private goToPage(page: number): void {\n const last = Math.max(0, this.pageCount - 1);\n this.currentPage = Math.max(0, Math.min(page, last));\n this.requestUpdate();\n }\n\n private onPageSizeChange(e: Event): void {\n const val = (e.target as HTMLSelectElement).value;\n const n = parseInt(val, 10);\n if (!Number.isFinite(n) || n < 1) return;\n this.pageSize = n;\n this.currentPage = 0;\n this.requestUpdate();\n }\n\n private onSort(colIndex: number): void {\n if (this.sortColumnIndex === colIndex) {\n this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n this.sortColumnIndex = colIndex;\n this.sortDirection = 'asc';\n }\n this.requestUpdate();\n }\n\n private onFilterInput(e: Event): void {\n this.filterQuery = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }\n\n private clearFilter(): void {\n this.filterQuery = '';\n this.requestUpdate();\n }\n\n private getSortAria(colIndex: number): string {\n if (this.sortColumnIndex !== colIndex) return 'none';\n return this.sortDirection === 'asc' ? 'ascending' : 'descending';\n }\n\n render() {\n const { columns } = this;\n const total = this.totalRows;\n const displayRows = this.pagedRows;\n const page = this.clampedPage;\n const count = this.pageCount;\n const start = total === 0 ? 0 : page * this.pageSize + 1;\n const end = Math.min((page + 1) * this.pageSize, total);\n\n if (columns.length === 0 && total === 0 && this.rows.length === 0) {\n return html`<div class=\"table-empty\">${this.emptyMessage}</div>`;\n }\n\n return html`\n <div class=\"table-toolbar\">\n <wa-input\n class=\"filter-input\"\n placeholder=\"Filter…\"\n .value=${this.filterQuery}\n @input=${this.onFilterInput}\n @wa-clear=${this.clearFilter}\n with-clear\n size=\"small\"\n aria-label=\"Filter rows\"\n >\n <wa-icon slot=\"start\" name=\"magnifying-glass\" label=\"Filter\"></wa-icon>\n </wa-input>\n <div class=\"paging-controls\">\n <wa-select\n class=\"page-size-select\"\n size=\"small\"\n .value=${String(this.pageSize)}\n title=\"Rows per page\"\n @change=${this.onPageSizeChange}\n >\n ${LyraDataTable.PAGE_SIZE_OPTIONS.map(\n (n) => html`<wa-option value=${String(n)}>${n}</wa-option>`\n )}\n </wa-select>\n <span class=\"paging-summary\" aria-live=\"polite\">\n ${total === 0 ? '0 rows' : `${start}–${end} of ${total}`}\n </span>\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Previous page\"\n ?disabled=${count <= 1 || page <= 0}\n @click=${() => this.goToPage(page - 1)}\n >\n <wa-icon name=\"chevron-left\" label=\"Previous\"></wa-icon>\n </wa-button>\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Next page\"\n ?disabled=${count <= 1 || page >= count - 1}\n @click=${() => this.goToPage(page + 1)}\n >\n <wa-icon name=\"chevron-right\" label=\"Next\"></wa-icon>\n </wa-button>\n </div>\n </div>\n <div class=\"table-wrap\">\n <table class=\"result-table\">\n <thead>\n <tr>\n ${columns.map(\n (col, i) => html`\n <th scope=\"col\" role=\"columnheader\" aria-sort=${this.getSortAria(i)}>\n <button\n type=\"button\"\n class=\"th-sort\"\n @click=${() => this.onSort(i)}\n title=\"Sort by ${col}\"\n >\n <span class=\"th-label\">${col}</span>\n ${this.sortColumnIndex === i\n ? html`<wa-icon\n name=${this.sortDirection === 'asc' ? 'arrow-up' : 'arrow-down'}\n label=${this.sortDirection}\n ></wa-icon>`\n : html`<wa-icon name=\"arrows-up-down\" label=\"Sort\"></wa-icon>`}\n </button>\n </th>\n `\n )}\n </tr>\n </thead>\n <tbody>\n ${displayRows.length === 0\n ? html`<tr><td colspan=${columns.length} class=\"table-empty-cell\">No matching rows.</td></tr>`\n : displayRows.map(\n (row) => html`\n <tr>\n ${row.map((cell) => html`<td>${cellString(cell)}</td>`)}\n </tr>\n `\n )}\n </tbody>\n </table>\n </div>\n `;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n }\n .table-empty {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n }\n .table-toolbar {\n flex: none;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.25rem 0;\n flex-wrap: wrap;\n }\n .filter-input {\n max-width: 280px;\n }\n .paging-controls {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-left: auto;\n }\n .page-size-select {\n }\n .paging-summary {\n font-size: 0.8125rem;\n color: var(--wa-color-text-quiet);\n min-width: 5rem;\n }\n .table-wrap {\n flex: 1;\n min-height: 0;\n overflow: auto;\n border: 1px solid var(--wa-color-neutral-border-quiet);\n border-radius: var(--wa-border-radius-medium, 0.25rem);\n }\n .result-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.875rem;\n color: var(--wa-color-text-normal);\n }\n .result-table th,\n .result-table td {\n padding: 0.5rem 0.75rem;\n text-align: left;\n border-bottom: 1px solid var(--wa-color-neutral-border-quiet);\n }\n .result-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--wa-color-surface-lowered);\n font-weight: 600;\n white-space: nowrap;\n color: var(--wa-color-text-normal);\n box-shadow: 0 1px 0 0 var(--wa-color-neutral-border-quiet);\n }\n .result-table tbody tr:nth-child(even) td {\n background: var(--wa-color-surface-default);\n }\n .result-table tbody tr:nth-child(odd) td {\n background: var(--wa-color-surface-lowered);\n }\n .result-table tbody tr:hover td {\n background: var(--wa-color-neutral-fill-normal);\n }\n .th-sort {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n width: 100%;\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n cursor: pointer;\n color: inherit;\n text-align: left;\n }\n .th-sort:hover {\n opacity: 0.85;\n }\n .th-label {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .th-sort wa-icon {\n flex-shrink: 0;\n opacity: 0.7;\n font-size: 0.75em;\n }\n .table-empty-cell {\n color: var(--wa-color-text-quiet);\n font-style: italic;\n text-align: center;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'lyra-data-table': LyraDataTable;\n }\n}\n","import { customElement, property, state } from 'lit/decorators.js';\nimport { css, html } from 'lit';\nimport { LyraPart, toastError, filebrowserDialog } from '@eclipse-lyra/core';\nimport { dataviewerService, type DataviewListEntry } from './dataviewer-service';\nimport type { DataView } from './api';\nimport { TOPIC_DATAVIEW_ADDED } from './api';\nimport { when } from '@eclipse-lyra/core/externals/lit';\nimport './lyra-data-table';\n\n@customElement('lyra-dataview')\nexport class DataViewPart extends LyraPart {\n @property({ attribute: false })\n dataview: DataView | null = null;\n\n @property({ type: Boolean })\n standalone = false;\n\n @state()\n private persistedList: DataviewListEntry[] = [];\n\n @state()\n private selectedStorageKey = '';\n\n @state()\n private selectedView: DataView | null = null;\n\n @state()\n private loadingList = true;\n\n @state()\n private autoActivateTab = true;\n\n private get displayed(): DataView | null {\n return this.selectedView ?? this.dataview;\n }\n\n private get hasData(): boolean {\n const dv = this.displayed;\n if (!dv) return false;\n const { columns, rows } = dv.data;\n return Array.isArray(columns) && Array.isArray(rows) && (columns.length > 0 || rows.length > 0);\n }\n\n private toCsv(dv: DataView): string {\n const { columns, rows } = dv.data;\n const escapeCell = (value: unknown): string => {\n if (value === null || value === undefined) return '';\n const str = String(value);\n if (!/[\",\\n]/.test(str)) return str;\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n };\n const header = columns.map(escapeCell).join(',');\n const body = rows.map((row) => row.map(escapeCell).join(',')).join('\\n');\n return body ? `${header}\\n${body}` : header;\n }\n\n private async onExportCsv(): Promise<void> {\n const dv = this.displayed;\n if (!dv || !this.hasData) return;\n try {\n const csv = this.toCsv(dv);\n const safeTitle = dv.title?.trim() || 'dataview';\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const fileName = `${safeTitle.replace(/[^a-zA-Z0-9-_]+/g, '_')}-${timestamp}.csv`;\n const targetDir = await this.chooseExportDirectory();\n if (!targetDir) return;\n // @ts-ignore executeCommand is available via LyraPart/LyraWidget\n this.executeCommand('touch', {\n path: `${targetDir}/${fileName}`,\n contents: csv,\n });\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n private async chooseExportDirectory(): Promise<string | null> {\n return filebrowserDialog('directory');\n }\n\n protected async doInitUI() {\n const persisted = await this.getDialogSetting();\n if (persisted && typeof persisted.autoActivateTab === 'boolean') this.autoActivateTab = persisted.autoActivateTab;\n this.subscribe(TOPIC_DATAVIEW_ADDED, async () => {\n await this.refreshPersistedList(true);\n if (this.autoActivateTab) this.activateContainingTab();\n });\n await this.refreshPersistedList(false);\n }\n\n private async refreshPersistedList(selectLatest: boolean): Promise<void> {\n this.loadingList = true;\n this.requestUpdate();\n try {\n this.persistedList = await dataviewerService.listViews();\n if (selectLatest && this.persistedList.length > 0) {\n const latest = this.persistedList[this.persistedList.length - 1];\n this.selectedStorageKey = latest.storageKey;\n this.selectedView = await dataviewerService.getView(latest.storageKey);\n } else if (this.selectedStorageKey) {\n this.selectedView = await dataviewerService.getView(this.selectedStorageKey);\n } else {\n this.selectedView = null;\n }\n } catch (e) {\n toastError(e instanceof Error ? e.message : String(e));\n this.persistedList = [];\n this.selectedView = null;\n } finally {\n this.loadingList = false;\n this.requestUpdate();\n this.updateToolbar();\n }\n }\n\n private async selectStorageKey(key: string): Promise<void> {\n this.selectedStorageKey = key;\n if (!key) {\n this.selectedView = null;\n this.requestUpdate();\n this.updateToolbar();\n return;\n }\n try {\n this.selectedView = await dataviewerService.getView(key);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n this.selectedView = null;\n }\n this.requestUpdate();\n this.updateToolbar();\n }\n\n private async onAutoActivateChange(e: Event): Promise<void> {\n const checked = (e.target as HTMLInputElement).checked;\n this.autoActivateTab = checked;\n const current = (await this.getDialogSetting()) ?? {};\n await this.setDialogSetting({ ...current, autoActivateTab: checked });\n this.updateToolbar();\n }\n\n private async onHistorySelect(e: CustomEvent<{ item?: { value?: string } }>): Promise<void> {\n const value = e.detail?.item?.value ?? '';\n if (!value || value === '__stats__') {\n return;\n }\n await this.selectStorageKey(value);\n }\n\n private async onDeleteView(e: Event, storageKey: string): Promise<void> {\n e.stopPropagation();\n e.preventDefault();\n try {\n await dataviewerService.deleteView(storageKey);\n const deletedWasSelected = this.selectedStorageKey === storageKey;\n if (deletedWasSelected) {\n this.selectedStorageKey = '';\n this.selectedView = null;\n }\n await this.refreshPersistedList(true);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n private async onClearHistory(): Promise<void> {\n try {\n await dataviewerService.clearAllViews();\n this.selectedStorageKey = '';\n this.selectedView = null;\n await this.refreshPersistedList(false);\n } catch (err) {\n toastError(err instanceof Error ? err.message : String(err));\n }\n }\n\n protected renderToolbar() {\n if (this.standalone) return html``;\n const current = this.selectedView ?? this.dataview;\n const selectedMeta = this.persistedList.find((e) => e.storageKey === this.selectedStorageKey);\n const baseTitle = selectedMeta?.title ?? current?.title ?? (this.persistedList.length > 0 ? 'Latest data view' : 'No data');\n const formattedCreatedAt =\n (selectedMeta?.createdAt ?? (current as any)?.createdAt)\n ? new Date(selectedMeta?.createdAt ?? (current as any)?.createdAt).toLocaleString()\n : null;\n const engineLabel = current?.source ?? null;\n const titleWithEngine = engineLabel ? `${baseTitle} · ${engineLabel}` : baseTitle;\n const currentLabel = formattedCreatedAt ? `${titleWithEngine} (${formattedCreatedAt})` : titleWithEngine;\n return html`\n <wa-dropdown\n placement=\"bottom-start\"\n distance=\"4\"\n size=\"small\"\n hoist\n @wa-select=${(e: CustomEvent) => this.onHistorySelect(e as any)}\n >\n <wa-button\n slot=\"trigger\"\n appearance=\"plain\"\n size=\"small\"\n with-caret\n title=\"Data view history\"\n >\n <wa-icon name=\"clock-rotate-left\" label=\"History\"></wa-icon>\n </wa-button>\n\n <wa-dropdown-item value=\"__stats__\" disabled>\n ${this.persistedList.length} data view${this.persistedList.length === 1 ? '' : 's'}\n ${this.persistedList.length > 0\n ? html`\n <wa-button\n slot=\"details\"\n appearance=\"plain\"\n size=\"small\"\n title=\"Clear history\"\n @click=${() => this.onClearHistory()}\n >\n <wa-icon name=\"trash\" label=\"Clear history\"></wa-icon>\n </wa-button>\n `\n : null}\n </wa-dropdown-item>\n\n ${this.persistedList.map(\n (entry) => html`\n <wa-dropdown-item value=${entry.storageKey}>\n ${entry.source ? `${entry.title} · ${entry.source}` : entry.title}\n ${entry.createdAt\n ? html`<span style=\"opacity: 0.7; margin-left: 0.5rem; font-size: 0.75em;\">\n (${new Date(entry.createdAt).toLocaleString()})\n </span>`\n : null}\n <wa-button\n slot=\"details\"\n appearance=\"plain\"\n size=\"small\"\n title=\"Delete data view\"\n @click=${(e: Event) => this.onDeleteView(e, entry.storageKey)}\n >\n <wa-icon name=\"trash\" label=\"Delete\"></wa-icon>\n </wa-button>\n </wa-dropdown-item>\n `\n )}\n\n </wa-dropdown>\n\n <wa-divider orientation=\"vertical\"></wa-divider>\n\n <wa-button\n size=\"small\"\n appearance=\"plain\"\n title=\"Export current data view to CSV\"\n ?disabled=${!this.hasData}\n @click=${() => this.onExportCsv()}\n >\n <wa-icon name=\"file-csv\" label=\"Export CSV\"></wa-icon>\n </wa-button>\n\n <wa-switch\n ?checked=${this.autoActivateTab}\n size=\"small\"\n title=\"Switch to this tab when new results arrive\"\n @change=${(e: Event) => this.onAutoActivateChange(e)}\n style=\"margin-top: 0.5rem;\"\n >\n Auto-show\n </wa-switch>\n\n ${when(current, () => html`<wa-divider orientation=\"vertical\"></wa-divider><span>${currentLabel}</span>`)}\n `;\n }\n\n private renderTable(dv: DataView) {\n if (!this.hasData) {\n return html`<div class=\"result-empty\">No data.</div>`;\n }\n return html`<lyra-data-table .data=${dv.data}></lyra-data-table>`;\n }\n\n render() {\n const dv = this.displayed;\n if (dv != null) return this.renderTable(dv);\n return html`<div class=\"result-empty\">No data.</div>`;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .result-empty {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n }\n `;\n\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'lyra-dataview': DataViewPart;\n }\n}\n","import Papa from 'papaparse';\n\n/** Parses CSV-like (comma-, tab-, or other delimited) text; delimiter is auto-detected. */\nexport function parseCsv(text: string): { columns: string[]; rows: unknown[][] } {\n const result = Papa.parse<Record<string, unknown>>(text, {\n header: true,\n skipEmptyLines: true,\n });\n const columns = result.meta.fields ?? [];\n const rows = result.data.map((row: Record<string, unknown>) =>\n columns.map((col: string) => row[col])\n );\n return { columns, rows };\n}\n","import { html } from 'lit';\nimport {\n rootContext,\n editorRegistry,\n contributionRegistry,\n File,\n type EditorInput,\n} from '@eclipse-lyra/core';\nimport { PANEL_BOTTOM } from '@eclipse-lyra/core';\nimport { dataviewerService } from './dataviewer-service';\nimport './dataview-part';\nimport type { DataView } from './api';\nimport { parseCsv } from './parse-csv';\n\ndataviewerService.init();\nrootContext.put('dataviewerService', dataviewerService);\n\ncontributionRegistry.registerContribution(PANEL_BOTTOM, {\n name: 'view.dataviewer',\n label: 'Data Views',\n icon: 'table',\n component: (id: string) => html`<lyra-dataview id=\"${id}\"></lyra-dataview>`,\n});\n\neditorRegistry.registerEditorInputHandler({\n editorId: 'system.dataviewer-table',\n label: 'Table',\n icon: 'table',\n ranking: 800,\n canHandle: (input: unknown) => {\n if (!(input instanceof File)) return false;\n const lower = input.getName().toLowerCase();\n return lower.endsWith('.csv') || lower.endsWith('.tsv');\n },\n handle: async (input: File) => {\n const name = input.getName();\n const text = (await input.getContents()) as string;\n const { columns, rows } = parseCsv(text ?? '');\n const dataView: DataView = { title: name, data: { columns, rows } };\n const editorInput: EditorInput = {\n title: name,\n data: dataView,\n key: name,\n icon: 'table',\n noOverflow: false,\n state: {},\n component: () => html`<lyra-dataview .dataview=${dataView} .standalone=${true}></lyra-dataview>`,\n };\n return editorInput;\n },\n});\n\nexport default function () {}\n"],"names":["__decorateClass"],"mappings":";;;;;;;AAKA,MAAM,aAAa;AACnB,MAAM,YAAY,aAAa;AAWxB,MAAM,kBAAkB;AAAA,EAG7B,OAAa;AACX,QAAI,KAAK,sBAAsB,OAAW;AAC1C,SAAK,oBAAoB,UAAU,wBAAwB,CAAC,YAAsB;AAChF,WAAK,KAAK,cAAc,OAAO;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,cAAc,SAAkC;AAC5D,UAAM,aAAa,GAAA;AACnB,UAAM,YAAY,KAAK,IAAA;AACvB,UAAM,QAAkB;AAAA,MACtB,IAAI,QAAQ,MAAM;AAAA,MAClB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB;AAAA,IAAA;AAEF,UAAM,mBAAmB,cAAc,aAAa,YAAY,KAAK;AACrE,UAAM,QAAS,MAAM,mBAAmB,UAAU,SAAS;AAC3D,UAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAA;AAC5C,SAAK,KAAK,EAAE,YAAY,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,UAAA,CAAW;AACjF,UAAM,mBAAmB,cAAc,WAAW,IAAI;AACtD,YAAQ,sBAAsB,EAAE,YAAY,OAAO,QAAQ,OAAO,WAAW;AAAA,EAC/E;AAAA,EAEA,MAAM,YAA0C;AAC9C,UAAM,MAAM,MAAM,mBAAmB,UAAU,SAAS;AACxD,QAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,EAAG,QAAO,CAAA;AACpD,QAAI,OAAO,IAAI,CAAC,MAAM,UAAU;AAC9B,aAAQ,IAAiB,IAAI,CAAC,gBAAgB;AAAA,QAC5C;AAAA,QACA,OAAO;AAAA,QACP,WAAW;AAAA,MAAA,EACX;AAAA,IACJ;AACA,UAAM,OAAO;AACb,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAAA,EAC3D;AAAA,EAEA,MAAM,QAAQ,YAA8C;AAC1D,UAAM,QAAQ,MAAM,mBAAmB,UAAU,aAAa,UAAU;AACxE,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAM,WAAW,YAAmC;AAClD,UAAM,QAAS,MAAM,mBAAmB,UAAU,SAAS;AAC3D,UAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,OAAO,CAAC,MAAM,EAAE,eAAe,UAAU,IAAI,CAAA;AACvF,UAAM,mBAAmB,cAAc,WAAW,IAAI;AACtD,UAAM,mBAAmB,cAAc,aAAa,YAAY,IAAI;AAAA,EACtE;AAAA,EAEA,MAAM,gBAA+B;AACnC,UAAM,QAAS,MAAM,mBAAmB,UAAU,SAAS;AAC3D,UAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAA;AAC5C,UAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,UAAU,mBAAmB,cAAc,aAAa,MAAM,YAAY,IAAI,CAAC,CAAC;AAC5G,UAAM,mBAAmB,cAAc,WAAW,EAAE;AAAA,EACtD;AACF;AAEO,MAAM,oBAAoB,IAAI,kBAAA;;;;;;;;;;;ACxErC,SAAS,WAAW,OAAwB;AAC1C,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,gBAAgB,MAAmB,UAA2B;AACrE,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SAAO,KAAK,MAAM,CAAC,QAAQ;AACzB,UAAM,IAAI,IAAI,QAAQ;AACtB,QAAI,MAAM,QAAQ,MAAM,OAAW,QAAO;AAC1C,UAAM,IAAI,OAAO,CAAC;AAClB,WAAO,OAAO,SAAS,CAAC;AAAA,EAC1B,CAAC;AACH;AAEA,SAAS,aAAa,GAAY,GAAY,SAA0B;AACtE,MAAI,SAAS;AACX,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,CAAC,OAAO,SAAS,EAAE,UAAU,OAAO,SAAS,EAAE,IAAI,IAAI;AAC3D,QAAI,CAAC,OAAO,SAAS,EAAE,EAAG,QAAO;AACjC,WAAO,KAAK;AAAA,EACd;AACA,SAAO,WAAW,CAAC,EAAE,cAAc,WAAW,CAAC,GAAG,QAAW,EAAE,SAAS,MAAM;AAChF;AAGO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA;AAEL,SAAA,OAAoB,EAAE,SAAS,CAAA,GAAI,MAAM,CAAA,EAAC;AAG1C,SAAA,eAAe;AAGf,SAAQ,kBAAiC;AAGzC,SAAQ,gBAA+B;AAGvC,SAAQ,cAAc;AAGtB,SAAQ,WAAW;AAGnB,SAAQ,cAAc;AAAA,EAAA;AAAA,EAItB,IAAY,UAAoB;AAC9B,WAAO,MAAM,QAAQ,KAAK,MAAM,OAAO,IAAI,KAAK,KAAK,UAAU,CAAA;AAAA,EACjE;AAAA,EAEA,IAAY,OAAoB;AAC9B,WAAO,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,OAAO,CAAA;AAAA,EAC3D;AAAA,EAEA,IAAY,eAA4B;AACtC,UAAM,IAAI,KAAK,YAAY,KAAA,EAAO,YAAA;AAClC,QAAI,CAAC,EAAG,QAAO,KAAK;AACpB,WAAO,KAAK,KAAK;AAAA,MAAO,CAAC,QACvB,IAAI,KAAK,CAAC,SAAS,WAAW,IAAI,EAAE,cAAc,SAAS,CAAC,CAAC;AAAA,IAAA;AAAA,EAEjE;AAAA,EAEA,IAAY,aAA0B;AACpC,UAAM,WAAW,KAAK;AACtB,QAAI,KAAK,mBAAmB,QAAQ,KAAK,kBAAkB,EAAG,QAAO;AACrE,UAAM,MAAM,KAAK;AACjB,UAAM,UAAU,gBAAgB,UAAU,GAAG;AAC7C,UAAM,MAAM,KAAK,kBAAkB,QAAQ,IAAI;AAC/C,WAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,MAAM,SAAS;AACxC,YAAM,IAAI,KAAK,GAAG;AAClB,YAAM,IAAI,KAAK,GAAG;AAClB,aAAO,MAAM,aAAa,GAAG,GAAG,OAAO;AAAA,IACzC,CAAC;AAAA,EACH;AAAA,EAEA,IAAY,YAAoB;AAC9B,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,IAAY,YAAoB;AAC9B,UAAM,QAAQ,KAAK;AACnB,QAAI,UAAU,EAAG,QAAO;AACxB,WAAO,KAAK,KAAK,QAAQ,KAAK,QAAQ;AAAA,EACxC;AAAA,EAEA,IAAY,YAAyB;AACnC,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,KAAK;AAClB,UAAM,QAAQ,OAAO,KAAK;AAC1B,WAAO,IAAI,MAAM,OAAO,QAAQ,KAAK,QAAQ;AAAA,EAC/C;AAAA,EAEA,IAAY,cAAsB;AAChC,UAAM,QAAQ,KAAK;AACnB,WAAO,SAAS,IAAI,IAAI,KAAK,IAAI,KAAK,aAAa,QAAQ,CAAC;AAAA,EAC9D;AAAA,EAEQ,SAAS,MAAoB;AACnC,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,YAAY,CAAC;AAC3C,SAAK,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,IAAI,CAAC;AACnD,SAAK,cAAA;AAAA,EACP;AAAA,EAEQ,iBAAiB,GAAgB;AACvC,UAAM,MAAO,EAAE,OAA6B;AAC5C,UAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG;AAClC,SAAK,WAAW;AAChB,SAAK,cAAc;AACnB,SAAK,cAAA;AAAA,EACP;AAAA,EAEQ,OAAO,UAAwB;AACrC,QAAI,KAAK,oBAAoB,UAAU;AACrC,WAAK,gBAAgB,KAAK,kBAAkB,QAAQ,SAAS;AAAA,IAC/D,OAAO;AACL,WAAK,kBAAkB;AACvB,WAAK,gBAAgB;AAAA,IACvB;AACA,SAAK,cAAA;AAAA,EACP;AAAA,EAEQ,cAAc,GAAgB;AACpC,SAAK,cAAe,EAAE,OAA4B;AAClD,SAAK,cAAA;AAAA,EACP;AAAA,EAEQ,cAAoB;AAC1B,SAAK,cAAc;AACnB,SAAK,cAAA;AAAA,EACP;AAAA,EAEQ,YAAY,UAA0B;AAC5C,QAAI,KAAK,oBAAoB,SAAU,QAAO;AAC9C,WAAO,KAAK,kBAAkB,QAAQ,cAAc;AAAA,EACtD;AAAA,EAEA,SAAS;AACP,UAAM,EAAE,YAAY;AACpB,UAAM,QAAQ,KAAK;AACnB,UAAM,cAAc,KAAK;AACzB,UAAM,OAAO,KAAK;AAClB,UAAM,QAAQ,KAAK;AACnB,UAAM,QAAQ,UAAU,IAAI,IAAI,OAAO,KAAK,WAAW;AACvD,UAAM,MAAM,KAAK,KAAK,OAAO,KAAK,KAAK,UAAU,KAAK;AAEtD,QAAI,QAAQ,WAAW,KAAK,UAAU,KAAK,KAAK,KAAK,WAAW,GAAG;AACjE,aAAO,gCAAgC,KAAK,YAAY;AAAA,IAC1D;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKQ,KAAK,WAAW;AAAA,mBAChB,KAAK,aAAa;AAAA,sBACf,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAWjB,OAAO,KAAK,QAAQ,CAAC;AAAA;AAAA,sBAEpB,KAAK,gBAAgB;AAAA;AAAA,cAE7B,cAAc,kBAAkB;AAAA,MAChC,CAAC,MAAM,wBAAwB,OAAO,CAAC,CAAC,IAAI,CAAC;AAAA,IAAA,CAC9C;AAAA;AAAA;AAAA,cAGC,UAAU,IAAI,WAAW,GAAG,KAAK,IAAI,GAAG,OAAO,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM5C,SAAS,KAAK,QAAQ,CAAC;AAAA,qBAC1B,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQ1B,SAAS,KAAK,QAAQ,QAAQ,CAAC;AAAA,qBAClC,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAUlC,QAAQ;AAAA,MACR,CAAC,KAAK,MAAM;AAAA,kEACsC,KAAK,YAAY,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,+BAItD,MAAM,KAAK,OAAO,CAAC,CAAC;AAAA,uCACZ,GAAG;AAAA;AAAA,+CAEK,GAAG;AAAA,wBAC1B,KAAK,oBAAoB,IACvB;AAAA,mCACS,KAAK,kBAAkB,QAAQ,aAAa,YAAY;AAAA,oCACvD,KAAK,aAAa;AAAA,yCAE5B,4DAA4D;AAAA;AAAA;AAAA;AAAA,IAAA,CAIvE;AAAA;AAAA;AAAA;AAAA,cAID,YAAY,WAAW,IACrB,uBAAuB,QAAQ,MAAM,0DACrC,YAAY;AAAA,MACV,CAAC,QAAQ;AAAA;AAAA,wBAEH,IAAI,IAAI,CAAC,SAAS,WAAW,WAAW,IAAI,CAAC,OAAO,CAAC;AAAA;AAAA;AAAA,IAAA,CAG5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AA6GF;AAtUa,cAsBa,oBAAoB,CAAC,IAAI,IAAI,IAAI,GAAG;AAtBjD,cA2NJ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAzNhBA,kBAAA;AAAA,EADC,SAAS,EAAE,WAAW,MAAA,CAAO;AAAA,GADnB,cAEX,WAAA,QAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAJf,cAKX,WAAA,gBAAA,CAAA;AAGQA,kBAAA;AAAA,EADP,MAAA;AAAM,GAPI,cAQH,WAAA,mBAAA,CAAA;AAGAA,kBAAA;AAAA,EADP,MAAA;AAAM,GAVI,cAWH,WAAA,iBAAA,CAAA;AAGAA,kBAAA;AAAA,EADP,MAAA;AAAM,GAbI,cAcH,WAAA,eAAA,CAAA;AAGAA,kBAAA;AAAA,EADP,MAAA;AAAM,GAhBI,cAiBH,WAAA,YAAA,CAAA;AAGAA,kBAAA;AAAA,EADP,MAAA;AAAM,GAnBI,cAoBH,WAAA,eAAA,CAAA;AApBG,gBAANA,kBAAA;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB,aAAA;;;;;;;;;;;ACxBN,IAAM,eAAN,cAA2B,SAAS;AAAA,EAApC,cAAA;AAAA,UAAA,GAAA,SAAA;AAEL,SAAA,WAA4B;AAG5B,SAAA,aAAa;AAGb,SAAQ,gBAAqC,CAAA;AAG7C,SAAQ,qBAAqB;AAG7B,SAAQ,eAAgC;AAGxC,SAAQ,cAAc;AAGtB,SAAQ,kBAAkB;AAAA,EAAA;AAAA,EAE1B,IAAY,YAA6B;AACvC,WAAO,KAAK,gBAAgB,KAAK;AAAA,EACnC;AAAA,EAEA,IAAY,UAAmB;AAC7B,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,EAAE,SAAS,KAAA,IAAS,GAAG;AAC7B,WAAO,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,KAAK,KAAK,SAAS;AAAA,EAC/F;AAAA,EAEQ,MAAM,IAAsB;AAClC,UAAM,EAAE,SAAS,KAAA,IAAS,GAAG;AAC7B,UAAM,aAAa,CAAC,UAA2B;AAC7C,UAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,YAAM,MAAM,OAAO,KAAK;AACxB,UAAI,CAAC,SAAS,KAAK,GAAG,EAAG,QAAO;AAChC,aAAO,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC;AAAA,IACpC;AACA,UAAM,SAAS,QAAQ,IAAI,UAAU,EAAE,KAAK,GAAG;AAC/C,UAAM,OAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,UAAU,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI;AACvE,WAAO,OAAO,GAAG,MAAM;AAAA,EAAK,IAAI,KAAK;AAAA,EACvC;AAAA,EAEA,MAAc,cAA6B;AACzC,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,MAAM,CAAC,KAAK,QAAS;AAC1B,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,EAAE;AACzB,YAAM,YAAY,GAAG,OAAO,KAAA,KAAU;AACtC,YAAM,iCAAgB,KAAA,GAAO,cAAc,QAAQ,SAAS,GAAG;AAC/D,YAAM,WAAW,GAAG,UAAU,QAAQ,oBAAoB,GAAG,CAAC,IAAI,SAAS;AAC3E,YAAM,YAAY,MAAM,KAAK,sBAAA;AAC7B,UAAI,CAAC,UAAW;AAEhB,WAAK,eAAe,SAAS;AAAA,QAC3B,MAAM,GAAG,SAAS,IAAI,QAAQ;AAAA,QAC9B,UAAU;AAAA,MAAA,CACX;AAAA,IACH,SAAS,KAAK;AACZ,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,wBAAgD;AAC5D,WAAO,kBAAkB,WAAW;AAAA,EACtC;AAAA,EAEA,MAAgB,WAAW;AACzB,UAAM,YAAY,MAAM,KAAK,iBAAA;AAC7B,QAAI,aAAa,OAAO,UAAU,oBAAoB,UAAW,MAAK,kBAAkB,UAAU;AAClG,SAAK,UAAU,sBAAsB,YAAY;AAC/C,YAAM,KAAK,qBAAqB,IAAI;AACpC,UAAI,KAAK,gBAAiB,MAAK,sBAAA;AAAA,IACjC,CAAC;AACD,UAAM,KAAK,qBAAqB,KAAK;AAAA,EACvC;AAAA,EAEA,MAAc,qBAAqB,cAAsC;AACvE,SAAK,cAAc;AACnB,SAAK,cAAA;AACL,QAAI;AACF,WAAK,gBAAgB,MAAM,kBAAkB,UAAA;AAC7C,UAAI,gBAAgB,KAAK,cAAc,SAAS,GAAG;AACjD,cAAM,SAAS,KAAK,cAAc,KAAK,cAAc,SAAS,CAAC;AAC/D,aAAK,qBAAqB,OAAO;AACjC,aAAK,eAAe,MAAM,kBAAkB,QAAQ,OAAO,UAAU;AAAA,MACvE,WAAW,KAAK,oBAAoB;AAClC,aAAK,eAAe,MAAM,kBAAkB,QAAQ,KAAK,kBAAkB;AAAA,MAC7E,OAAO;AACL,aAAK,eAAe;AAAA,MACtB;AAAA,IACF,SAAS,GAAG;AACV,iBAAW,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AACrD,WAAK,gBAAgB,CAAA;AACrB,WAAK,eAAe;AAAA,IACtB,UAAA;AACE,WAAK,cAAc;AACnB,WAAK,cAAA;AACL,WAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,KAA4B;AACzD,SAAK,qBAAqB;AAC1B,QAAI,CAAC,KAAK;AACR,WAAK,eAAe;AACpB,WAAK,cAAA;AACL,WAAK,cAAA;AACL;AAAA,IACF;AACA,QAAI;AACF,WAAK,eAAe,MAAM,kBAAkB,QAAQ,GAAG;AAAA,IACzD,SAAS,KAAK;AACZ,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC3D,WAAK,eAAe;AAAA,IACtB;AACA,SAAK,cAAA;AACL,SAAK,cAAA;AAAA,EACP;AAAA,EAEA,MAAc,qBAAqB,GAAyB;AAC1D,UAAM,UAAW,EAAE,OAA4B;AAC/C,SAAK,kBAAkB;AACvB,UAAM,UAAW,MAAM,KAAK,iBAAA,KAAuB,CAAA;AACnD,UAAM,KAAK,iBAAiB,EAAE,GAAG,SAAS,iBAAiB,SAAS;AACpE,SAAK,cAAA;AAAA,EACP;AAAA,EAEA,MAAc,gBAAgB,GAA8D;AAC1F,UAAM,QAAQ,EAAE,QAAQ,MAAM,SAAS;AACvC,QAAI,CAAC,SAAS,UAAU,aAAa;AACnC;AAAA,IACF;AACA,UAAM,KAAK,iBAAiB,KAAK;AAAA,EACnC;AAAA,EAEA,MAAc,aAAa,GAAU,YAAmC;AACtE,MAAE,gBAAA;AACF,MAAE,eAAA;AACF,QAAI;AACF,YAAM,kBAAkB,WAAW,UAAU;AAC7C,YAAM,qBAAqB,KAAK,uBAAuB;AACvD,UAAI,oBAAoB;AACtB,aAAK,qBAAqB;AAC1B,aAAK,eAAe;AAAA,MACtB;AACA,YAAM,KAAK,qBAAqB,IAAI;AAAA,IACtC,SAAS,KAAK;AACZ,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,iBAAgC;AAC5C,QAAI;AACF,YAAM,kBAAkB,cAAA;AACxB,WAAK,qBAAqB;AAC1B,WAAK,eAAe;AACpB,YAAM,KAAK,qBAAqB,KAAK;AAAA,IACvC,SAAS,KAAK;AACZ,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA,EAEU,gBAAgB;AACxB,QAAI,KAAK,WAAY,QAAO;AAC5B,UAAM,UAAU,KAAK,gBAAgB,KAAK;AAC1C,UAAM,eAAe,KAAK,cAAc,KAAK,CAAC,MAAM,EAAE,eAAe,KAAK,kBAAkB;AAC5F,UAAM,YAAY,cAAc,SAAS,SAAS,UAAU,KAAK,cAAc,SAAS,IAAI,qBAAqB;AACjH,UAAM,qBACH,cAAc,aAAc,SAAiB,YAC1C,IAAI,KAAK,cAAc,aAAc,SAAiB,SAAS,EAAE,mBACjE;AACN,UAAM,cAAc,SAAS,UAAU;AACvC,UAAM,kBAAkB,cAAc,GAAG,SAAS,MAAM,WAAW,KAAK;AACxE,UAAM,eAAe,qBAAqB,GAAG,eAAe,KAAK,kBAAkB,MAAM;AACzF,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMY,CAAC,MAAmB,KAAK,gBAAgB,CAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAa3D,KAAK,cAAc,MAAM,aAAa,KAAK,cAAc,WAAW,IAAI,KAAK,GAAG;AAAA,cAChF,KAAK,cAAc,SAAS,IAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAMa,MAAM,KAAK,eAAA,CAAgB;AAAA;AAAA;AAAA;AAAA,oBAKxC,IAAI;AAAA;AAAA;AAAA,YAGR,KAAK,cAAc;AAAA,MACnB,CAAC,UAAU;AAAA,wCACiB,MAAM,UAAU;AAAA,kBACtC,MAAM,SAAS,GAAG,MAAM,KAAK,MAAM,MAAM,MAAM,KAAK,MAAM,KAAK;AAAA,kBAC/D,MAAM,YACJ;AAAA,yBACK,IAAI,KAAK,MAAM,SAAS,EAAE,gBAAgB;AAAA,+BAE/C,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAMG,CAAC,MAAa,KAAK,aAAa,GAAG,MAAM,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAMpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAUW,CAAC,KAAK,OAAO;AAAA,mBAChB,MAAM,KAAK,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMtB,KAAK,eAAe;AAAA;AAAA;AAAA,oBAGrB,CAAC,MAAa,KAAK,qBAAqB,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMpD,KAAK,SAAS,MAAM,6DAA6D,YAAY,SAAS,CAAC;AAAA;AAAA,EAE/G;AAAA,EAEQ,YAAY,IAAc;AAChC,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO;AAAA,IACT;AACA,WAAO,8BAA8B,GAAG,IAAI;AAAA,EAC9C;AAAA,EAEA,SAAS;AACP,UAAM,KAAK,KAAK;AAChB,QAAI,MAAM,KAAM,QAAO,KAAK,YAAY,EAAE;AAC1C,WAAO;AAAA,EACT;AAiBF;AAnSa,aAoRJ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAlRhB,gBAAA;AAAA,EADC,SAAS,EAAE,WAAW,MAAA,CAAO;AAAA,GADnB,aAEX,WAAA,YAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAJhB,aAKX,WAAA,cAAA,CAAA;AAGQ,gBAAA;AAAA,EADP,MAAA;AAAM,GAPI,aAQH,WAAA,iBAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GAVI,aAWH,WAAA,sBAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GAbI,aAcH,WAAA,gBAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GAhBI,aAiBH,WAAA,eAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GAnBI,aAoBH,WAAA,mBAAA,CAAA;AApBG,eAAN,gBAAA;AAAA,EADN,cAAc,eAAe;AAAA,GACjB,YAAA;ACPN,SAAS,SAAS,MAAwD;AAC/E,QAAM,SAAS,KAAK,MAA+B,MAAM;AAAA,IACvD,QAAQ;AAAA,IACR,gBAAgB;AAAA,EAAA,CACjB;AACD,QAAM,UAAU,OAAO,KAAK,UAAU,CAAA;AACtC,QAAM,OAAO,OAAO,KAAK;AAAA,IAAI,CAAC,QAC5B,QAAQ,IAAI,CAAC,QAAgB,IAAI,GAAG,CAAC;AAAA,EAAA;AAEvC,SAAO,EAAE,SAAS,KAAA;AACpB;ACCA,kBAAkB,KAAA;AAClB,YAAY,IAAI,qBAAqB,iBAAiB;AAEtD,qBAAqB,qBAAqB,cAAc;AAAA,EACtD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,WAAW,CAAC,OAAe,0BAA0B,EAAE;AACzD,CAAC;AAED,eAAe,2BAA2B;AAAA,EACxC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW,CAAC,UAAmB;AAC7B,QAAI,EAAE,iBAAiB,MAAO,QAAO;AACrC,UAAM,QAAQ,MAAM,QAAA,EAAU,YAAA;AAC9B,WAAO,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,MAAM;AAAA,EACxD;AAAA,EACA,QAAQ,OAAO,UAAgB;AAC7B,UAAM,OAAO,MAAM,QAAA;AACnB,UAAM,OAAQ,MAAM,MAAM,YAAA;AAC1B,UAAM,EAAE,SAAS,KAAA,IAAS,SAAS,QAAQ,EAAE;AAC7C,UAAM,WAAqB,EAAE,OAAO,MAAM,MAAM,EAAE,SAAS,OAAK;AAChE,UAAM,cAA2B;AAAA,MAC/B,OAAO;AAAA,MACP,MAAM;AAAA,MACN,KAAK;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO,CAAA;AAAA,MACP,WAAW,MAAM,gCAAgC,QAAQ,gBAAgB,IAAI;AAAA,IAAA;AAE/E,WAAO;AAAA,EACT;AACF,CAAC;AAED,SAAA,sBAA2B;AAAC;"}