Skip to content

Commit

Permalink
Major refactor almost complete. Row headers still outstanding, but th…
Browse files Browse the repository at this point in the history
…at's not super important
  • Loading branch information
set authored and J-Cake committed Nov 6, 2024
1 parent e7aba64 commit cc34110
Show file tree
Hide file tree
Showing 13 changed files with 549 additions and 681 deletions.
11 changes: 11 additions & 0 deletions layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
align-items: center;
}

/* Defined by the spreadsheet, contains the table widget */
.spreadsheet {
grid-area: table;

display: grid;

grid-template-columns: subgrid;
grid-template-rows: subgrid;
}

/* Wrapper **within** the table component */
.table-container {
grid-area: table;

Expand Down
4 changes: 2 additions & 2 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Spreadsheet from "./viewport.js";
import SpreadsheetView from "./spreadsheet.js";
import { icons } from 'lucide-react';

export type Tool = {
Expand All @@ -8,7 +8,7 @@ export type Tool = {
} & (Button | ViewportOptions);
export type Button = {
type: 'button',
onClick: (sheet: Spreadsheet) => void,
onClick: (sheet: SpreadsheetView) => void,
};
export type ViewportOptions = {
type: 'viewport',
Expand Down
99 changes: 0 additions & 99 deletions src/components/table.old.tsx

This file was deleted.

62 changes: 52 additions & 10 deletions src/components/table.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import React from 'react';
import useResizeObserver from '@react-hook/resize-observer';

import {StateHolder} from "../spreadsheet.js";
import {DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_HEIGHT} from "./table.old.js";
import {DocumentProperties, Value} from "../csv.js";
import {StateHolder} from "../main.js";
import SelectionIndicator, {Selection} from "../selection.js";


export const DEFAULT_COLUMN_WIDTH = 128;
export const MIN_COLUMN_WIDTH = 24;

export const DEFAULT_ROW_HEIGHT = 28;
export const MIN_ROW_HEIGHT = 6;

// export type ColumnHeader = () => React.ReactNode;
export interface ColumnHeader {
title: string,
width: number,
index: number,

render: (col: ColumnHeader) => React.ReactNode
}
Expand All @@ -19,21 +28,28 @@ interface TableRow {
}

export interface TableProps<Row extends TableRow> {
children: { data: Row[] },
children: {
data: Row[],
selection?: Selection.CellGroup[]
},
sheet: StateHolder,

columns: Record<string, ColumnHeader>
renderColumn: (col: ColumnHeader) => React.ReactNode,
}

export default function Table<Row extends TableRow>(props: TableProps<Row>) {
const [columns, setColumns] = React.useState<ColumnHeader[]>(Object.values(props.columns));
const [columns, setColumns] = React.useState<ColumnHeader[]>([]);

React.useEffect(() => setColumns(props.sheet.documentProperties.columnTitles.map((col, colIndex) => ({
title: col,
width: columns?.[colIndex]?.width ?? DEFAULT_COLUMN_WIDTH,
render: props.renderColumn,
index: colIndex
}))), [props]);

const ref = React.useRef<HTMLDivElement | null>(null);

const resizeColumn = (colIndex: number, width: number) => setColumns(prev => prev.with(colIndex, {
...prev[colIndex],
width
}));
const resizeColumn = (colIndex: number, width: number) => setColumns(prev => prev.with(colIndex, { ...prev[colIndex], width }));

return <section
className={"table-widget"}
Expand Down Expand Up @@ -72,10 +88,12 @@ export default function Table<Row extends TableRow>(props: TableProps<Row>) {
gridRow: rowIndex + 2,
gridColumn: colIndex + 2
}}>
{row.data[col.title]()}
{row.data[col.title]?.() ?? ""}
</div>)}
</>)}

{props.children.selection ? <SelectionIndicator selection={props.children.selection} sheet={props.sheet} /> : null}

