(value: unknown, fallback: T[]): T[] {
if (typeof value !== 'string' || !value.trim()) {
return fallback;
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed) ? (parsed as T[]) : fallback;
} catch {
return fallback;
}
}
function parseColumns(value: unknown): DataTableColumn[] {
if (typeof value !== 'string' || !value.trim()) {
return DEFAULT_COLUMNS;
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? (parsed as DataTableColumn[])
: DEFAULT_COLUMNS;
} catch {
return DEFAULT_COLUMNS;
}
}
function parseFilters(value: unknown): DataTableFilters {
if (typeof value !== 'string' || !value.trim()) {
return {};
}
try {
const parsed = JSON.parse(value);
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
? (parsed as DataTableFilters)
: {};
} catch {
return {};
}
}
function handleSort(event: Event, handlers?: PlaygroundPreviewHandlers): void {
if (!handlers) {
return;
}
const detail = (
event as CustomEvent<{ sortField: string; sortOrder: number }>
).detail;
handlers.onPropChange('sortField', detail.sortField);
handlers.onPropChange('sortOrder', String(detail.sortOrder));
handlers.onPropChange('first', '0');
}
function handlePage(event: Event, handlers?: PlaygroundPreviewHandlers): void {
if (!handlers) {
return;
}
const detail = (event as CustomEvent<{ first: number }>).detail;
handlers.onPropChange('first', String(detail.first));
}
function handleFilter(
event: Event,
handlers?: PlaygroundPreviewHandlers,
): void {
if (!handlers) {
return;
}
const detail = (event as CustomEvent<{ filters: DataTableFilters }>).detail;
handlers.onPropChange('filters', JSON.stringify(detail.filters, null, 2));
handlers.onPropChange('first', '0');
}
function renderPreview(
props: PlaygroundProps,
handlers?: PlaygroundPreviewHandlers,
): TemplateResult {
return html`
(props.value, DEFAULT_VALUE)}
.columns=${parseColumns(props.columns)}
.filters=${parseFilters(props.filters)}
data-key=${whenString(props.dataKey)}
rows=${Number(props.rows)}
first=${Number(props.first)}
sort-field=${whenString(props.sortField)}
sort-order=${Number(props.sortOrder) as -1 | 0 | 1}
empty-message=${whenString(props.emptyMessage)}
data-table-class=${whenString(props.dataTableClass)}
size=${whenString(props.size)}
nui-type=${whenString(props.nuiType)}
?paginator=${whenBoolean(props.paginator)}
?filter=${whenBoolean(props.filter)}
?show-headers=${whenBoolean(props.showHeaders)}
?striped-rows=${whenBoolean(props.stripedRows)}
?row-hover=${whenBoolean(props.rowHover)}
?loading=${whenBoolean(props.loading)}
?unstyled=${whenBoolean(props.unstyled)}
@sort=${(event: Event) => handleSort(event, handlers)}
@page=${(event: Event) => handlePage(event, handlers)}
@filter=${(event: Event) => handleFilter(event, handlers)}
>
`;
}
export const nuiDataTablePlayground: PlaygroundDefinition = {
tag: 'nui-data-table',
label: 'Data Table',
description:
'Tabular data with auto columns, sorting, column filters, pagination, striped rows, and row hover.',
defaults: NUI_DATA_TABLE_DEFAULTS,
controls: CONTROLS,
renderPreview,
getPreviewClass: () => 'is-fluid',
formatUsage: (props) => {
const {
value: _value,
columns: _columns,
filters: _filters,
...usageProps
} = props;
return formatUsageFromDefaults(
'nui-data-table',
usageProps,
NUI_DATA_TABLE_DEFAULTS,
ATTRIBUTE_NAMES,
);
},
};