226 lines
5.8 KiB
TypeScript
226 lines
5.8 KiB
TypeScript
import type { Table, TableData } from "@sealcode/jdd";
|
|
import { isTableHeader } from "@sealcode/jdd";
|
|
import type { StatefulPage } from "@sealcode/sealgen";
|
|
import type { BaseContext } from "koa";
|
|
import { TempstreamJSX } from "tempstream";
|
|
import { makeJDDContext } from "../../jdd-context.js";
|
|
import { ComponentInput } from "./component-input.js";
|
|
import type { ComponentPreviewActions } from "./component-preview-actions.js";
|
|
import type { JDDPageState } from "./jdd-page.js";
|
|
import add_column_right_icon from "./table-add-column-right.svg";
|
|
import add_row_below_icon from "./table-add-row-below.svg";
|
|
import add_column_header_icon from "./table-add-row-header-below.svg";
|
|
import delete_column_icon from "./table-delete-column.svg";
|
|
import delete_row_icon from "./table-delete-row.svg";
|
|
import move_column_right_icon from "./table-move-column-right.svg";
|
|
import move_row_down_icon from "./table-move-row-down.svg";
|
|
|
|
export async function ComponentInputTable<
|
|
State extends JDDPageState,
|
|
CellType,
|
|
HeaderType
|
|
>({
|
|
state,
|
|
arg_path,
|
|
ctx,
|
|
arg,
|
|
value,
|
|
page,
|
|
}: {
|
|
state: State;
|
|
ctx: BaseContext;
|
|
arg_path: string[];
|
|
arg: Table<CellType, HeaderType>;
|
|
value: TableData<CellType, HeaderType>;
|
|
page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
|
|
}): Promise<import("stream").Readable> {
|
|
if (!value) {
|
|
value = await arg.getEmptyValue(makeJDDContext(ctx));
|
|
}
|
|
|
|
return (
|
|
<fieldset>
|
|
<legend>{arg_path.at(-1)}</legend>
|
|
<div>
|
|
<table style="position: relative; /* necessary for sticky th*/">
|
|
<tbody>
|
|
<tr>
|
|
<td></td>
|
|
{[...Array(arg.getColumnsCount(value)).keys()].map(
|
|
(column_index) => (
|
|
<th class="sticky sticky--top subdued">
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "remove_table_column",
|
|
label: "Remove column",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${delete_column_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
column_index
|
|
)}
|
|
{column_index >= arg.getColumnsCount(value) - 1
|
|
? ""
|
|
: page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "move_table_column_right",
|
|
label: "Move column to the right",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${move_column_right_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
column_index
|
|
)}
|
|
</th>
|
|
)
|
|
)}
|
|
</tr>
|
|
{value.rows.map((row, row_index) => (
|
|
<tr>
|
|
<td class="sticky sticky--left subdued">
|
|
<div style="display: flex; flex-flow: column; row-gap: 5px;">
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "remove_table_row",
|
|
label: "Remove row",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${delete_row_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
row_index
|
|
)}
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "move_table_row_down",
|
|
label: "Move this row down",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${move_row_down_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
row_index
|
|
)}
|
|
</div>
|
|
</td>
|
|
{isTableHeader(row) ? (
|
|
<th colspan={arg.getColumnsCount(value).toString()}>
|
|
<ComponentInput
|
|
{...{
|
|
state,
|
|
ctx,
|
|
arg_path: [
|
|
...arg_path,
|
|
"rows",
|
|
row_index.toString(),
|
|
"header_content",
|
|
],
|
|
arg: arg.header_type,
|
|
value: row.header_content,
|
|
page,
|
|
}}
|
|
/>
|
|
</th>
|
|
) : (
|
|
row.cells.map((cell, cell_index) => (
|
|
<td>
|
|
<ComponentInput
|
|
{...{
|
|
ctx,
|
|
state,
|
|
arg_path: [
|
|
...arg_path,
|
|
"rows",
|
|
row_index.toString(),
|
|
"cells",
|
|
cell_index.toString(),
|
|
],
|
|
arg: arg.cell_type,
|
|
value: cell,
|
|
page,
|
|
}}
|
|
/>
|
|
</td>
|
|
))
|
|
)}
|
|
{row_index == 0 ? (
|
|
<td
|
|
class="subdued"
|
|
rowspan={value.rows.length.toString()}
|
|
>
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "add_table_column",
|
|
label: "Add column",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${add_column_right_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path
|
|
)}
|
|
</td>
|
|
) : (
|
|
""
|
|
)}
|
|
</tr>
|
|
))}
|
|
<tr>
|
|
<td
|
|
class="subdued"
|
|
colspan={(arg.getColumnsCount(value) + 1).toString()}
|
|
>
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "add_table_row",
|
|
label: "Add table row",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${add_row_below_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
arg.getColumnsCount(value)
|
|
)}
|
|
{page.makeActionButton(
|
|
state,
|
|
{
|
|
action: "add_table_row",
|
|
label: "Add table header",
|
|
content: /* HTML */ `<img
|
|
width="20"
|
|
height="20"
|
|
src="${add_column_header_icon.url}"
|
|
/>`,
|
|
},
|
|
arg_path,
|
|
arg.getColumnsCount(value),
|
|
"header"
|
|
)}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</fieldset>
|
|
);
|
|
}
|