</section>
</section>;
}
Expand All @@ -87,6 +105,8 @@ export function TableHeaderCell(props: {
}) {
const ref = React.useRef<HTMLDivElement>(null);

// This thing apparently isn't a function... Actually it is
// @ts-ignore
useResizeObserver(ref, e => props.onResize(e.contentRect));

return <div
Expand All @@ -102,4 +122,26 @@ export function TableHeaderCell(props: {
{props.header.render(props.header)}

</div>
}

export function columnHeadersFromDocument(document: StateHolder, render: (col: ColumnHeader) => React.ReactNode): Record<string, ColumnHeader> {
return Object.fromEntries(document.documentProperties.columnTitles.map((col, colIndex) => [col, {
title: col,
width: document.documentProperties.columnWidths[colIndex],
index: colIndex,
render
}]))
}

export function mkTableCell<Row extends TableRow>(document: StateHolder, child: (col: Value, addr: Selection.Cell) => React.ReactNode, selection?: Selection.CellGroup[]): TableProps<Row>["children"] {
return {
data: document.doc.raw.map((row, rowIndex) => ({
id: rowIndex,
data: Object.fromEntries(row.map((col, colIndex) => [
document.documentProperties.columnTitles[colIndex],
() => child(col, { col: colIndex, row: rowIndex })
]))
})) as Row[],
selection
}
}
3 changes: 1 addition & 2 deletions src/components/toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import * as icons from 'lucide-react';

import Spreadsheet from "../viewport.js";
import {Settings} from "../settings/settingsTab.js";
import Tools, {Tool} from '../actions.js';
import {StateHolder} from "../spreadsheet.js";
import {StateHolder} from "../main.js";

export default function Toolbar(props: { settings: Settings, sheet: StateHolder }) {
return <div className={"flex toolbar"}>
Expand Down
2 changes: 1 addition & 1 deletion src/components/valueEditor.old.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {Value} from "../csv.js";
import {StateHolder} from "../spreadsheet.js";
import {StateHolder} from "../main.js";

export function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>, spreadsheet: StateHolder) {
if (e.key == "Enter" || e.key == "Tab")
Expand Down
112 changes: 112 additions & 0 deletions src/contextMenu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from "react";
import * as obs from "obsidian";

import {ColumnHeader} from "./components/table.js";
import {renameColumn} from "./renameColumn.js";
import {StateHolder} from "./main.js";

export function columnContextMenu(e: React.MouseEvent, col: ColumnHeader, sheet: StateHolder) {
const menu = new obs.Menu();

menu.addItem(item => item
.setIcon("pencil")
.setTitle("Rename Column")
.onClick(_ => renameColumn(sheet, col)));

menu.addItem(item => {
const submenu = (item
.setIcon("languages")
.setTitle("Set column format") as any as { setSubmenu: () => obs.Menu })
.setSubmenu();

// for (const [key, ren] of Object.entries(renderers))
// submenu.addItem(item => item
// .setIcon(ren.friendlyName.icon ?? null)
// .setTitle(ren.friendlyName.label)
// .onClick(_ => sheet.editFormat(col, key)));
});

menu.addSeparator();

menu.addItem(item => item
.setIcon("arrow-left-to-line")
.setTitle("Swap column leftwards"));
menu.addItem(item => item
.setIcon("arrow-right-to-line")
.setTitle("Swap column rightwards"));

menu.addSeparator();

menu.addItem(item => item
.setIcon("list-plus")
.setTitle("Insert column before")
.onClick(_ => sheet.insertCol(col.index - 1)));
menu.addItem(item => item
.setIcon("list-plus")
.setTitle("Insert column after")
.onClick(_ => sheet.insertCol(col.index)));

menu.addSeparator();

menu.addItem(item => item
.setIcon("trash-2")
.setTitle("Delete Column")
.onClick(e => sheet.removeCol(col.index)));

menu.addSeparator();

menu.addItem(item => item
.setIcon("arrow-up-narrow-wide")
.setTitle(`Sort by ${sheet.documentProperties.columnTitles[col.index]}`)
.onClick(e => void 0));

menu.addItem(item => item
.setIcon("arrow-down-wide-narrow")
.setTitle(`Sort by ${sheet.documentProperties.columnTitles[col.index]} (Descending)`)
.onClick(e => void 0));

menu.addItem(item => item
.setIcon("filter")
.setTitle(`Filter on ${sheet.documentProperties.columnTitles[col.index]}`)
.onClick(e => void 0));

menu.addItem(item => item
.setIcon("group")
.setTitle(`Group by ${sheet.documentProperties.columnTitles[col.index]}`)
.onClick(e => void 0));

menu.showAtMouseEvent(e.nativeEvent);
}

export function rowContextMenu(e: React.MouseEvent, row: number, sheet: StateHolder) {
sheet.state.dispatch('change-active', {activeCell: null});

const menu = new obs.Menu();

menu.addItem(item => item
.setIcon("arrow-up-to-line")
.setTitle("Swap row upwards"));
menu.addItem(item => item
.setIcon("arrow-down-to-line")
.setTitle("Swap row downwards"));

menu.addSeparator();

menu.addItem(item => item
.setIcon("list-plus")
.setTitle("Insert row above")
.onClick(_ => sheet.insertRow(row - 1)));
menu.addItem(item => item
.setIcon("list-plus")
.setTitle("Insert row below")
.onClick(_ => sheet.insertRow(row)));

menu.addSeparator();

menu.addItem(item => item
.setIcon("trash-2")
.setTitle("Delete Row")
.onClick(e => sheet.removeRow(row)));

menu.showAtMouseEvent(e.nativeEvent);
}
Loading

0 comments on commit cc34110

Please sign in to comment.