Skip to content

Commit f0feda0

Browse files
authored
Added Table, TableItem & ErrorPrompt (#347)
* 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
1 parent 0515fdb commit f0feda0

File tree

7 files changed

+448
-0
lines changed

7 files changed

+448
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { NodeWidget, QErrorMessage, QErrorMessageSignals } from "@nodegui/nodegui";
2+
import { throwUnsupported } from "../../utils/helpers";
3+
import { RNWidget } from "../config";
4+
import { DialogProps, setDialogProps } from "../Dialog/RNDialog";
5+
6+
export interface ErrorPromptProps extends DialogProps<QErrorMessageSignals> {
7+
message: string;
8+
}
9+
10+
function setErrorPromptProps(widget: RNErrorPrompt, newProps: ErrorPromptProps, oldProps: ErrorPromptProps) {
11+
const setter: ErrorPromptProps = {
12+
set message(message: string) {
13+
widget.showMessage(message);
14+
widget.close();
15+
},
16+
};
17+
Object.assign(setter, newProps);
18+
setDialogProps(widget, newProps, oldProps);
19+
}
20+
21+
export class RNErrorPrompt extends QErrorMessage implements RNWidget {
22+
setProps(newProps: ErrorPromptProps, oldProps: ErrorPromptProps): void {
23+
setErrorPromptProps(this, newProps, oldProps);
24+
}
25+
appendInitialChild(child: NodeWidget<any>): void {
26+
throwUnsupported(this);
27+
}
28+
appendChild(child: NodeWidget<any>): void {
29+
throwUnsupported(this);
30+
}
31+
insertBefore(child: NodeWidget<any>, beforeChild: NodeWidget<any>): void {
32+
throwUnsupported(this);
33+
}
34+
removeChild(child: NodeWidget<any>): void {
35+
throwUnsupported(this);
36+
}
37+
static tagName = "error-prompt";
38+
}

src/components/ErrorPrompt/index.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Fiber } from "react-reconciler";
2+
import { AppContainer } from "../../reconciler";
3+
import { ComponentConfig, registerComponent } from "../config";
4+
import { RNErrorPrompt, ErrorPromptProps } from "./RNErrorPrompt";
5+
6+
class ErrorPromptConfig extends ComponentConfig {
7+
tagName: string = RNErrorPrompt.tagName;
8+
shouldSetTextContent(nextProps: ErrorPromptProps): boolean {
9+
return false;
10+
}
11+
createInstance(newProps: ErrorPromptProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNErrorPrompt {
12+
const widget = new RNErrorPrompt();
13+
widget.setProps(newProps, { message: "" });
14+
return widget;
15+
}
16+
commitMount(instance: RNErrorPrompt, newProps: ErrorPromptProps, internalInstanceHandle: any): void {
17+
if (newProps.visible !== false && newProps.open !== false) {
18+
instance.show();
19+
}
20+
return;
21+
}
22+
commitUpdate(instance: RNErrorPrompt, updatePayload: any, oldProps: ErrorPromptProps, newProps: ErrorPromptProps, finishedWork: Fiber): void {
23+
instance.setProps(newProps, oldProps);
24+
}
25+
}
26+
/**
27+
* ErrorPrompt inherits the functionality of nodegui's `QErrorMessage`
28+
* @property `message` the message that needs to be displayed
29+
* @example
30+
* ```javascriptreact
31+
* function ErrorApplet(){
32+
* const [open, setOpen] = useState(false);
33+
* return (
34+
* <View>
35+
* <ErrorPrompt open={open} message="Error message!"/>
36+
* <Button text="Error" on={{clicked:()=>setOpen(true)}}/>
37+
* </View>
38+
* )
39+
* }
40+
* ```
41+
*/
42+
43+
export const ErrorPrompt = registerComponent<ErrorPromptProps>(new ErrorPromptConfig());

src/components/Table/RNTable.ts

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { FlexLayout, NodeWidget, QTableWidget, QTableWidgetItem, QTableWidgetSignals, SortOrder } from "@nodegui/nodegui";
2+
import { ViewProps, setViewProps } from "../View/RNView";
3+
import { RNComponent } from "../config";
4+
import { RNTableItem } from "../TableItem/RNTableItem";
5+
6+
export interface CellRange {
7+
row: number;
8+
column: number;
9+
}
10+
interface HorizontalHeader extends Omit<CellRange, "row"> {
11+
item: QTableWidgetItem;
12+
}
13+
interface VerticalHeader extends Omit<CellRange, "column"> {
14+
item: QTableWidgetItem;
15+
}
16+
17+
interface CellWidget extends CellRange {
18+
widget: NodeWidget<any>;
19+
}
20+
21+
interface Sort extends Omit<CellRange, "row"> {
22+
order?: SortOrder;
23+
}
24+
25+
interface ColumnSize extends Omit<CellRange, "row"> {
26+
width: number;
27+
}
28+
29+
interface RowSize extends Omit<CellRange, "column"> {
30+
width: number;
31+
}
32+
33+
export interface TableProps extends ViewProps<QTableWidgetSignals> {
34+
cellRange: CellRange;
35+
horizontalHeaderItems?: HorizontalHeader[];
36+
horizontalHeaderLabels?: string[];
37+
verticalHeaderItems?: VerticalHeader[];
38+
verticalHeaderLabels?: string[];
39+
cellWidgets?: CellWidget[];
40+
currentCell?: CellRange;
41+
sortItems?: Sort;
42+
selectedColumn?: number;
43+
selectedRow?: number;
44+
showGrid?: boolean;
45+
columnWidth?: ColumnSize[];
46+
rowHeight?: RowSize[];
47+
sortingEnabled?: boolean;
48+
hideColumns?: number[];
49+
hideRows?: number[];
50+
}
51+
52+
type CustomTableProps = Omit<TableProps, "cellRange">;
53+
54+
function verifyRanges({ row: rowCount, column: columnCount }: CellRange, { row, column }: Partial<CellRange>) {
55+
if (row && (row < 0 || row > rowCount - 1)) {
56+
console.warn(`Row "${row}" is out of range "${rowCount - 1}"`);
57+
}
58+
if (column && (column < 0 || column > columnCount - 1)) {
59+
console.warn(`Column "${column}" is out range "${columnCount - 1}"`);
60+
}
61+
}
62+
63+
/**
64+
* @ignore
65+
*/
66+
export const setTableProps = (widget: RNTable, newProps: CustomTableProps, oldProps: CustomTableProps) => {
67+
const cellRange: CellRange = {
68+
row: widget.rowCount(),
69+
column: widget.columnCount(),
70+
};
71+
72+
const setter: CustomTableProps = {
73+
set horizontalHeaderItems(items: HorizontalHeader[]) {
74+
for (const item of items) {
75+
widget.setHorizontalHeaderItem(item.column, item.item);
76+
}
77+
},
78+
set horizontalHeaderLabels(labels: string[]) {
79+
widget.setHorizontalHeaderLabels(labels);
80+
},
81+
set verticalHeaderItems(items: VerticalHeader[]) {
82+
for (const { row, item } of items) {
83+
verifyRanges(cellRange, { row });
84+
widget.setVerticalHeaderItem(row, item);
85+
}
86+
},
87+
set verticalHeaderLabels(labels: string[]) {
88+
widget.setVerticalHeaderLabels(labels);
89+
},
90+
set cellWidgets(cellWidgets: CellWidget[]) {
91+
for (const { column, row, widget: cellWidget } of cellWidgets) {
92+
verifyRanges(cellRange, { row, column });
93+
widget.setCellWidget(row, column, cellWidget);
94+
}
95+
},
96+
set currentCell({ row, column }: CellRange) {
97+
verifyRanges(cellRange, { row, column });
98+
widget.setCurrentCell(row, column);
99+
},
100+
set sortItems({ column, order }: Sort) {
101+
verifyRanges(cellRange, { column });
102+
widget.sortItems(column, order);
103+
},
104+
set selectedColumn(column: number) {
105+
verifyRanges(cellRange, { column });
106+
widget.selectColumn(column);
107+
},
108+
set selectedRow(row: number) {
109+
widget.selectRow(row);
110+
},
111+
set showGrid(showGrid: boolean) {
112+
widget.setShowGrid(showGrid);
113+
},
114+
set columnWidth(sizes: ColumnSize[]) {
115+
for (const { column, width } of sizes) {
116+
verifyRanges(cellRange, { column });
117+
widget.setColumnWidth(column, width);
118+
}
119+
},
120+
set rowHeight(sizes: RowSize[]) {
121+
for (const { row, width } of sizes) {
122+
verifyRanges(cellRange, { row });
123+
widget.setRowHeight(row, width);
124+
}
125+
},
126+
set sortingEnabled(sortingEnabled: boolean) {
127+
widget.setSortingEnabled(sortingEnabled);
128+
},
129+
set hideColumns(columns: number[]) {
130+
for (const column of columns) {
131+
verifyRanges(cellRange, { column });
132+
widget.hideColumn(column);
133+
}
134+
},
135+
set hideRows(rows: number[]) {
136+
for (const row of rows) {
137+
verifyRanges(cellRange, { row });
138+
widget.hideRow(row);
139+
}
140+
},
141+
};
142+
Object.assign(setter, newProps);
143+
setViewProps(widget, newProps, oldProps);
144+
};
145+
146+
/**
147+
* @ignore
148+
*/
149+
export class RNTable extends QTableWidget implements RNComponent {
150+
setProps(newProps: CustomTableProps, oldProps: CustomTableProps): void {
151+
setTableProps(this, newProps, oldProps);
152+
}
153+
removeChild(child: NodeWidget<any>): void {
154+
child.close();
155+
}
156+
appendInitialChild(child: RNTableItem): void {
157+
const { cellPosition } = child;
158+
if (!this.layout) {
159+
this.setLayout(new FlexLayout());
160+
}
161+
const row = this.rowCount();
162+
const column = this.columnCount();
163+
verifyRanges({ row, column }, { row: cellPosition[0], column: cellPosition[1] });
164+
this.setItem(cellPosition[0], cellPosition[1], child);
165+
}
166+
appendChild(child: RNTableItem): void {
167+
this.appendInitialChild(child);
168+
}
169+
insertBefore(child: RNTableItem, beforeChild: RNTableItem): void {
170+
this.appendInitialChild(child);
171+
}
172+
static tagName = "table";
173+
}

src/components/Table/index.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { registerComponent, ComponentConfig } from "../config";
2+
import { Fiber } from "react-reconciler";
3+
import { RNTable, TableProps } from "./RNTable";
4+
import { AppContainer } from "../../reconciler";
5+
6+
class TableConfig extends ComponentConfig {
7+
tagName = RNTable.tagName;
8+
shouldSetTextContent(nextProps: TableProps): boolean {
9+
return false;
10+
}
11+
createInstance(newProps: TableProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNTable {
12+
const widget = new RNTable(newProps.cellRange.row, newProps.cellRange.column);
13+
widget.setProps(newProps, {});
14+
return widget;
15+
}
16+
commitMount(instance: RNTable, newProps: TableProps, internalInstanceHandle: any): void {
17+
if (newProps.visible !== false) {
18+
instance.show();
19+
}
20+
return;
21+
}
22+
commitUpdate(instance: RNTable, updatePayload: any, oldProps: TableProps, newProps: TableProps, finishedWork: Fiber): void {
23+
instance.setProps(newProps, oldProps);
24+
}
25+
}
26+
/**
27+
* React implementation of nodegui's [QTableWidget](https://docs.nodegui.org/docs/api/generated/classes/qtablewidget/)
28+
* @property `cellRange` define the number of rows & columns to create
29+
* @example
30+
* ```javascriptreact
31+
* return (
32+
* <Table
33+
cellRange={{ row: 2, column: 2 }} // 2 x 2 = 4 cells
34+
style="flex: 1;"
35+
horizontalHeaderLabels={["What", "How", "When"]}
36+
verticalHeaderLabels={["yes", "this", "later"]}
37+
hideRows={[0]} //hides 0 indexed rows
38+
>
39+
<TableItem cellPosition={[0, 0]} text="1" toolTip="Tooltip"/>
40+
<TableItem cellPosition={[0, 1]} text="2"/>
41+
<TableItem cellPosition={[1, 0]} text="3"/>
42+
<TableItem cellPosition={[1, 1]} text="4"/>
43+
</Table>
44+
* )
45+
* ```
46+
*/
47+
48+
export const Table = registerComponent<TableProps>(new TableConfig());

0 commit comments

Comments
 (0)