Skip to content

Commit

Permalink
Readymade 3.1.0 (#59)
Browse files Browse the repository at this point in the history
### 3.1.0

Readymade 3.1.0 Large Glass breaks the glass, adding new features that allow UI controls to communicate over WebSocket, WebRTC Data Channel, and Touch OSC.

### @readymade/ui

- new: `RdDial` has similar interface to `RdSlider` but action is limited to a rotary dial
- new: documentation available at [https://readymade-ui.github.io/readymade/#/lib](https://readymade-ui.github.io/readymade/#/lib)
- feat: `RdControl` can now be set via attribute or via `setControl` method on all inputs in @readymade/ui
- feat: provide CSS styles for `RdButton` via `setControl`. Any provided styles are bound to the internal `HTMLButtonElement`

### @readymade/transmit

- feat: `Transmitter` is a new `class` for handling `WebRTC DataChannel`, `WebSocket` and `Touch OSC` communication.

`Transmitter` is a Swiss-army knife for communicating over WebRTC DataChannel, WebSocket or Touch OSC.

#### Getting Started

```bash
npm install @readymade/transmit
```

```bash
yarn add @readymade/transmit
```

Import `Transmitter` and instantiate with a configuration Object.

```javascript
import { Transmitter, TransmitterConfig } from '@readymade/transmit';

const config: TransmitterConfig = {
  sharedKey: 'lobby',
  rtc: {
    iceServers,
  },
  serverConfig: {
    http: {
      protocol: 'http',
      hostname: 'localhost',
      port: 4449,
    },
    ws: {
      osc: {
        protocol: 'ws',
        hostname: 'localhost',
        port: 4445,
      },
      signal: {
        protocol: 'ws',
        hostname: 'localhost',
        port: 4446,
      },
      announce: {
        protocol: 'ws',
        hostname: 'localhost',
        port: 4447,
      },
      message: {
        protocol: 'ws',
        hostname: 'localhost',
        port: 4448,
      },
    },
  },
  onMessage,
  onConnect,
}

const transmitter = new Transmitter(config);
```

### Messages

When `signal` and `announce` servers are configured, the instance of `Transmitter` will automatically attempt a handshake with a remote peer. If a peer is found, a WebRTC DataChannel peer to peer connection will open. To send a message over the data channel use the `send` method.

```javascript
transmitter.send({ message: 'ping' });
```

If you want to send messages over WebSocket, use `sendSocketMessage`.

```javascript
transmitter.sendSocketMessage({ message: 'ping' });
```

To send a message over TouchOSC, use `sendTouchOSCMessage`, ensuring the data your are sending follows the OSC protocol. Below is an example of sending a OSC message with type definitions.

```javascript
transmitter.sendTouchOSCMessage('/OSCQUERY/Left Controls/Flip H', [
  {
    type: 'i',
    value: 1,
  },
]);
```

To listen for messages, inject a callback into the configuration. In the above example, `onMessage` would appear like so:

```javascript
const onMessage = (message) => {
  if (message.payload.event === 'ping') {
    this.transmitter.send({ event: 'pong' });
  }
};
```

To react to a peer to peer connection, bind an `onConnect` callback to the configuration.

### BREAKING CHANGES

`RdControl` type definition in @readymade/ui has been updated to normalize types for all controls and make type definitions more specific per control. `RdLegacyControl` is now exported which is the old type definition. The interface of all controls have been normalized, some properties are deprecated, while other shared properties are now moved to `attributes` that are unique to each control.

#### Before

```typescript
interface RdControl {
  type: string;
  name: string;
  orient?: string;
  min?: number | number[];
  max?: number | number[];
  isActive?: boolean;
  placeSelf?: string;
  transform?: string;
  numberType?: 'int' | 'float';
}
```

#### After

```typescript
interface RdControl<A> {
  type?: string;
  name: string;
  isActive?: boolean;
  hasUserInput?: boolean;
  hasRemoteInput?: boolean;
  currentValue?: number | string | Array<number> | Array<string> | boolean;
  timeStamp?: Date | number;
  attributes?: A;
}
```

For instance, in `RdSlider` which is a custom element that has several unique attributes, the type definition is now:

```typescript
interface RdSliderAttributes {
  size?: string;
  height?: number;
  width?: number;
  orient?: string;
  min?: number | number[];
  max?: number | number[];
  position?: string;
  x?: number;
  y?: number;
  snapToCenter?: boolean;
  transform?: string;
  numberType?: 'int' | 'float';
}

RdControl<RdSliderAttributes>;
```

The reason for this change is to support @readymade/transmit. Passing an event from custom element to `BroadcastChannel` or any of the available channels in `Transmitter` is much simpler when the API is normalized.
  • Loading branch information
steveblue authored Nov 17, 2024
1 parent 622dac5 commit fe9dcdf
Show file tree
Hide file tree
Showing 53 changed files with 4,240 additions and 609 deletions.
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
src/client/app/view/home/home.html
src/client/app/view/home/home.ts
src/client/app/view/home/home.ts
src/client/app/view/lib/lib.html
27 changes: 26 additions & 1 deletion BUILD.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,45 @@ cp src/modules/core/README.md dist/packages/@readymade/core/README.md
npx tsc -p src/modules/dom/tsconfig.json --outDir dist/packages/@readymade/dom/esm2022 --declarationDir dist/packages/@readymade/dom/typings
npx rollup -c src/modules/dom/rollup.config.js
cp src/modules/dom/package.json dist/packages/@readymade/dom/package.json
cp CHANGELOG.md dist/packages/@readymade/dom/CHANGELOG.md
cp src/modules/dom/LICENSE.txt dist/packages/@readymade/dom/LICENSE.txt
cp src/modules/dom/README.md dist/packages/@readymade/dom/README.md


npx tsc -p src/modules/router/tsconfig.json --outDir dist/packages/@readymade/router/esm2022 --declarationDir dist/packages/@readymade/router/typings
npx rollup -c src/modules/router/rollup.config.js
cp src/modules/router/package.json dist/packages/@readymade/router/package.json
cp CHANGELOG.md dist/packages/@readymade/router/CHANGELOG.md
cp src/modules/router/LICENSE.txt dist/packages/@readymade/router/LICENSE.txt
cp src/modules/router/README.md dist/packages/@readymade/router/README.md


npx tsc -p src/modules/ui/tsconfig.json --outDir dist/packages/@readymade/ui/esm2022 --declarationDir dist/packages/@readymade/ui/typings
npx rollup -c src/modules/ui/rollup.config.js
cp src/modules/ui/package.json dist/packages/@readymade/ui/package.json
cp CHANGELOG.md dist/packages/@readymade/ui/CHANGELOG.md
cp src/modules/ui/LICENSE.txt dist/packages/@readymade/ui/LICENSE.txt
cp src/modules/ui/README.md dist/packages/@readymade/ui/README.md
cp src/client/style/readymade-ui.css dist/packages/@readymade/ui/readymade-ui.css
cp src/client/style/readymade-ui.css dist/packages/@readymade/ui/readymade-ui.css

npx tsc -p src/modules/transmit/tsconfig.json --outDir dist/packages/@readymade/transmit/esm2022 --declarationDir dist/packages/@readymade/transmit/typings
npx rollup -c src/modules/transmit/rollup.config.js
cp CHANGELOG.md dist/packages/@readymade/transmit/CHANGELOG.md
cp src/modules/transmit/package.json dist/packages/@readymade/transmit/package.json
cp src/modules/transmit/LICENSE.txt dist/packages/@readymade/transmit/LICENSE.txt
cp src/modules/transmit/README.md dist/packages/@readymade/transmit/README.md


rm -rf dist/packages/@readymade/core/fesm2022/typings
rm -rf dist/packages/@readymade/dom/fesm2022/typings
rm -rf dist/packages/@readymade/router/fesm2022/typings
rm -rf dist/packages/@readymade/transmit/fesm2022/typings
rm -rf dist/packages/@readymade/ui/fesm2022/typings
rm -rf dist/packages/@readymade/dom/esm2022/core
rm -rf dist/packages/@readymade/dom/typings/core
rm -rf dist/packages/@readymade/router/esm2022/core
rm -rf dist/packages/@readymade/router/typings/core
rm -rf dist/packages/@readymade/ui/esm2022/core
rm -rf dist/packages/@readymade/ui/esm2022/dom
rm -rf dist/packages/@readymade/ui/typings/core
rm -rf dist/packages/@readymade/ui/typings/dom
168 changes: 168 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,173 @@
# CHANGELOG

### 3.1.0

Readymade 3.1.0 Large Glass breaks the glass, adding new features that allow UI controls to communicate over WebSocket, WebRTC Data Channel, and Touch OSC.

### @readymade/ui

- new: `RdDial` has similar interface to `RdSlider` but action is limited to a rotary dial
- new: documentation available at [https://readymade-ui.github.io/readymade/#/lib](https://readymade-ui.github.io/readymade/#/lib)
- feat: `RdControl` can now be set via attribute or via `setControl` method on all inputs in @readymade/ui
- feat: provide CSS styles for `RdButton` via `setControl`. Any provided styles are bound to the internal `HTMLButtonElement`

### @readymade/transmit

- feat: `Transmitter` is a new `class` for handling `WebRTC DataChannel`, `WebSocket` and `Touch OSC` communication.

`Transmitter` is a Swiss-army knife for communicating over WebRTC DataChannel, WebSocket or Touch OSC.

#### Getting Started

```bash
npm install @readymade/transmit
```

```bash
yarn add @readymade/transmit
```

Import `Transmitter` and instantiate with a configuration Object.

```javascript
import { Transmitter, TransmitterConfig } from '@readymade/transmit';

const config: TransmitterConfig = {
sharedKey: 'lobby',
rtc: {
iceServers,
},
serverConfig: {
http: {
protocol: 'http',
hostname: 'localhost',
port: 4449,
},
ws: {
osc: {
protocol: 'ws',
hostname: 'localhost',
port: 4445,
},
signal: {
protocol: 'ws',
hostname: 'localhost',
port: 4446,
},
announce: {
protocol: 'ws',
hostname: 'localhost',
port: 4447,
},
message: {
protocol: 'ws',
hostname: 'localhost',
port: 4448,
},
},
},
onMessage,
onConnect,
}

const transmitter = new Transmitter(config);
```

### Messages

When `signal` and `announce` servers are configured, the instance of `Transmitter` will automatically attempt a handshake with a remote peer. If a peer is found, a WebRTC DataChannel peer to peer connection will open. To send a message over the data channel use the `send` method.

```javascript
transmitter.send({ message: 'ping' });
```

If you want to send messages over WebSocket, use `sendSocketMessage`.

```javascript
transmitter.sendSocketMessage({ message: 'ping' });
```

To send a message over TouchOSC, use `sendTouchOSCMessage`, ensuring the data your are sending follows the OSC protocol. Below is an example of sending a OSC message with type definitions.

```javascript
transmitter.sendTouchOSCMessage('/OSCQUERY/Left Controls/Flip H', [
{
type: 'i',
value: 1,
},
]);
```

To listen for messages, inject a callback into the configuration. In the above example, `onMessage` would appear like so:

```javascript
const onMessage = (message) => {
if (message.payload.event === 'ping') {
this.transmitter.send({ event: 'pong' });
}
};
```

To react to a peer to peer connection, bind an `onConnect` callback to the configuration.

### BREAKING CHANGES

`RdControl` type definition in @readymade/ui has been updated to normalize types for all controls and make type definitions more specific per control. `RdLegacyControl` is now exported which is the old type definition. The interface of all controls have been normalized, some properties are deprecated, while other shared properties are now moved to `attributes` that are unique to each control.

#### Before

```typescript
interface RdControl {
type: string;
name: string;
orient?: string;
min?: number | number[];
max?: number | number[];
isActive?: boolean;
placeSelf?: string;
transform?: string;
numberType?: 'int' | 'float';
}
```

#### After

```typescript
interface RdControl<A> {
type?: string;
name: string;
isActive?: boolean;
hasUserInput?: boolean;
hasRemoteInput?: boolean;
currentValue?: number | string | Array<number> | Array<string> | boolean;
timeStamp?: Date | number;
attributes?: A;
}
```

For instance, in `RdSlider` which is a custom element that has several unique attributes, the type definition is now:

```typescript
interface RdSliderAttributes {
size?: string;
height?: number;
width?: number;
orient?: string;
min?: number | number[];
max?: number | number[];
position?: string;
x?: number;
y?: number;
snapToCenter?: boolean;
transform?: string;
numberType?: 'int' | 'float';
}

RdControl<RdSliderAttributes>;
```

The reason for this change is to support @readymade/transmit. Passing an event from custom element to `BroadcastChannel` or any of the available channels in `Transmitter` is much simpler when the API is normalized.

### 3.0.0

Readymade 3.0.0 Large Glass brings project dependencies up to date, adds new features and introduces several bugfixes and enhancements.
Expand Down
18 changes: 13 additions & 5 deletions cypress/integration/components/button.spec.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
/// <reference types="cypress" />

describe('MyButtonComponent Test', () => {

beforeEach(() => {
cy.visit('/test');
cy.wait(1);
});

it('Displays outline when clicked', () => {
cy.get('app-testbed').shadow().find('button[is="my-button"]').click();
cy.get('app-testbed').shadow().find('button[is="my-button"]').should('have.css', 'box-shadow', 'rgb(255, 105, 180) 0px 0px 0px 0px');
cy.get('app-testbed')
.shadow()
.find('button[is="my-button"]')
.should('have.css', 'box-shadow', 'rgb(255, 105, 180) 0px 0px 0px 0px');
});

it('Displays Click', () => {
cy.get('app-testbed').shadow().find('button[is="my-button"]').contains('Click');
cy.get('app-testbed')
.shadow()
.find('button[is="my-button"]')
.contains('Click');
});

it('Controls MyListComponent with BroadcastChannel API', () => {
cy.get('app-testbed').shadow().find('button[is="my-button"]').click();
cy.get('app-testbed').shadow().find('my-item').invoke('attr', 'state').should('contain', '--selected');
cy.get('app-testbed')
.shadow()
.find('my-item')
.invoke('attr', 'state')
.should('contain', '--selected');
});

});
10 changes: 6 additions & 4 deletions cypress/integration/components/input.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@

describe('MyInputComponent Test', () => {

beforeEach(() => {
cy.visit('/test');
cy.wait(1);
});

it('Displays input when focused', () => {
cy.get('app-testbed').shadow().find('input[is="my-input"]').focus().invoke('val').should('contain', 'input');
cy.get('app-testbed')
.shadow()
.find('input[is="my-input"]')
.focus()
.invoke('val')
.should('contain', 'input');
});

});
11 changes: 7 additions & 4 deletions cypress/integration/components/item.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

describe('MyItemComponent Test', () => {

beforeEach(() => {
cy.visit('/test');
cy.wait(1);
Expand All @@ -11,7 +9,12 @@ describe('MyItemComponent Test', () => {
});

it('Displays selected when clicked', () => {
cy.get('app-testbed').shadow().find('my-item').first().click('left').invoke('attr', 'state').should('contain', '--selected');
cy.get('app-testbed')
.shadow()
.find('my-item')
.first()
.click('left')
.invoke('attr', 'state')
.should('contain', '--selected');
});

});
31 changes: 24 additions & 7 deletions cypress/integration/components/list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@

describe('MyListComponent Test', () => {

beforeEach(() => {
cy.visit('/test');
});

it('Displays four instances of MyItemComponent', () => {
cy.get('app-testbed').shadow().find('my-list').find('my-item').should('have.length', 4);
cy.get('app-testbed')
.shadow()
.find('my-list')
.find('my-item')
.should('have.length', 4);
});

it('Selects the last item when clicked', () => {
cy.get('app-testbed').shadow().find('my-list').find('li').first().click('left');
cy.get('app-testbed').shadow().find('my-list').find('li').last().click('left');
cy.get('app-testbed').shadow().find('my-list').find('my-item').last().invoke('attr', 'state').should('contain', '--selected');
cy.get('app-testbed')
.shadow()
.find('my-list')
.find('li')
.first()
.click('left');
cy.get('app-testbed')
.shadow()
.find('my-list')
.find('li')
.last()
.click('left');
cy.get('app-testbed')
.shadow()
.find('my-list')
.find('my-item')
.last()
.invoke('attr', 'state')
.should('contain', '--selected');
});

});
Loading

0 comments on commit fe9dcdf

Please sign in to comment.