Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce react-light-desk #175

Merged
merged 3 commits into from
Sep 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions light-desk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [breaking]: rework backend interfaces to unify defining and mutating props,
adding / removing listeners, and child-parent relationships.

Deprecations, to remove before releases:
- `.addChild()` and `addChildren()` functions

## [2.1.1] - 2022-01-11

- Update ws and @types/ws
Expand Down
47 changes: 36 additions & 11 deletions light-desk/src/backend/components/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,32 @@ export abstract class BaseParent<T> extends Base<T> implements Parent {

public abstract validateChildren(children: Component[]): void;

public addChildren = <CS extends Component[]>(...children: CS): CS => {
public appendChildren = <CS extends Component[]>(...children: CS): CS => {
for (const c of children) {
if (!this.children.includes(c)) {
const newChildren = [...this.children, c];
this.validateChildren(newChildren);
this.children = Object.freeze(newChildren);
c.setParent(this);
}
const newChildren = [...this.children.filter((ch) => ch !== c), c];
this.validateChildren(newChildren);
this.children = Object.freeze(newChildren);
c.setParent(this);
}
this.updateTree();
return children;
};

public addChild = <C extends Component>(child: C): C => {
this.addChildren(child);
/**
* @deprecated use appendChildren instead
*/
public addChildren = this.appendChildren;

public appendChild = <C extends Component>(child: C): C => {
this.appendChildren(child);
return child;
};

/**
* @deprecated use appendChild instead
*/
public addChild = this.appendChild;

public removeChild = (component: Component) => {
const match = this.children.findIndex((c) => c === component);
if (match >= 0) {
Expand Down Expand Up @@ -158,8 +166,25 @@ export abstract class BaseParent<T> extends Base<T> implements Parent {
}
}

public insertBefore(_child: Component, _beforeChild: Component) {
throw new Error('TODO');
public insertBefore(child: Component, beforeChild: Component) {
// Remove child from current parent (if it exists)
const filteredChildren = this.children.filter((c) => c !== child);
// Find position of beforeChild
let match = filteredChildren.findIndex((c) => c === beforeChild);
console.log('match', match);
if (match === -1) {
// If beforeChild is not found, insert at the end
match = filteredChildren.length;
}
const newChildren = [
...filteredChildren.slice(0, match),
child,
...filteredChildren.slice(match),
];
this.validateChildren(newChildren);
this.children = Object.freeze(newChildren);
child.setParent(this);
this.updateTree();
}
}

Expand Down
2 changes: 1 addition & 1 deletion light-desk/src/backend/components/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type InternalTabProps = {
name: string;
};

export type TabProps = InternalTabsProps;
export type TabProps = InternalTabProps;

export class Tab extends BaseParent<InternalTabProps> {
public validateChildren = (children: Component[]) => {
Expand Down
5 changes: 5 additions & 0 deletions react-light-desk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/node_modules/
/lib/
/index.js
/index.d.ts
*.log
9 changes: 9 additions & 0 deletions react-light-desk/gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var util = require('@synesthesia-project/gulp-util');
var gulp = require('gulp');

util.setupBasicTypescriptProject({
clean: ['lib'],
outputDir: './lib'
});

gulp.task('default', gulp.series('clean', 'ts'));
36 changes: 36 additions & 0 deletions react-light-desk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@synesthesia-project/react-light-desk",
"version": "0.0.1",
"description": "Core synesthesia libraries, type definitions & protocols",
"license": "MIT",
"main": "index.js",
"types": "index.d.js",
"repository": {
"type": "git",
"url": "https://github.com/synesthesia-project/synesthesia"
},
"scripts": {
"clean": "gulp clean",
"build": "gulp",
"lint": "gulp lint",
"lint:fix": "gulp lint:fix"
},
"files": [
"lib/**/*",
"index.d.ts",
"index.js",
"README.md"
],
"dependencies": {
"@synesthesia-project/compositor": "^0.0.1",
"@synesthesia-project/light-desk": "^2.1.1",
"react-reconciler": "0.26.0"
},
"devDependencies": {
"@synesthesia-project/gulp-util": "~0.0.1",
"@types/react": "^17.0.0",
"@types/react-reconciler": "~0.26.0",
"react": "^17.0.2",
"gulp": "~4.0.2"
}
}
42 changes: 42 additions & 0 deletions react-light-desk/src/components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react';
import { LightDeskIntrinsicElements } from './types';

export const Button: React.FunctionComponent<
LightDeskIntrinsicElements['button']
> = (props) => React.createElement('button', props, props.children);

export const Group: React.FunctionComponent<
LightDeskIntrinsicElements['group']
> = (props) => React.createElement('group', props, props.children);

export const GroupHeader: React.FunctionComponent<
LightDeskIntrinsicElements['group-header']
> = (props) => React.createElement('group-header', props, props.children);

export const Label: React.FunctionComponent<
LightDeskIntrinsicElements['label']
> = (props) => React.createElement('label', props, props.children);

export const Rect: React.FunctionComponent<
LightDeskIntrinsicElements['rect']
> = (props) => React.createElement('rect', props, props.children);

export const SliderButton: React.FunctionComponent<
LightDeskIntrinsicElements['slider-button']
> = (props) => React.createElement('slider-button', props, props.children);

export const Switch: React.FunctionComponent<
LightDeskIntrinsicElements['switch']
> = (props) => React.createElement('switch', props, props.children);

export const Tab: React.FunctionComponent<LightDeskIntrinsicElements['tab']> = (
props
) => React.createElement('tab', props, props.children);

export const Tabs: React.FunctionComponent<
LightDeskIntrinsicElements['tabs']
> = (props) => React.createElement('tabs', props, props.children);

export const TextInput: React.FunctionComponent<
LightDeskIntrinsicElements['text-input']
> = (props) => React.createElement('text-input', props, props.children);
38 changes: 38 additions & 0 deletions react-light-desk/src/examples/example-001.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import * as ld from '@synesthesia-project/light-desk';

import { LightDeskRenderer, Group } from '../index';

const desk = new ld.LightDesk();

desk.start({
mode: 'automatic',
port: 1338,
});

const group = new ld.Group();
desk.setRoot(group);

const TestComponent = ({ foo }: { foo: string }) => {
const [count, setCount] = React.useState(0);

React.useEffect(() => {
const timeout = setTimeout(() => {
setCount(count + 1);
}, 1000);
return () => clearTimeout(timeout);
}, [count]);

return <Group title={`asd: ${count}`}>{`${foo}: ${count}`}</Group>;
};

const App = () => (
<Group title="foo">
<TestComponent foo="a" />
<Group defaultCollapsibleState="closed">
<TestComponent foo="b" />
</Group>
</Group>
);

LightDeskRenderer.render(<App />, group);
26 changes: 26 additions & 0 deletions react-light-desk/src/examples/example-002.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import * as ld from '@synesthesia-project/light-desk';

import { LightDeskRenderer, Group } from '../index';

const desk = new ld.LightDesk();

desk.start({
mode: 'automatic',
port: 1338,
});

const group = new ld.Group();
desk.setRoot(group);

const App = () => {
const [title, setTitle] = React.useState('initial-group');

return (
<Group title={title} editableTitle={true} onTitleChanged={setTitle}>
{`Label: ${title}`}
</Group>
);
};

LightDeskRenderer.render(<App />, group);
Loading
Loading