Skip to content

Commit

Permalink
Added Table, TableItem & ErrorPrompt (#347)
Browse files Browse the repository at this point in the history
* Dialog component created & RNView, RNBoxView was tweaked for Dialog

* Added Components:
- FileDialog
- InputDialog
- ProgressDialog
Edited:
- demo file for testing the dialogs

* Added Compoents:
- ColorDialog
- FontDialog
Edited:
- Dialog (for adding some props)

* updated ProgressBar Example

* newly created components were exported

* New Components:
- Table
- TableItem
Modified:
- demo.tsx

!info: Table & TableItem works initially. But some of the functionality need imperative/useRef approach

* finalized Table & TableItem

* Added ErrorPrompt widget & warnings in Table widget

* exported newly created ErrorPrompt & reverted demo to as it was

* Fixed error prompt message not changing dynamically
  • Loading branch information
KRTirtho committed Apr 6, 2021
1 parent 0515fdb commit f0feda0
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/components/ErrorPrompt/RNErrorPrompt.ts
@@ -0,0 +1,38 @@
import { NodeWidget, QErrorMessage, QErrorMessageSignals } from "@nodegui/nodegui";
import { throwUnsupported } from "../../utils/helpers";
import { RNWidget } from "../config";
import { DialogProps, setDialogProps } from "../Dialog/RNDialog";

export interface ErrorPromptProps extends DialogProps<QErrorMessageSignals> {
message: string;
}

function setErrorPromptProps(widget: RNErrorPrompt, newProps: ErrorPromptProps, oldProps: ErrorPromptProps) {
const setter: ErrorPromptProps = {
set message(message: string) {
widget.showMessage(message);
widget.close();
},
};
Object.assign(setter, newProps);
setDialogProps(widget, newProps, oldProps);
}

export class RNErrorPrompt extends QErrorMessage implements RNWidget {
setProps(newProps: ErrorPromptProps, oldProps: ErrorPromptProps): void {
setErrorPromptProps(this, newProps, oldProps);
}
appendInitialChild(child: NodeWidget<any>): void {
throwUnsupported(this);
}
appendChild(child: NodeWidget<any>): void {
throwUnsupported(this);
}
insertBefore(child: NodeWidget<any>, beforeChild: NodeWidget<any>): void {
throwUnsupported(this);
}
removeChild(child: NodeWidget<any>): void {
throwUnsupported(this);
}
static tagName = "error-prompt";
}
43 changes: 43 additions & 0 deletions src/components/ErrorPrompt/index.ts
@@ -0,0 +1,43 @@
import { Fiber } from "react-reconciler";
import { AppContainer } from "../../reconciler";
import { ComponentConfig, registerComponent } from "../config";
import { RNErrorPrompt, ErrorPromptProps } from "./RNErrorPrompt";

class ErrorPromptConfig extends ComponentConfig {
tagName: string = RNErrorPrompt.tagName;
shouldSetTextContent(nextProps: ErrorPromptProps): boolean {
return false;
}
createInstance(newProps: ErrorPromptProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNErrorPrompt {
const widget = new RNErrorPrompt();
widget.setProps(newProps, { message: "" });
return widget;
}
commitMount(instance: RNErrorPrompt, newProps: ErrorPromptProps, internalInstanceHandle: any): void {
if (newProps.visible !== false && newProps.open !== false) {
instance.show();
}
return;
}
commitUpdate(instance: RNErrorPrompt, updatePayload: any, oldProps: ErrorPromptProps, newProps: ErrorPromptProps, finishedWork: Fiber): void {
instance.setProps(newProps, oldProps);
}
}
/**
* ErrorPrompt inherits the functionality of nodegui's `QErrorMessage`
* @property `message` the message that needs to be displayed
* @example
* ```javascriptreact
* function ErrorApplet(){
* const [open, setOpen] = useState(false);
* return (
* <View>
* <ErrorPrompt open={open} message="Error message!"/>
* <Button text="Error" on={{clicked:()=>setOpen(true)}}/>
* </View>
* )
* }
* ```
*/

export const ErrorPrompt = registerComponent<ErrorPromptProps>(new ErrorPromptConfig());
173 changes: 173 additions & 0 deletions src/components/Table/RNTable.ts
@@ -0,0 +1,173 @@
import { FlexLayout, NodeWidget, QTableWidget, QTableWidgetItem, QTableWidgetSignals, SortOrder } from "@nodegui/nodegui";
import { ViewProps, setViewProps } from "../View/RNView";
import { RNComponent } from "../config";
import { RNTableItem } from "../TableItem/RNTableItem";

export interface CellRange {
row: number;
column: number;
}
interface HorizontalHeader extends Omit<CellRange, "row"> {
item: QTableWidgetItem;
}
interface VerticalHeader extends Omit<CellRange, "column"> {
item: QTableWidgetItem;
}

interface CellWidget extends CellRange {
widget: NodeWidget<any>;
}

interface Sort extends Omit<CellRange, "row"> {
order?: SortOrder;
}

interface ColumnSize extends Omit<CellRange, "row"> {
width: number;
}

interface RowSize extends Omit<CellRange, "column"> {
width: number;
}

export interface TableProps extends ViewProps<QTableWidgetSignals> {
cellRange: CellRange;
horizontalHeaderItems?: HorizontalHeader[];
horizontalHeaderLabels?: string[];
verticalHeaderItems?: VerticalHeader[];
verticalHeaderLabels?: string[];
cellWidgets?: CellWidget[];
currentCell?: CellRange;
sortItems?: Sort;
selectedColumn?: number;
selectedRow?: number;
showGrid?: boolean;
columnWidth?: ColumnSize[];
rowHeight?: RowSize[];
sortingEnabled?: boolean;
hideColumns?: number[];
hideRows?: number[];
}

type CustomTableProps = Omit<TableProps, "cellRange">;

function verifyRanges({ row: rowCount, column: columnCount }: CellRange, { row, column }: Partial<CellRange>) {
if (row && (row < 0 || row > rowCount - 1)) {
console.warn(`Row "${row}" is out of range "${rowCount - 1}"`);
}
if (column && (column < 0 || column > columnCount - 1)) {
console.warn(`Column "${column}" is out range "${columnCount - 1}"`);
}
}

/**
* @ignore
*/
export const setTableProps = (widget: RNTable, newProps: CustomTableProps, oldProps: CustomTableProps) => {
const cellRange: CellRange = {
row: widget.rowCount(),
column: widget.columnCount(),
};

const setter: CustomTableProps = {
set horizontalHeaderItems(items: HorizontalHeader[]) {
for (const item of items) {
widget.setHorizontalHeaderItem(item.column, item.item);
}
},
set horizontalHeaderLabels(labels: string[]) {
widget.setHorizontalHeaderLabels(labels);
},
set verticalHeaderItems(items: VerticalHeader[]) {
for (const { row, item } of items) {
verifyRanges(cellRange, { row });
widget.setVerticalHeaderItem(row, item);
}
},
set verticalHeaderLabels(labels: string[]) {
widget.setVerticalHeaderLabels(labels);
},
set cellWidgets(cellWidgets: CellWidget[]) {
for (const { column, row, widget: cellWidget } of cellWidgets) {
verifyRanges(cellRange, { row, column });
widget.setCellWidget(row, column, cellWidget);
}
},
set currentCell({ row, column }: CellRange) {
verifyRanges(cellRange, { row, column });
widget.setCurrentCell(row, column);
},
set sortItems({ column, order }: Sort) {
verifyRanges(cellRange, { column });
widget.sortItems(column, order);
},
set selectedColumn(column: number) {
verifyRanges(cellRange, { column });
widget.selectColumn(column);
},
set selectedRow(row: number) {
widget.selectRow(row);
},
set showGrid(showGrid: boolean) {
widget.setShowGrid(showGrid);
},
set columnWidth(sizes: ColumnSize[]) {
for (const { column, width } of sizes) {
verifyRanges(cellRange, { column });
widget.setColumnWidth(column, width);
}
},
set rowHeight(sizes: RowSize[]) {
for (const { row, width } of sizes) {
verifyRanges(cellRange, { row });
widget.setRowHeight(row, width);
}
},
set sortingEnabled(sortingEnabled: boolean) {
widget.setSortingEnabled(sortingEnabled);
},
set hideColumns(columns: number[]) {
for (const column of columns) {
verifyRanges(cellRange, { column });
widget.hideColumn(column);
}
},
set hideRows(rows: number[]) {
for (const row of rows) {
verifyRanges(cellRange, { row });
widget.hideRow(row);
}
},
};
Object.assign(setter, newProps);
setViewProps(widget, newProps, oldProps);
};

/**
* @ignore
*/
export class RNTable extends QTableWidget implements RNComponent {
setProps(newProps: CustomTableProps, oldProps: CustomTableProps): void {
setTableProps(this, newProps, oldProps);
}
removeChild(child: NodeWidget<any>): void {
child.close();
}
appendInitialChild(child: RNTableItem): void {
const { cellPosition } = child;
if (!this.layout) {
this.setLayout(new FlexLayout());
}
const row = this.rowCount();
const column = this.columnCount();
verifyRanges({ row, column }, { row: cellPosition[0], column: cellPosition[1] });
this.setItem(cellPosition[0], cellPosition[1], child);
}
appendChild(child: RNTableItem): void {
this.appendInitialChild(child);
}
insertBefore(child: RNTableItem, beforeChild: RNTableItem): void {
this.appendInitialChild(child);
}
static tagName = "table";
}
48 changes: 48 additions & 0 deletions src/components/Table/index.ts
@@ -0,0 +1,48 @@
import { registerComponent, ComponentConfig } from "../config";
import { Fiber } from "react-reconciler";
import { RNTable, TableProps } from "./RNTable";
import { AppContainer } from "../../reconciler";

class TableConfig extends ComponentConfig {
tagName = RNTable.tagName;
shouldSetTextContent(nextProps: TableProps): boolean {
return false;
}
createInstance(newProps: TableProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNTable {
const widget = new RNTable(newProps.cellRange.row, newProps.cellRange.column);
widget.setProps(newProps, {});
return widget;
}
commitMount(instance: RNTable, newProps: TableProps, internalInstanceHandle: any): void {
if (newProps.visible !== false) {
instance.show();
}
return;
}
commitUpdate(instance: RNTable, updatePayload: any, oldProps: TableProps, newProps: TableProps, finishedWork: Fiber): void {
instance.setProps(newProps, oldProps);
}
}
/**
* React implementation of nodegui's [QTableWidget](https://docs.nodegui.org/docs/api/generated/classes/qtablewidget/)
* @property `cellRange` define the number of rows & columns to create
* @example
* ```javascriptreact
* return (
* <Table
cellRange={{ row: 2, column: 2 }} // 2 x 2 = 4 cells
style="flex: 1;"
horizontalHeaderLabels={["What", "How", "When"]}
verticalHeaderLabels={["yes", "this", "later"]}
hideRows={[0]} //hides 0 indexed rows
>
<TableItem cellPosition={[0, 0]} text="1" toolTip="Tooltip"/>
<TableItem cellPosition={[0, 1]} text="2"/>
<TableItem cellPosition={[1, 0]} text="3"/>
<TableItem cellPosition={[1, 1]} text="4"/>
</Table>
* )
* ```
*/

export const Table = registerComponent<TableProps>(new TableConfig());

0 comments on commit f0feda0

Please sign in to comment.