Skip to content

Commit 45ccc31

Browse files
authored
Add List and ListItem using QListWidget and QListWidgetItem (#364)
``` <List> <ListItem text="NodeGui is great" /> <ListItem text="This item has a child"> <View> <Text>Hello World</Text> </View> </ListItem> </List> ```
1 parent 0574712 commit 45ccc31

File tree

5 files changed

+202
-0
lines changed

5 files changed

+202
-0
lines changed

src/components/List/RNList.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { FlexLayout, QListWidget, QListWidgetSignals } from "@nodegui/nodegui";
2+
import { ViewProps, setViewProps } from "../View/RNView";
3+
import { RNComponent } from "../config";
4+
import { RNListItem } from "../ListItem/RNListItem";
5+
6+
7+
export interface ListProps extends ViewProps<QListWidgetSignals> {
8+
}
9+
10+
type CustomListProps = ListProps;
11+
12+
13+
/**
14+
* @ignore
15+
*/
16+
export const setListProps = (widget: RNList, newProps: CustomListProps, oldProps: CustomListProps) => {
17+
18+
const setter: CustomListProps = {
19+
};
20+
Object.assign(setter, newProps);
21+
setViewProps(widget, newProps, oldProps);
22+
};
23+
24+
/**
25+
* @ignore
26+
*/
27+
export class RNList extends QListWidget implements RNComponent {
28+
setProps(newProps: CustomListProps, oldProps: CustomListProps): void {
29+
setListProps(this, newProps, oldProps);
30+
}
31+
removeChild(child: RNListItem): void {
32+
const row = this.row(child);
33+
this.takeItem(row);
34+
}
35+
appendInitialChild(child: RNListItem): void {
36+
this.appendChild(child);
37+
}
38+
appendChild(child: RNListItem): void {
39+
if (!this.layout) {
40+
this.setLayout(new FlexLayout());
41+
}
42+
43+
if (!(child instanceof RNListItem)) {
44+
throw new Error("Children of list should be of type ListItem");
45+
}
46+
47+
this.addItem(child);
48+
if (child.actualListItemWidget) {
49+
child.setSizeHint(child.actualListItemWidget.size());
50+
this.setItemWidget(child, child.actualListItemWidget);
51+
}
52+
}
53+
insertBefore(child: RNListItem, beforeChild: RNListItem): void {
54+
const row = this.row(beforeChild);
55+
this.insertItem(row, child);
56+
}
57+
static tagName = "list";
58+
}

src/components/List/index.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { registerComponent, ComponentConfig } from "../config";
2+
import { Fiber } from "react-reconciler";
3+
import { RNList, ListProps } from "./RNList";
4+
import { AppContainer } from "../../reconciler";
5+
6+
class ListConfig extends ComponentConfig {
7+
tagName = RNList.tagName;
8+
shouldSetTextContent(nextProps: ListProps): boolean {
9+
return false;
10+
}
11+
createInstance(newProps: ListProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNList {
12+
const widget = new RNList();
13+
widget.setProps(newProps, {});
14+
return widget;
15+
}
16+
commitMount(instance: RNList, newProps: ListProps, internalInstanceHandle: any): void {
17+
if (newProps.visible !== false) {
18+
instance.show();
19+
}
20+
return;
21+
}
22+
commitUpdate(instance: RNList, updatePayload: any, oldProps: ListProps, newProps: ListProps, finishedWork: Fiber): void {
23+
instance.setProps(newProps, oldProps);
24+
}
25+
}
26+
/**
27+
* React implementation of nodegui's [QListWidget](https://docs.nodegui.org/docs/api/generated/classes/qlistwidget/)
28+
* @example
29+
* ```javascriptreact
30+
* return (
31+
* <List>
32+
<ListItem text="NodeGui is great" />
33+
<ListItem text="This item has a child">
34+
<View>
35+
<Text>Hello World</Text>
36+
</View>
37+
</ListItem>
38+
</List>
39+
* )
40+
* ```
41+
*/
42+
43+
export const List = registerComponent<ListProps>(new ListConfig());

src/components/ListItem/RNListItem.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { NodeWidget, QListWidgetItem, QIcon } from "@nodegui/nodegui";
2+
import { RNComponent } from "../config";
3+
4+
export interface ListItemProps {
5+
title?: string;
6+
icon?: QIcon;
7+
}
8+
9+
/**
10+
* @ignore
11+
*/
12+
export const setListItemProps = (
13+
widget: RNListItem,
14+
newProps: ListItemProps,
15+
oldProps: ListItemProps
16+
) => {
17+
const setter: ListItemProps = {
18+
set title(text: string) {
19+
widget.setText(text);
20+
},
21+
set icon(qicon: QIcon) {
22+
widget.setIcon(qicon);
23+
}
24+
};
25+
Object.assign(setter, newProps);
26+
};
27+
28+
/**
29+
* @ignore
30+
*/
31+
export class RNListItem extends QListWidgetItem implements RNComponent {
32+
native: any;
33+
actualListItemWidget?: NodeWidget<any>;
34+
35+
setProps(newProps: ListItemProps, oldProps: ListItemProps): void {
36+
setListItemProps(this, newProps, oldProps);
37+
}
38+
appendInitialChild(child: NodeWidget<any>): void {
39+
if (this.actualListItemWidget) {
40+
throw new Error("ListItem can have only one child");
41+
}
42+
this.actualListItemWidget = child;
43+
}
44+
appendChild(child: NodeWidget<any>): void {
45+
this.appendInitialChild(child);
46+
}
47+
insertBefore(child: NodeWidget<any>, beforeChild: NodeWidget<any>): void {
48+
this.appendInitialChild(child);
49+
}
50+
removeChild(child: NodeWidget<any>): void {
51+
if (child) {
52+
child.close();
53+
}
54+
if (this.actualListItemWidget) {
55+
delete this.actualListItemWidget;
56+
}
57+
}
58+
static tagName: string = "listitem";
59+
}

src/components/ListItem/index.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Fiber } from "react-reconciler";
2+
import { registerComponent, ComponentConfig } from "../config";
3+
import { RNListItem, ListItemProps } from "./RNListItem";
4+
import { AppContainer } from "../../reconciler";
5+
6+
class ListItemConfig extends ComponentConfig {
7+
tagName = RNListItem.tagName;
8+
shouldSetTextContent(nextProps: ListItemProps): boolean {
9+
return false;
10+
}
11+
createInstance(
12+
newProps: ListItemProps,
13+
rootInstance: AppContainer,
14+
context: any,
15+
workInProgress: Fiber
16+
): RNListItem {
17+
const item = new RNListItem();
18+
item.setProps(newProps, {});
19+
return item;
20+
}
21+
finalizeInitialChildren(
22+
instance: RNListItem,
23+
newProps: ListItemProps,
24+
rootContainerInstance: AppContainer,
25+
context: any
26+
): boolean {
27+
return false;
28+
}
29+
commitUpdate(
30+
instance: RNListItem,
31+
updatePayload: any,
32+
oldProps: ListItemProps,
33+
newProps: ListItemProps,
34+
finishedWork: Fiber
35+
): void {
36+
instance.setProps(newProps, oldProps);
37+
}
38+
}
39+
40+
export const ListItem = registerComponent<ListItemProps>(new ListItemConfig());

src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export { InputDialog } from "./components/InputDialog";
3232
export { ProgressDialog } from "./components/ProgressDialog";
3333
export { Table } from "./components/Table";
3434
export { TableItem } from "./components/TableItem";
35+
export { List } from "./components/List";
36+
export { ListItem } from "./components/ListItem";
3537
export { ErrorPrompt } from "./components/ErrorPrompt"
3638
export { useEventHandler } from "./hooks";
3739
export { Renderer } from "./renderer";

0 commit comments

Comments
 (0)