feat: implement DeesTable component with schema-first columns API, data actions, and customizable styles
- Added DeesTable class extending DeesElement - Introduced properties for headings, data, actions, and columns - Implemented rendering logic for table headers, rows, and cells - Added support for sorting, searching, and context menus - Included customizable styles for table layout and appearance - Integrated editable fields and drag-and-drop file handling - Enhanced accessibility with ARIA attributes for sorting
This commit is contained in:
1
.serena/.gitignore
vendored
Normal file
1
.serena/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/cache
|
67
.serena/project.yml
Normal file
67
.serena/project.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
||||
# * For C, use cpp
|
||||
# * For JavaScript, use typescript
|
||||
# Special requirements:
|
||||
# * csharp: Requires the presence of a .sln file in the project folder.
|
||||
language: typescript
|
||||
|
||||
# whether to use the project's gitignore file to ignore files
|
||||
# Added on 2025-04-07
|
||||
ignore_all_files_in_gitignore: true
|
||||
# list of additional paths to ignore
|
||||
# same syntax as gitignore, so you can use * and **
|
||||
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
||||
# Added (renamed) on 2025-04-07
|
||||
ignored_paths: []
|
||||
|
||||
# whether the project is in read-only mode
|
||||
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||
# Added on 2025-04-18
|
||||
read_only: false
|
||||
|
||||
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
||||
# Below is the complete list of tools for convenience.
|
||||
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||
# execute `uv run scripts/print_tool_overview.py`.
|
||||
#
|
||||
# * `activate_project`: Activates a project by name.
|
||||
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||
# * `delete_lines`: Deletes a range of lines within a file.
|
||||
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
||||
# * `execute_shell_command`: Executes a shell command.
|
||||
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
||||
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
||||
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
||||
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||
# * `initial_instructions`: Gets the initial instructions for the current project.
|
||||
# Should only be used in settings where the system prompt cannot be set,
|
||||
# e.g. in clients you have no control over, like Claude Desktop.
|
||||
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||
# * `insert_at_line`: Inserts content at a given line in a file.
|
||||
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
||||
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
||||
# * `read_file`: Reads a file within the project directory.
|
||||
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
||||
# * `remove_project`: Removes a project from the Serena configuration.
|
||||
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
||||
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
||||
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
||||
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
||||
# * `switch_modes`: Activates modes by providing a list of their names
|
||||
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
||||
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
||||
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
||||
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
||||
excluded_tools: []
|
||||
|
||||
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||
# (contrary to the memories, which are loaded on demand).
|
||||
initial_prompt: ""
|
||||
|
||||
project_name: "dees-catalog"
|
10
package.json
10
package.json
@@ -24,7 +24,7 @@
|
||||
"@fortawesome/free-solid-svg-icons": "^7.0.1",
|
||||
"@push.rocks/smarti18n": "^1.0.4",
|
||||
"@push.rocks/smartpromise": "^4.2.0",
|
||||
"@push.rocks/smartstring": "^4.0.15",
|
||||
"@push.rocks/smartstring": "^4.1.0",
|
||||
"@tiptap/core": "^2.23.0",
|
||||
"@tiptap/extension-link": "^2.23.0",
|
||||
"@tiptap/extension-text-align": "^2.23.0",
|
||||
@@ -33,11 +33,11 @@
|
||||
"@tiptap/starter-kit": "^2.23.0",
|
||||
"@tsclass/tsclass": "^9.2.0",
|
||||
"@webcontainer/api": "1.2.0",
|
||||
"apexcharts": "^5.3.4",
|
||||
"apexcharts": "^5.3.5",
|
||||
"highlight.js": "11.11.1",
|
||||
"ibantools": "^4.5.1",
|
||||
"lucide": "^0.542.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"lucide": "^0.544.0",
|
||||
"monaco-editor": "^0.53.0",
|
||||
"pdfjs-dist": "^4.10.38",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
@@ -45,7 +45,7 @@
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.6.8",
|
||||
"@git.zone/tsbundle": "^2.5.1",
|
||||
"@git.zone/tstest": "^2.3.6",
|
||||
"@git.zone/tstest": "^2.3.8",
|
||||
"@git.zone/tswatch": "^2.2.1",
|
||||
"@push.rocks/projectinfo": "^5.0.2",
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
|
583
pnpm-lock.yaml
generated
583
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
onlyBuiltDependencies:
|
||||
- puppeteer
|
@@ -20,7 +20,7 @@ import { DeesInputMultitoggle } from './dees-input-multitoggle.js';
|
||||
import { DeesInputPhone } from './dees-input-phone.js';
|
||||
import { DeesInputTypelist } from './dees-input-typelist.js';
|
||||
import { DeesFormSubmit } from './dees-form-submit.js';
|
||||
import { DeesTable } from './dees-table.js';
|
||||
import { DeesTable } from './dees-table/dees-table.js';
|
||||
import { demoFunc } from './dees-form.demo.js';
|
||||
|
||||
// Unified set for form input types
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { type ITableAction } from './dees-table.js';
|
||||
import * as plugins from './00plugins.js';
|
||||
import * as plugins from '../00plugins.js';
|
||||
import { html, css, cssManager } from '@design.estate/dees-element';
|
||||
|
||||
interface ITableDemoData {
|
||||
@@ -427,6 +427,46 @@ export const demoFunc = () => html`
|
||||
dataName="items"
|
||||
></dees-table>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Schema-First Columns (New)</h2>
|
||||
<p class="demo-description">Defines columns explicitly and renders via schema. No displayFunction needed.</p>
|
||||
<dees-table
|
||||
heading1="Users (Schema-First)"
|
||||
heading2="Columns define rendering and order"
|
||||
.columns=${[
|
||||
{ key: 'name', header: 'Name', sortable: true },
|
||||
{ key: 'email', header: 'Email', renderer: (v: string) => html`<dees-badge>${v}</dees-badge>` },
|
||||
{ key: 'joinedAt', header: 'Joined', renderer: (v: string) => new Date(v).toLocaleDateString() },
|
||||
]}
|
||||
.data=${[
|
||||
{ name: 'Alice', email: 'alice@example.com', joinedAt: '2022-08-01' },
|
||||
{ name: 'Bob', email: 'bob@example.com', joinedAt: '2021-12-11' },
|
||||
{ name: 'Carol', email: 'carol@example.com', joinedAt: '2023-03-22' },
|
||||
]}
|
||||
dataName="users"
|
||||
></dees-table>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Partial Schema + Augment (New)</h2>
|
||||
<p class="demo-description">Provides only the important columns; the rest are merged in from displayFunction.</p>
|
||||
<dees-table
|
||||
heading1="Users (Partial + Augment)"
|
||||
heading2="Missing columns are derived"
|
||||
.columns=${[
|
||||
{ key: 'name', header: 'Name', sortable: true },
|
||||
]}
|
||||
.displayFunction=${(u: any) => ({ name: u.name, email: u.email, role: u.role })}
|
||||
.augmentFromDisplayFunction=${true}
|
||||
.data=${[
|
||||
{ name: 'Erin', email: 'erin@example.com', role: 'Admin' },
|
||||
{ name: 'Finn', email: 'finn@example.com', role: 'User' },
|
||||
{ name: 'Gina', email: 'gina@example.com', role: 'User' },
|
||||
]}
|
||||
dataName="users"
|
||||
></dees-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
@@ -1,6 +1,6 @@
|
||||
import * as plugins from './00plugins.js';
|
||||
import * as plugins from '../00plugins.js';
|
||||
import { demoFunc } from './dees-table.demo.js';
|
||||
import { cssGeistFontFamily } from './00fonts.js';
|
||||
import { cssGeistFontFamily } from '../00fonts.js';
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
directives,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import { DeesContextmenu } from './dees-contextmenu.js';
|
||||
import { DeesContextmenu } from '../dees-contextmenu.js';
|
||||
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { type TIconKey } from './dees-icon.js';
|
||||
import { type TIconKey } from '../dees-icon.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -63,6 +63,21 @@ export interface ITableActionDataArg<T> {
|
||||
table: DeesTable<T>;
|
||||
}
|
||||
|
||||
// schema-first columns API (Phase 1)
|
||||
export interface Column<T = any> {
|
||||
/** key in the raw item or a computed key name */
|
||||
key: keyof T | string;
|
||||
/** header label or template; defaults to key */
|
||||
header?: string | TemplateResult;
|
||||
/** compute the cell value when not reading directly by key */
|
||||
value?: (row: T) => any;
|
||||
/** optional cell renderer */
|
||||
renderer?: (value: any, row: T, ctx: { rowIndex: number; colIndex: number; column: Column<T> }) => TemplateResult | string;
|
||||
/** reserved for future phases; present to sketch intent */
|
||||
sortable?: boolean;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
export type TDisplayFunction<T = any> = (itemArg: T) => object;
|
||||
|
||||
// the table implementation
|
||||
@@ -134,6 +149,24 @@ export class DeesTable<T> extends DeesElement {
|
||||
})
|
||||
public dataActions: ITableAction<T>[] = [];
|
||||
|
||||
// schema-first columns API
|
||||
@property({ attribute: false })
|
||||
public columns: Column<T>[] = [];
|
||||
|
||||
/**
|
||||
* Stable row identity for selection and updates. If provided as a function,
|
||||
* it is only usable as a property (not via attribute).
|
||||
*/
|
||||
@property({ attribute: false })
|
||||
public rowKey?: keyof T | ((row: T) => string);
|
||||
|
||||
/**
|
||||
* When true and columns are provided, merge any missing columns discovered
|
||||
* via displayFunction into the effective schema.
|
||||
*/
|
||||
@property({ type: Boolean })
|
||||
public augmentFromDisplayFunction: boolean = false;
|
||||
|
||||
@property({
|
||||
attribute: false,
|
||||
})
|
||||
@@ -180,6 +213,12 @@ export class DeesTable<T> extends DeesElement {
|
||||
|
||||
public dataChangeSubject = new domtools.plugins.smartrx.rxjs.Subject();
|
||||
|
||||
// simple client-side sorting (Phase 1)
|
||||
@property({ attribute: false })
|
||||
private sortKey?: string;
|
||||
@property({ attribute: false })
|
||||
private sortDir: 'asc' | 'desc' | null = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
@@ -544,6 +583,11 @@ export class DeesTable<T> extends DeesElement {
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
const usingColumns = Array.isArray(this.columns) && this.columns.length > 0;
|
||||
const effectiveColumns: Column<T>[] = usingColumns
|
||||
? this.computeEffectiveColumns()
|
||||
: this.computeColumnsFromDisplayFunction();
|
||||
|
||||
return html`
|
||||
<div class="mainbox">
|
||||
<!-- the heading part -->
|
||||
@@ -609,32 +653,35 @@ export class DeesTable<T> extends DeesElement {
|
||||
<!-- the actual table -->
|
||||
<style></style>
|
||||
${this.data.length > 0
|
||||
? (() => {
|
||||
// Only pick up the keys from the first transformed data object
|
||||
// as all data objects are assumed to have the same structure
|
||||
const firstTransformedItem = this.displayFunction(this.data[0]);
|
||||
const headings: string[] = Object.keys(firstTransformedItem);
|
||||
return html`
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
${headings.map(
|
||||
(headingArg) => html`
|
||||
<th>${headingArg}</th>
|
||||
`
|
||||
)}
|
||||
${(() => {
|
||||
if (this.dataActions && this.dataActions.length > 0) {
|
||||
return html`
|
||||
<th>Actions</th>
|
||||
`;
|
||||
}
|
||||
})()}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${this.data.map((itemArg) => {
|
||||
const transformedItem = this.displayFunction(itemArg);
|
||||
? html`
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
${effectiveColumns
|
||||
.filter((c) => !c.hidden)
|
||||
.map((col) => {
|
||||
const isSortable = !!col.sortable;
|
||||
const ariaSort = this.getAriaSort(col);
|
||||
return html`
|
||||
<th
|
||||
role="columnheader"
|
||||
aria-sort=${ariaSort}
|
||||
style="${isSortable ? 'cursor: pointer;' : ''}"
|
||||
@click=${() => (isSortable ? this.toggleSort(col) : null)}
|
||||
>
|
||||
${col.header ?? (col.key as any)}
|
||||
${this.renderSortIndicator(col)}
|
||||
</th>`;
|
||||
})}
|
||||
${(() => {
|
||||
if (this.dataActions && this.dataActions.length > 0) {
|
||||
return html` <th>Actions</th> `;
|
||||
}
|
||||
})()}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${this.getViewData(effectiveColumns).map((itemArg, rowIndex) => {
|
||||
const getTr = (elementArg: HTMLElement): HTMLElement => {
|
||||
if (elementArg.tagName === 'TR') {
|
||||
return elementArg;
|
||||
@@ -651,8 +698,6 @@ export class DeesTable<T> extends DeesElement {
|
||||
eventArg.preventDefault();
|
||||
eventArg.stopPropagation();
|
||||
const realTarget = getTr(eventArg.target as HTMLElement);
|
||||
console.log('dragenter');
|
||||
console.log(realTarget);
|
||||
setTimeout(() => {
|
||||
realTarget.classList.add('hasAttachment');
|
||||
}, 0);
|
||||
@@ -702,29 +747,31 @@ export class DeesTable<T> extends DeesElement {
|
||||
}}
|
||||
class="${itemArg === this.selectedDataRow ? 'selected' : ''}"
|
||||
>
|
||||
${headings.map(
|
||||
(headingArg) => html`
|
||||
<td
|
||||
@dblclick=${(e: Event) => {
|
||||
if (this.editableFields.includes(headingArg)) {
|
||||
this.handleCellEditing(e, itemArg, headingArg);
|
||||
} else {
|
||||
const wantedAction = this.dataActions.find((actionArg) =>
|
||||
${effectiveColumns
|
||||
.filter((c) => !c.hidden)
|
||||
.map((col, colIndex) => {
|
||||
const value = this.getCellValue(itemArg, col);
|
||||
const content = col.renderer
|
||||
? col.renderer(value, itemArg, { rowIndex, colIndex, column: col })
|
||||
: value;
|
||||
const editKey = String(col.key);
|
||||
return html`
|
||||
<td
|
||||
@dblclick=${(e: Event) => {
|
||||
const dblAction = this.dataActions.find((actionArg) =>
|
||||
actionArg.type.includes('doubleClick')
|
||||
);
|
||||
if (wantedAction) {
|
||||
wantedAction.actionFunc({
|
||||
item: itemArg,
|
||||
table: this,
|
||||
});
|
||||
if (this.editableFields.includes(editKey)) {
|
||||
this.handleCellEditing(e, itemArg, editKey);
|
||||
} else if (dblAction) {
|
||||
dblAction.actionFunc({ item: itemArg, table: this });
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="innerCellContainer">${transformedItem[headingArg]}</div>
|
||||
</td>
|
||||
`
|
||||
)}
|
||||
}}
|
||||
>
|
||||
<div class="innerCellContainer">${content}</div>
|
||||
</td>
|
||||
`;
|
||||
})}
|
||||
${(() => {
|
||||
if (this.dataActions && this.dataActions.length > 0) {
|
||||
return html`
|
||||
@@ -732,36 +779,30 @@ export class DeesTable<T> extends DeesElement {
|
||||
<div class="actionsContainer">
|
||||
${this.getActionsForType('inRow').map(
|
||||
(actionArg) => html`
|
||||
<div
|
||||
class="action"
|
||||
@click=${() =>
|
||||
actionArg.actionFunc({
|
||||
item: itemArg,
|
||||
table: this,
|
||||
})}
|
||||
>
|
||||
${actionArg.iconName
|
||||
? html`
|
||||
<dees-icon
|
||||
.icon=${actionArg.iconName}
|
||||
></dees-icon>
|
||||
`
|
||||
: actionArg.name}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
<div
|
||||
class="action"
|
||||
@click=${() =>
|
||||
actionArg.actionFunc({
|
||||
item: itemArg,
|
||||
table: this,
|
||||
})}
|
||||
>
|
||||
${actionArg.iconName
|
||||
? html` <dees-icon .icon=${actionArg.iconName}></dees-icon> `
|
||||
: actionArg.name}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
}
|
||||
})()}
|
||||
</tr>
|
||||
`;
|
||||
</tr>`;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
})()
|
||||
</tbody>
|
||||
</table>
|
||||
`
|
||||
: html` <div class="noDataSet">No data set!</div> `}
|
||||
<div class="footer">
|
||||
<div class="tableStatistics">
|
||||
@@ -869,6 +910,87 @@ export class DeesTable<T> extends DeesElement {
|
||||
table.style.tableLayout = 'fixed';
|
||||
}
|
||||
|
||||
private computeColumnsFromDisplayFunction(): Column<T>[] {
|
||||
if (!this.data || this.data.length === 0) return [];
|
||||
const firstTransformedItem = this.displayFunction(this.data[0]);
|
||||
const keys: string[] = Object.keys(firstTransformedItem);
|
||||
return keys.map((key) => ({
|
||||
key,
|
||||
header: key,
|
||||
value: (row: T) => this.displayFunction(row)[key],
|
||||
}));
|
||||
}
|
||||
|
||||
private computeEffectiveColumns(): Column<T>[] {
|
||||
const base = (this.columns || []).slice();
|
||||
if (!this.augmentFromDisplayFunction) return base;
|
||||
const fromDisplay = this.computeColumnsFromDisplayFunction();
|
||||
const existingKeys = new Set(base.map((c) => String(c.key)));
|
||||
for (const col of fromDisplay) {
|
||||
if (!existingKeys.has(String(col.key))) {
|
||||
base.push(col);
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
private getCellValue(row: T, col: Column<T>): any {
|
||||
return col.value ? col.value(row) : (row as any)[col.key as any];
|
||||
}
|
||||
|
||||
private getViewData(effectiveColumns: Column<T>[]): T[] {
|
||||
if (!this.sortKey || !this.sortDir) return this.data;
|
||||
const col = effectiveColumns.find((c) => String(c.key) === this.sortKey);
|
||||
if (!col) return this.data;
|
||||
const arr = this.data.slice();
|
||||
const dir = this.sortDir === 'asc' ? 1 : -1;
|
||||
arr.sort((a, b) => {
|
||||
const va = this.getCellValue(a, col);
|
||||
const vb = this.getCellValue(b, col);
|
||||
if (va == null && vb == null) return 0;
|
||||
if (va == null) return -1 * dir;
|
||||
if (vb == null) return 1 * dir;
|
||||
if (typeof va === 'number' && typeof vb === 'number') return (va - vb) * dir;
|
||||
const sa = String(va).toLowerCase();
|
||||
const sb = String(vb).toLowerCase();
|
||||
if (sa < sb) return -1 * dir;
|
||||
if (sa > sb) return 1 * dir;
|
||||
return 0;
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
private toggleSort(col: Column<T>) {
|
||||
const key = String(col.key);
|
||||
if (this.sortKey !== key) {
|
||||
this.sortKey = key;
|
||||
this.sortDir = 'asc';
|
||||
} else {
|
||||
if (this.sortDir === 'asc') this.sortDir = 'desc';
|
||||
else if (this.sortDir === 'desc') {
|
||||
this.sortDir = null;
|
||||
this.sortKey = undefined;
|
||||
} else this.sortDir = 'asc';
|
||||
}
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('sortChange', {
|
||||
detail: { key: this.sortKey, dir: this.sortDir },
|
||||
bubbles: true,
|
||||
})
|
||||
);
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private getAriaSort(col: Column<T>): 'none' | 'ascending' | 'descending' {
|
||||
if (String(col.key) !== this.sortKey || !this.sortDir) return 'none';
|
||||
return this.sortDir === 'asc' ? 'ascending' : 'descending';
|
||||
}
|
||||
|
||||
private renderSortIndicator(col: Column<T>) {
|
||||
if (String(col.key) !== this.sortKey || !this.sortDir) return html``;
|
||||
return html`<span style="margin-left:6px; opacity:0.7;">${this.sortDir === 'asc' ? '▲' : '▼'}</span>`;
|
||||
}
|
||||
|
||||
getActionsForType(typeArg: ITableAction['type'][0]) {
|
||||
const actions: ITableAction[] = [];
|
||||
for (const action of this.dataActions) {
|
||||
@@ -884,7 +1006,7 @@ export class DeesTable<T> extends DeesElement {
|
||||
const originalColor = target.style.color;
|
||||
target.style.color = 'transparent';
|
||||
const transformedItem = this.displayFunction(itemArg);
|
||||
const initialValue = (transformedItem[key] as unknown as string) || '';
|
||||
const initialValue = ((transformedItem as any)[key] ?? (itemArg as any)[key] ?? '') as string;
|
||||
// Create an input element
|
||||
const input = document.createElement('input');
|
||||
input.type = 'text';
|
@@ -57,7 +57,7 @@ export * from './dees-speechbubble.js';
|
||||
export * from './dees-spinner.js';
|
||||
export * from './dees-statsgrid.js';
|
||||
export * from './dees-stepper.js';
|
||||
export * from './dees-table.js';
|
||||
export * from './dees-table/dees-table.js';
|
||||
export * from './dees-terminal.js';
|
||||
export * from './dees-toast.js';
|
||||
export * from './dees-updater.js';
|
||||
|
Reference in New Issue
Block a user