lint
This commit is contained in:
17
.github/workflows/build_docker.yml
vendored
17
.github/workflows/build_docker.yml
vendored
@ -3,28 +3,23 @@ name: Build and Push Docker Images
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- "main"
|
||||||
jobs:
|
jobs:
|
||||||
topos:
|
topos:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
-
|
- name: Set up QEMU
|
||||||
name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
-
|
- name: Set up Docker Buildx
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
- name: Login to Docker Hub
|
||||||
name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
-
|
- name: Build and push
|
||||||
name: Build and push
|
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,2 +1 @@
|
|||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|||||||
@ -46,15 +46,18 @@ The `tauri` version is only here to quickstart future developments but nothing
|
|||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
### Run the application
|
### Run the application
|
||||||
|
|
||||||
`docker run -p 8001:80 yassinsiouda/topos:latest`
|
`docker run -p 8001:80 yassinsiouda/topos:latest`
|
||||||
|
|
||||||
### Build and run the prod image
|
### Build and run the prod image
|
||||||
|
|
||||||
`docker compose --profile prod up`
|
`docker compose --profile prod up`
|
||||||
|
|
||||||
### Build and run the dev image
|
### Build and run the dev image
|
||||||
|
|
||||||
**First installation**
|
**First installation**
|
||||||
First you need to map node_modules to your local machine for your ide intellisense to work properly
|
First you need to map node_modules to your local machine for your ide intellisense to work properly
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose --profile dev up -d
|
docker compose --profile dev up -d
|
||||||
docker cp topos-dev:/app/node_modules .
|
docker cp topos-dev:/app/node_modules .
|
||||||
@ -62,7 +65,7 @@ docker compose --profile dev down
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Then**
|
**Then**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose --profile dev up
|
docker compose --profile dev up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
version: '3.7'
|
version: "3.7"
|
||||||
services:
|
services:
|
||||||
topos-dev:
|
topos-dev:
|
||||||
container_name: topos-dev
|
container_name: topos-dev
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "",
|
"name": "",
|
||||||
"short_name": "",
|
"short_name": "",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#ffffff",
|
"theme_color": "#ffffff",
|
||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
"display": "standalone"
|
"display": "standalone"
|
||||||
}
|
}
|
||||||
|
|||||||
135
fonts/index.css
135
fonts/index.css
@ -1,7 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "IBM Plex Mono";
|
font-family: "IBM Plex Mono";
|
||||||
src: url("woff2/IBMPlexMono-Regular.woff2") format("woff2"),
|
src:
|
||||||
url("woff/IBMPlexMono-Regular.woff") format("woff");
|
url("woff2/IBMPlexMono-Regular.woff2") format("woff2"),
|
||||||
|
url("woff/IBMPlexMono-Regular.woff") format("woff");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@ -9,8 +10,9 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "IBM PLex Mono";
|
font-family: "IBM PLex Mono";
|
||||||
src: url("woff2/IBMPlexMono-Italic.woff2") format("woff2"),
|
src:
|
||||||
url("woff/IBMPlexMono-Italic.woff") format("woff");
|
url("woff2/IBMPlexMono-Italic.woff2") format("woff2"),
|
||||||
|
url("woff/IBMPlexMono-Italic.woff") format("woff");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@ -18,8 +20,9 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "IBM PLex Mono";
|
font-family: "IBM PLex Mono";
|
||||||
src: url("woff2/IBMPlexMono-Bold.woff2") format("woff2"),
|
src:
|
||||||
url("woff/IBMPlexMono-Bold.woff") format("woff");
|
url("woff2/IBMPlexMono-Bold.woff2") format("woff2"),
|
||||||
|
url("woff/IBMPlexMono-Bold.woff") format("woff");
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@ -27,8 +30,9 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "IBM Plex Mono";
|
font-family: "IBM Plex Mono";
|
||||||
src: url("woff2/IBMPlexMono-BoldItalic.woff2") format("woff2"),
|
src:
|
||||||
url("woff/IBMPlexMono-BoldItalic.woff") format("woff");
|
url("woff2/IBMPlexMono-BoldItalic.woff2") format("woff2"),
|
||||||
|
url("woff/IBMPlexMono-BoldItalic.woff") format("woff");
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@ -37,84 +41,85 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Comic Mono";
|
font-family: "Comic Mono";
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src: url(./woff/ComicMono.woff) format("woff"),
|
src:
|
||||||
url(./woff2/ComicMono.woff2) format("wooff2");
|
url(./woff/ComicMono.woff) format("woff"),
|
||||||
|
url(./woff2/ComicMono.woff2) format("wooff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Comic Mono";
|
font-family: "Comic Mono";
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src: url(./woff/ComicMono-Bold.woff) format("woff"),
|
src:
|
||||||
url(./woff/ComicMono-Bold.woff2) format("woff2"),
|
url(./woff/ComicMono-Bold.woff) format("woff"),
|
||||||
}
|
url(./woff/ComicMono-Bold.woff2) format("woff2");
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'jgs7';
|
|
||||||
src: url('./woff2/jgs7.woff2') format('woff2'),
|
|
||||||
url('./woff/jgs7.woff') format('woff');
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'jgs5';
|
font-family: "jgs7";
|
||||||
src: url('./woff2/jgs5.woff2') format('woff2'),
|
src:
|
||||||
url('./woff/jgs5.woff') format('woff');
|
url("./woff2/jgs7.woff2") format("woff2"),
|
||||||
font-weight: normal;
|
url("./woff/jgs7.woff") format("woff");
|
||||||
font-style: normal;
|
font-weight: normal;
|
||||||
font-display: swap;
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'jgs9';
|
font-family: "jgs5";
|
||||||
src: url('./woff2/jgs9.woff2') format('woff2'),
|
src:
|
||||||
url('./woff/jgs9.woff') format('woff');
|
url("./woff2/jgs5.woff2") format("woff2"),
|
||||||
font-weight: normal;
|
url("./woff/jgs5.woff") format("woff");
|
||||||
font-style: normal;
|
font-weight: normal;
|
||||||
font-display: swap;
|
font-style: normal;
|
||||||
}
|
font-display: swap;
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'jgs_vecto';
|
|
||||||
src: url('./woff2/jgs_vecto.woff2') format('woff2');
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Steps Mono';
|
font-family: "jgs9";
|
||||||
src: url('./woff2/Steps-Mono.woff2') format('woff2');
|
src:
|
||||||
font-weight: normal;
|
url("./woff2/jgs9.woff2") format("woff2"),
|
||||||
font-style: normal;
|
url("./woff/jgs9.woff") format("woff");
|
||||||
font-display: swap;
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Steps Mono Thin';
|
font-family: "jgs_vecto";
|
||||||
src: url('./woff2/Steps-Mono-Thin.woff2') format('woff2');
|
src: url("./woff2/jgs_vecto.woff2") format("woff2");
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Jet Brains';
|
font-family: "Steps Mono";
|
||||||
src: url('./woff2/JetBrainsMono-Regular.woff2') format('woff2');
|
src: url("./woff2/Steps-Mono.woff2") format("woff2");
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Jet Brains';
|
font-family: "Steps Mono Thin";
|
||||||
src: url('./woff2/JetBrainsMono-Bold.woff2') format('woff2');
|
src: url("./woff2/Steps-Mono-Thin.woff2") format("woff2");
|
||||||
font-weight: 700;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Jet Brains";
|
||||||
|
src: url("./woff2/JetBrainsMono-Regular.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Jet Brains";
|
||||||
|
src: url("./woff2/JetBrainsMono-Bold.woff2") format("woff2");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,4 +3,4 @@ export default {
|
|||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
74
src/API.ts
74
src/API.ts
@ -111,7 +111,7 @@ export class UserAPI {
|
|||||||
}
|
}
|
||||||
this.app.settings.saveApplicationToLocalStorage(
|
this.app.settings.saveApplicationToLocalStorage(
|
||||||
this.app.universes,
|
this.app.universes,
|
||||||
this.app.settings
|
this.app.settings,
|
||||||
);
|
);
|
||||||
this.app.updateKnownUniversesView();
|
this.app.updateKnownUniversesView();
|
||||||
};
|
};
|
||||||
@ -203,7 +203,7 @@ export class UserAPI {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.errorTimeoutID = setTimeout(
|
this.errorTimeoutID = setTimeout(
|
||||||
() => this.app.interface.error_line.classList.add("hidden"),
|
() => this.app.interface.error_line.classList.add("hidden"),
|
||||||
2000
|
2000,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ export class UserAPI {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.printTimeoutID = setTimeout(
|
this.printTimeoutID = setTimeout(
|
||||||
() => this.app.interface.error_line.classList.add("hidden"),
|
() => this.app.interface.error_line.classList.add("hidden"),
|
||||||
4000
|
4000,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.app.clock.tick = beat * this.app.clock.ppqn;
|
this.app.clock.tick = beat * this.app.clock.ppqn;
|
||||||
this.app.clock.time_position = this.app.clock.convertTicksToTimeposition(
|
this.app.clock.time_position = this.app.clock.convertTicksToTimeposition(
|
||||||
beat * this.app.clock.ppqn
|
beat * this.app.clock.ppqn,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ export class UserAPI {
|
|||||||
blinkScript(this.app, "local", arg);
|
blinkScript(this.app, "local", arg);
|
||||||
tryEvaluate(
|
tryEvaluate(
|
||||||
this.app,
|
this.app,
|
||||||
this.app.universes[this.app.selected_universe].locals[arg]
|
this.app.universes[this.app.selected_universe].locals[arg],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -372,7 +372,7 @@ export class UserAPI {
|
|||||||
delete this.app.universes[universe];
|
delete this.app.universes[universe];
|
||||||
this.app.settings.saveApplicationToLocalStorage(
|
this.app.settings.saveApplicationToLocalStorage(
|
||||||
this.app.universes,
|
this.app.universes,
|
||||||
this.app.settings
|
this.app.settings,
|
||||||
);
|
);
|
||||||
this.app.updateKnownUniversesView();
|
this.app.updateKnownUniversesView();
|
||||||
};
|
};
|
||||||
@ -388,7 +388,7 @@ export class UserAPI {
|
|||||||
};
|
};
|
||||||
this.app.settings.saveApplicationToLocalStorage(
|
this.app.settings.saveApplicationToLocalStorage(
|
||||||
this.app.universes,
|
this.app.universes,
|
||||||
this.app.settings
|
this.app.settings,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.app.selected_universe = "Default";
|
this.app.selected_universe = "Default";
|
||||||
@ -425,7 +425,7 @@ export class UserAPI {
|
|||||||
value: number | number[] = 60,
|
value: number | number[] = 60,
|
||||||
velocity?: number | number[],
|
velocity?: number | number[],
|
||||||
channel?: number | number[],
|
channel?: number | number[],
|
||||||
port?: number | string | number[] | string[]
|
port?: number | string | number[] | string[],
|
||||||
): MidiEvent => {
|
): MidiEvent => {
|
||||||
/**
|
/**
|
||||||
* Sends a MIDI note to the current MIDI output.
|
* Sends a MIDI note to the current MIDI output.
|
||||||
@ -500,7 +500,7 @@ export class UserAPI {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public active_note_events = (
|
public active_note_events = (
|
||||||
channel?: number
|
channel?: number,
|
||||||
): MidiNoteEvent[] | undefined => {
|
): MidiNoteEvent[] | undefined => {
|
||||||
/**
|
/**
|
||||||
* @returns A list of currently active MIDI notes
|
* @returns A list of currently active MIDI notes
|
||||||
@ -637,7 +637,7 @@ export class UserAPI {
|
|||||||
scale: number | string,
|
scale: number | string,
|
||||||
channel: number = 0,
|
channel: number = 0,
|
||||||
port: number | string = this.MidiConnection.currentOutputIndex || 0,
|
port: number | string = this.MidiConnection.currentOutputIndex || 0,
|
||||||
soundOff: boolean = false
|
soundOff: boolean = false,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Sends given scale to midi output for visual aid
|
* Sends given scale to midi output for visual aid
|
||||||
@ -661,7 +661,7 @@ export class UserAPI {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
scale: number | string = 0,
|
scale: number | string = 0,
|
||||||
channel: number = 0,
|
channel: number = 0,
|
||||||
port: number | string = this.MidiConnection.currentOutputIndex || 0
|
port: number | string = this.MidiConnection.currentOutputIndex || 0,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Hides all notes by sending all notes off to midi output
|
* Hides all notes by sending all notes off to midi output
|
||||||
@ -676,7 +676,7 @@ export class UserAPI {
|
|||||||
|
|
||||||
midi_notes_off = (
|
midi_notes_off = (
|
||||||
channel: number = 0,
|
channel: number = 0,
|
||||||
port: number | string = this.MidiConnection.currentOutputIndex || 0
|
port: number | string = this.MidiConnection.currentOutputIndex || 0,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Sends all notes off to midi output
|
* Sends all notes off to midi output
|
||||||
@ -686,7 +686,7 @@ export class UserAPI {
|
|||||||
|
|
||||||
midi_sound_off = (
|
midi_sound_off = (
|
||||||
channel: number = 0,
|
channel: number = 0,
|
||||||
port: number | string = this.MidiConnection.currentOutputIndex || 0
|
port: number | string = this.MidiConnection.currentOutputIndex || 0,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Sends all sound off to midi output
|
* Sends all sound off to midi output
|
||||||
@ -713,7 +713,7 @@ export class UserAPI {
|
|||||||
public z = (
|
public z = (
|
||||||
input: string | Generator<number>,
|
input: string | Generator<number>,
|
||||||
options: InputOptions = {},
|
options: InputOptions = {},
|
||||||
id: number | string = ""
|
id: number | string = "",
|
||||||
): Player => {
|
): Player => {
|
||||||
const zid = "z" + id.toString();
|
const zid = "z" + id.toString();
|
||||||
const key = id === "" ? this.generateCacheKey(input, options) : zid;
|
const key = id === "" ? this.generateCacheKey(input, options) : zid;
|
||||||
@ -790,7 +790,7 @@ export class UserAPI {
|
|||||||
public counter = (
|
public counter = (
|
||||||
name: string | number,
|
name: string | number,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
step?: number
|
step?: number,
|
||||||
): number => {
|
): number => {
|
||||||
/**
|
/**
|
||||||
* Returns the current value of a counter, and increments it by the step value.
|
* Returns the current value of a counter, and increments it by the step value.
|
||||||
@ -1297,8 +1297,8 @@ export class UserAPI {
|
|||||||
const results: boolean[] = nArray.map(
|
const results: boolean[] = nArray.map(
|
||||||
(value) =>
|
(value) =>
|
||||||
(this.app.clock.pulses_since_origin - Math.floor(nudge * this.ppqn())) %
|
(this.app.clock.pulses_since_origin - Math.floor(nudge * this.ppqn())) %
|
||||||
Math.floor(value * this.ppqn()) ===
|
Math.floor(value * this.ppqn()) ===
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
return results.some((value) => value === true);
|
return results.some((value) => value === true);
|
||||||
};
|
};
|
||||||
@ -1317,8 +1317,8 @@ export class UserAPI {
|
|||||||
const results: boolean[] = nArray.map(
|
const results: boolean[] = nArray.map(
|
||||||
(value) =>
|
(value) =>
|
||||||
(this.app.clock.pulses_since_origin - nudgeInPulses) %
|
(this.app.clock.pulses_since_origin - nudgeInPulses) %
|
||||||
Math.floor(value * barLength) ===
|
Math.floor(value * barLength) ===
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
return results.some((value) => value === true);
|
return results.some((value) => value === true);
|
||||||
};
|
};
|
||||||
@ -1333,7 +1333,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
const nArray = Array.isArray(n) ? n : [n];
|
const nArray = Array.isArray(n) ? n : [n];
|
||||||
const results: boolean[] = nArray.map(
|
const results: boolean[] = nArray.map(
|
||||||
(value) => (this.app.clock.pulses_since_origin - nudge) % value === 0
|
(value) => (this.app.clock.pulses_since_origin - nudge) % value === 0,
|
||||||
);
|
);
|
||||||
return results.some((value) => value === true);
|
return results.some((value) => value === true);
|
||||||
};
|
};
|
||||||
@ -1342,7 +1342,7 @@ export class UserAPI {
|
|||||||
public tick = (tick: number | number[], offset: number = 0): boolean => {
|
public tick = (tick: number | number[], offset: number = 0): boolean => {
|
||||||
const nArray = Array.isArray(tick) ? tick : [tick];
|
const nArray = Array.isArray(tick) ? tick : [tick];
|
||||||
const results: boolean[] = nArray.map(
|
const results: boolean[] = nArray.map(
|
||||||
(value) => this.app.clock.time_position.pulse === value + offset
|
(value) => this.app.clock.time_position.pulse === value + offset,
|
||||||
);
|
);
|
||||||
return results.some((value) => value === true);
|
return results.some((value) => value === true);
|
||||||
};
|
};
|
||||||
@ -1391,7 +1391,7 @@ export class UserAPI {
|
|||||||
|
|
||||||
public onbar = (
|
public onbar = (
|
||||||
bars: number[] | number,
|
bars: number[] | number,
|
||||||
n: number = this.app.clock.time_signature[0]
|
n: number = this.app.clock.time_signature[0],
|
||||||
): boolean => {
|
): boolean => {
|
||||||
let current_bar = (this.app.clock.time_position.bar % n) + 1;
|
let current_bar = (this.app.clock.time_position.bar % n) + 1;
|
||||||
return typeof bars === "number"
|
return typeof bars === "number"
|
||||||
@ -1419,7 +1419,7 @@ export class UserAPI {
|
|||||||
if (decimal_part <= 0)
|
if (decimal_part <= 0)
|
||||||
decimal_part = decimal_part + this.ppqn() * this.nominator();
|
decimal_part = decimal_part + this.ppqn() * this.nominator();
|
||||||
final_pulses.push(
|
final_pulses.push(
|
||||||
integral_part === this.cbeat() && this.cpulse() === decimal_part
|
integral_part === this.cbeat() && this.cpulse() === decimal_part,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return final_pulses.some((p) => p == true);
|
return final_pulses.some((p) => p == true);
|
||||||
@ -1501,7 +1501,7 @@ export class UserAPI {
|
|||||||
iterator: number,
|
iterator: number,
|
||||||
pulses: number,
|
pulses: number,
|
||||||
length: number,
|
length: number,
|
||||||
rotate: number = 0
|
rotate: number = 0,
|
||||||
): boolean => {
|
): boolean => {
|
||||||
/**
|
/**
|
||||||
* Returns a euclidean cycle of size length, with n pulses, rotated or not.
|
* Returns a euclidean cycle of size length, with n pulses, rotated or not.
|
||||||
@ -1520,7 +1520,7 @@ export class UserAPI {
|
|||||||
div: number,
|
div: number,
|
||||||
pulses: number,
|
pulses: number,
|
||||||
length: number,
|
length: number,
|
||||||
rotate: number = 0
|
rotate: number = 0,
|
||||||
): boolean => {
|
): boolean => {
|
||||||
return (
|
return (
|
||||||
this.beat(div) && this._euclidean_cycle(pulses, length, rotate).beat(div)
|
this.beat(div) && this._euclidean_cycle(pulses, length, rotate).beat(div)
|
||||||
@ -1530,7 +1530,7 @@ export class UserAPI {
|
|||||||
_euclidean_cycle(
|
_euclidean_cycle(
|
||||||
pulses: number,
|
pulses: number,
|
||||||
length: number,
|
length: number,
|
||||||
rotate: number = 0
|
rotate: number = 0,
|
||||||
): boolean[] {
|
): boolean[] {
|
||||||
if (pulses == length) return Array.from({ length }, () => true);
|
if (pulses == length) return Array.from({ length }, () => true);
|
||||||
function startsDescent(list: number[], i: number): boolean {
|
function startsDescent(list: number[], i: number): boolean {
|
||||||
@ -1541,7 +1541,7 @@ export class UserAPI {
|
|||||||
if (pulses >= length) return [true];
|
if (pulses >= length) return [true];
|
||||||
const resList = Array.from(
|
const resList = Array.from(
|
||||||
{ length },
|
{ length },
|
||||||
(_, i) => (((pulses * (i - 1)) % length) + length) % length
|
(_, i) => (((pulses * (i - 1)) % length) + length) % length,
|
||||||
);
|
);
|
||||||
let cycle = resList.map((_, i) => startsDescent(resList, i));
|
let cycle = resList.map((_, i) => startsDescent(resList, i));
|
||||||
if (rotate != 0) {
|
if (rotate != 0) {
|
||||||
@ -1660,7 +1660,7 @@ export class UserAPI {
|
|||||||
triangle = (
|
triangle = (
|
||||||
freq: number = 1,
|
freq: number = 1,
|
||||||
times: number = 1,
|
times: number = 1,
|
||||||
offset: number = 0
|
offset: number = 0,
|
||||||
): number => {
|
): number => {
|
||||||
/**
|
/**
|
||||||
* Returns a triangle wave between -1 and 1.
|
* Returns a triangle wave between -1 and 1.
|
||||||
@ -1677,7 +1677,7 @@ export class UserAPI {
|
|||||||
utriangle = (
|
utriangle = (
|
||||||
freq: number = 1,
|
freq: number = 1,
|
||||||
times: number = 1,
|
times: number = 1,
|
||||||
offset: number = 0
|
offset: number = 0,
|
||||||
): number => {
|
): number => {
|
||||||
/**
|
/**
|
||||||
* Returns a triangle wave between 0 and 1.
|
* Returns a triangle wave between 0 and 1.
|
||||||
@ -1694,7 +1694,7 @@ export class UserAPI {
|
|||||||
freq: number = 1,
|
freq: number = 1,
|
||||||
times: number = 1,
|
times: number = 1,
|
||||||
offset: number = 0,
|
offset: number = 0,
|
||||||
duty: number = 0.5
|
duty: number = 0.5,
|
||||||
): number => {
|
): number => {
|
||||||
/**
|
/**
|
||||||
* Returns a square wave with a specified duty cycle between -1 and 1.
|
* Returns a square wave with a specified duty cycle between -1 and 1.
|
||||||
@ -1714,7 +1714,7 @@ export class UserAPI {
|
|||||||
freq: number = 1,
|
freq: number = 1,
|
||||||
times: number = 1,
|
times: number = 1,
|
||||||
offset: number = 0,
|
offset: number = 0,
|
||||||
duty: number = 0.5
|
duty: number = 0.5,
|
||||||
): number => {
|
): number => {
|
||||||
/**
|
/**
|
||||||
* Returns a square wave between 0 and 1.
|
* Returns a square wave between 0 and 1.
|
||||||
@ -1774,7 +1774,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
const sum = values.reduce(
|
const sum = values.reduce(
|
||||||
(accumulator, currentValue) => accumulator + currentValue,
|
(accumulator, currentValue) => accumulator + currentValue,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
return sum / values.length;
|
return sum / values.length;
|
||||||
};
|
};
|
||||||
@ -1784,7 +1784,7 @@ export class UserAPI {
|
|||||||
yMin: number,
|
yMin: number,
|
||||||
yMax: number,
|
yMax: number,
|
||||||
xMin: number,
|
xMin: number,
|
||||||
xMax: number
|
xMax: number,
|
||||||
): number => {
|
): number => {
|
||||||
const percent = (inputY - yMin) / (yMax - yMin);
|
const percent = (inputY - yMin) / (yMax - yMin);
|
||||||
const outputX = percent * (xMax - xMin) + xMin;
|
const outputX = percent * (xMax - xMin) + xMin;
|
||||||
@ -1814,7 +1814,7 @@ export class UserAPI {
|
|||||||
lang: string = "en-US",
|
lang: string = "en-US",
|
||||||
voice: number = 0,
|
voice: number = 0,
|
||||||
rate: number = 1,
|
rate: number = 1,
|
||||||
pitch: number = 1
|
pitch: number = 1,
|
||||||
): void => {
|
): void => {
|
||||||
/*
|
/*
|
||||||
* Speaks the given text using the browser's speech synthesis API.
|
* Speaks the given text using the browser's speech synthesis API.
|
||||||
@ -1889,7 +1889,7 @@ export class UserAPI {
|
|||||||
const elements = args.slice(1); // Get the rest of the arguments as an array
|
const elements = args.slice(1); // Get the rest of the arguments as an array
|
||||||
const timepos = this.app.clock.pulses_since_origin;
|
const timepos = this.app.clock.pulses_since_origin;
|
||||||
const slice_count = Math.floor(
|
const slice_count = Math.floor(
|
||||||
timepos / Math.floor(chunk_size * this.ppqn())
|
timepos / Math.floor(chunk_size * this.ppqn()),
|
||||||
);
|
);
|
||||||
return elements[slice_count % elements.length];
|
return elements[slice_count % elements.length];
|
||||||
};
|
};
|
||||||
@ -1917,7 +1917,7 @@ export class UserAPI {
|
|||||||
// =============================================================
|
// =============================================================
|
||||||
|
|
||||||
register = (name: string, operation: EventOperation<AbstractEvent>): void => {
|
register = (name: string, operation: EventOperation<AbstractEvent>): void => {
|
||||||
AbstractEvent.prototype[name] = function(
|
AbstractEvent.prototype[name] = function (
|
||||||
this: AbstractEvent,
|
this: AbstractEvent,
|
||||||
...args: any[]
|
...args: any[]
|
||||||
) {
|
) {
|
||||||
@ -2024,7 +2024,7 @@ export class UserAPI {
|
|||||||
".cm-comment": {
|
".cm-comment": {
|
||||||
fontFamily: commentFont,
|
fontFamily: commentFont,
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export const drawCircle = (
|
|||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
radius: number,
|
radius: number,
|
||||||
color: string
|
color: string,
|
||||||
): void => {
|
): void => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const canvas: HTMLCanvasElement = app.interface.feedback;
|
const canvas: HTMLCanvasElement = app.interface.feedback;
|
||||||
@ -36,7 +36,7 @@ export const blinkScript = (
|
|||||||
*/
|
*/
|
||||||
app: Editor,
|
app: Editor,
|
||||||
script: "local" | "global" | "init",
|
script: "local" | "global" | "init",
|
||||||
no?: number
|
no?: number,
|
||||||
) => {
|
) => {
|
||||||
if (no !== undefined && no < 1 && no > 9) return;
|
if (no !== undefined && no < 1 && no > 9) return;
|
||||||
const blinkDuration =
|
const blinkDuration =
|
||||||
@ -55,7 +55,7 @@ export const blinkScript = (
|
|||||||
horizontalOffset + shift,
|
horizontalOffset + shift,
|
||||||
app.interface.feedback.clientHeight - 15,
|
app.interface.feedback.clientHeight - 15,
|
||||||
8,
|
8,
|
||||||
"#fdba74"
|
"#fdba74",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ export const blinkScript = (
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(app.interface.feedback as HTMLCanvasElement).width,
|
(app.interface.feedback as HTMLCanvasElement).width,
|
||||||
(app.interface.feedback as HTMLCanvasElement).height
|
(app.interface.feedback as HTMLCanvasElement).height,
|
||||||
);
|
);
|
||||||
}, blinkDuration);
|
}, blinkDuration);
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ let lastRenderTime: number = 0;
|
|||||||
|
|
||||||
export const runOscilloscope = (
|
export const runOscilloscope = (
|
||||||
canvas: HTMLCanvasElement,
|
canvas: HTMLCanvasElement,
|
||||||
app: Editor
|
app: Editor,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Runs the oscilloscope visualization on the provided canvas element.
|
* Runs the oscilloscope visualization on the provided canvas element.
|
||||||
@ -157,7 +157,7 @@ export const runOscilloscope = (
|
|||||||
width: number,
|
width: number,
|
||||||
height: number,
|
height: number,
|
||||||
offset_height: number,
|
offset_height: number,
|
||||||
offset_width: number
|
offset_width: number,
|
||||||
) {
|
) {
|
||||||
const maxFPS = 30;
|
const maxFPS = 30;
|
||||||
const now = performance.now();
|
const now = performance.now();
|
||||||
@ -172,11 +172,11 @@ export const runOscilloscope = (
|
|||||||
|
|
||||||
const performanceFactor = 1;
|
const performanceFactor = 1;
|
||||||
const reducedDataSize = Math.floor(
|
const reducedDataSize = Math.floor(
|
||||||
freqDataArray.length * performanceFactor
|
freqDataArray.length * performanceFactor,
|
||||||
);
|
);
|
||||||
const numBars = Math.min(
|
const numBars = Math.min(
|
||||||
reducedDataSize,
|
reducedDataSize,
|
||||||
app.osc.orientation === "horizontal" ? width : height
|
app.osc.orientation === "horizontal" ? width : height,
|
||||||
);
|
);
|
||||||
const barWidth =
|
const barWidth =
|
||||||
app.osc.orientation === "horizontal" ? width / numBars : height / numBars;
|
app.osc.orientation === "horizontal" ? width / numBars : height / numBars;
|
||||||
@ -189,7 +189,7 @@ export const runOscilloscope = (
|
|||||||
for (let i = 0; i < numBars; i++) {
|
for (let i = 0; i < numBars; i++) {
|
||||||
barHeight = Math.floor(
|
barHeight = Math.floor(
|
||||||
freqDataArray[Math.floor((i * freqDataArray.length) / numBars)] *
|
freqDataArray[Math.floor((i * freqDataArray.length) / numBars)] *
|
||||||
((height / 256) * app.osc.size)
|
((height / 256) * app.osc.size),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (app.osc.orientation === "horizontal") {
|
if (app.osc.orientation === "horizontal") {
|
||||||
@ -197,7 +197,7 @@ export const runOscilloscope = (
|
|||||||
x + offset_width,
|
x + offset_width,
|
||||||
(height - barHeight) / 2 + offset_height,
|
(height - barHeight) / 2 + offset_height,
|
||||||
barWidth + 1,
|
barWidth + 1,
|
||||||
barHeight
|
barHeight,
|
||||||
);
|
);
|
||||||
x += barWidth;
|
x += barWidth;
|
||||||
} else {
|
} else {
|
||||||
@ -205,7 +205,7 @@ export const runOscilloscope = (
|
|||||||
(width - barHeight) / 2 + offset_width,
|
(width - barHeight) / 2 + offset_width,
|
||||||
y + offset_height,
|
y + offset_height,
|
||||||
barHeight,
|
barHeight,
|
||||||
barWidth + 1
|
barWidth + 1,
|
||||||
);
|
);
|
||||||
y += barWidth;
|
y += barWidth;
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ export const runOscilloscope = (
|
|||||||
-OFFSET_WIDTH,
|
-OFFSET_WIDTH,
|
||||||
-OFFSET_HEIGHT,
|
-OFFSET_HEIGHT,
|
||||||
WIDTH + 2 * OFFSET_WIDTH,
|
WIDTH + 2 * OFFSET_WIDTH,
|
||||||
HEIGHT + 2 * OFFSET_HEIGHT
|
HEIGHT + 2 * OFFSET_HEIGHT,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ export const runOscilloscope = (
|
|||||||
-OFFSET_WIDTH,
|
-OFFSET_WIDTH,
|
||||||
-OFFSET_HEIGHT,
|
-OFFSET_HEIGHT,
|
||||||
WIDTH + 2 * OFFSET_WIDTH,
|
WIDTH + 2 * OFFSET_WIDTH,
|
||||||
HEIGHT + 2 * OFFSET_HEIGHT
|
HEIGHT + 2 * OFFSET_HEIGHT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
canvasCtx.lineWidth = app.osc.thickness;
|
canvasCtx.lineWidth = app.osc.thickness;
|
||||||
|
|||||||
@ -48,7 +48,10 @@ export class Clock {
|
|||||||
lastPlayPressTime: number;
|
lastPlayPressTime: number;
|
||||||
totalPauseTime: number;
|
totalPauseTime: number;
|
||||||
|
|
||||||
constructor(public app: Editor, ctx: AudioContext) {
|
constructor(
|
||||||
|
public app: Editor,
|
||||||
|
ctx: AudioContext,
|
||||||
|
) {
|
||||||
this.time_position = { bar: 0, beat: 0, pulse: 0 };
|
this.time_position = { bar: 0, beat: 0, pulse: 0 };
|
||||||
this.time_signature = [4, 4];
|
this.time_signature = [4, 4];
|
||||||
this.logicalTime = 0;
|
this.logicalTime = 0;
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export const makeExampleFactory = (application: Editor): Function => {
|
|||||||
const make_example = (
|
const make_example = (
|
||||||
description: string,
|
description: string,
|
||||||
code: string,
|
code: string,
|
||||||
open: boolean = false
|
open: boolean = false,
|
||||||
) => {
|
) => {
|
||||||
const codeId = `codeExample${application.exampleCounter++}`;
|
const codeId = `codeExample${application.exampleCounter++}`;
|
||||||
// Store the code snippet in the data structure
|
// Store the code snippet in the data structure
|
||||||
@ -160,7 +160,7 @@ export const updateDocumentationContent = (app: Editor, bindings: any) => {
|
|||||||
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
|
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
|
||||||
});
|
});
|
||||||
const converted_markdown = converter.makeHtml(
|
const converted_markdown = converter.makeHtml(
|
||||||
app.docs[app.currentDocumentationPane]
|
app.docs[app.currentDocumentationPane],
|
||||||
);
|
);
|
||||||
document.getElementById("documentation-content")!.innerHTML =
|
document.getElementById("documentation-content")!.innerHTML =
|
||||||
converted_markdown;
|
converted_markdown;
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const codeReplace = (code: string): string => {
|
|||||||
|
|
||||||
const tryCatchWrapper = async (
|
const tryCatchWrapper = async (
|
||||||
application: Editor,
|
application: Editor,
|
||||||
code: string
|
code: string,
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
/**
|
/**
|
||||||
* Wraps the provided code in a try-catch block and executes it.
|
* Wraps the provided code in a try-catch block and executes it.
|
||||||
@ -20,7 +20,7 @@ const tryCatchWrapper = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await new Function(`"use strict"; ${codeReplace(code)}`).call(
|
await new Function(`"use strict"; ${codeReplace(code)}`).call(
|
||||||
application.api
|
application.api,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -48,7 +48,7 @@ const addFunctionToCache = (code: string, fn: Function) => {
|
|||||||
export const tryEvaluate = async (
|
export const tryEvaluate = async (
|
||||||
application: Editor,
|
application: Editor,
|
||||||
code: File,
|
code: File,
|
||||||
timeout = 5000
|
timeout = 5000,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
/**
|
/**
|
||||||
* Tries to evaluate the provided code within a specified timeout period.
|
* Tries to evaluate the provided code within a specified timeout period.
|
||||||
@ -77,7 +77,7 @@ export const tryEvaluate = async (
|
|||||||
if (isCodeValid) {
|
if (isCodeValid) {
|
||||||
code.committed = code.candidate;
|
code.committed = code.candidate;
|
||||||
const newFunction = new Function(
|
const newFunction = new Function(
|
||||||
`"use strict"; ${codeReplace(wrappedCode)}`
|
`"use strict"; ${codeReplace(wrappedCode)}`,
|
||||||
);
|
);
|
||||||
addFunctionToCache(candidateCode, newFunction);
|
addFunctionToCache(candidateCode, newFunction);
|
||||||
} else {
|
} else {
|
||||||
@ -93,7 +93,7 @@ export const tryEvaluate = async (
|
|||||||
export const evaluate = async (
|
export const evaluate = async (
|
||||||
application: Editor,
|
application: Editor,
|
||||||
code: File,
|
code: File,
|
||||||
timeout = 1000
|
timeout = 1000,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
/**
|
/**
|
||||||
* Evaluates the given code using the provided application and timeout.
|
* Evaluates the given code using the provided application and timeout.
|
||||||
@ -117,7 +117,7 @@ export const evaluate = async (
|
|||||||
|
|
||||||
export const evaluateOnce = async (
|
export const evaluateOnce = async (
|
||||||
application: Editor,
|
application: Editor,
|
||||||
code: string
|
code: string,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
/**
|
/**
|
||||||
* Evaluates the code once without any caching or error-handling mechanisms besides the tryCatchWrapper.
|
* Evaluates the code once without any caching or error-handling mechanisms besides the tryCatchWrapper.
|
||||||
|
|||||||
@ -154,7 +154,7 @@ export class AppSettings {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const settingsFromStorage = JSON.parse(
|
const settingsFromStorage = JSON.parse(
|
||||||
localStorage.getItem("topos") || "{}"
|
localStorage.getItem("topos") || "{}",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (settingsFromStorage && Object.keys(settingsFromStorage).length !== 0) {
|
if (settingsFromStorage && Object.keys(settingsFromStorage).length !== 0) {
|
||||||
@ -210,7 +210,7 @@ export class AppSettings {
|
|||||||
|
|
||||||
saveApplicationToLocalStorage(
|
saveApplicationToLocalStorage(
|
||||||
universes: Universes,
|
universes: Universes,
|
||||||
settings: Settings
|
settings: Settings,
|
||||||
): void {
|
): void {
|
||||||
/**
|
/**
|
||||||
* Main method to store the application to local storage.
|
* Main method to store the application to local storage.
|
||||||
@ -328,7 +328,7 @@ export const loadUniverserFromUrl = (app: Editor): void => {
|
|||||||
export const loadUniverse = (
|
export const loadUniverse = (
|
||||||
app: Editor,
|
app: Editor,
|
||||||
universeName: string,
|
universeName: string,
|
||||||
universe: Universe = template_universe
|
universe: Universe = template_universe,
|
||||||
): void => {
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Loads a universe into the application.
|
* Loads a universe into the application.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export function objectWithArraysToArrayOfObjects(
|
export function objectWithArraysToArrayOfObjects(
|
||||||
input: Record<string, any>,
|
input: Record<string, any>,
|
||||||
arraysToArrays: string[]
|
arraysToArrays: string[],
|
||||||
): Record<string, any>[] {
|
): Record<string, any>[] {
|
||||||
/*
|
/*
|
||||||
* Transforms object with arrays into array of objects
|
* Transforms object with arrays into array of objects
|
||||||
@ -24,7 +24,7 @@ export function objectWithArraysToArrayOfObjects(
|
|||||||
acc.keys.push(key);
|
acc.keys.push(key);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{ keys: [] as string[], maxLength: 0 }
|
{ keys: [] as string[], maxLength: 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
const output: Record<string, any>[] = [];
|
const output: Record<string, any>[] = [];
|
||||||
@ -44,7 +44,7 @@ export function objectWithArraysToArrayOfObjects(
|
|||||||
|
|
||||||
export function arrayOfObjectsToObjectWithArrays<T extends Record<string, any>>(
|
export function arrayOfObjectsToObjectWithArrays<T extends Record<string, any>>(
|
||||||
array: T[],
|
array: T[],
|
||||||
mergeObject: Record<string, any> = {}
|
mergeObject: Record<string, any> = {},
|
||||||
): Record<string, any> {
|
): Record<string, any> {
|
||||||
/*
|
/*
|
||||||
* Transforms array of objects into object with arrays
|
* Transforms array of objects into object with arrays
|
||||||
@ -54,21 +54,24 @@ export function arrayOfObjectsToObjectWithArrays<T extends Record<string, any>>(
|
|||||||
* @returns {object} Merged object with arrays
|
* @returns {object} Merged object with arrays
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
return array.reduce((acc, obj) => {
|
return array.reduce(
|
||||||
const mergedObj = { ...obj, ...mergeObject };
|
(acc, obj) => {
|
||||||
Object.keys(mergedObj).forEach((key) => {
|
const mergedObj = { ...obj, ...mergeObject };
|
||||||
if (!acc[key]) {
|
Object.keys(mergedObj).forEach((key) => {
|
||||||
acc[key] = [];
|
if (!acc[key]) {
|
||||||
}
|
acc[key] = [];
|
||||||
acc[key].push(mergedObj[key]);
|
}
|
||||||
});
|
acc[key].push(mergedObj[key]);
|
||||||
return acc;
|
});
|
||||||
}, {} as Record<string, any>);
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, any>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterObject(
|
export function filterObject(
|
||||||
obj: Record<string, any>,
|
obj: Record<string, any>,
|
||||||
filter: string[]
|
filter: string[],
|
||||||
): Record<string, any> {
|
): Record<string, any> {
|
||||||
/*
|
/*
|
||||||
* Filter certain keys from object
|
* Filter certain keys from object
|
||||||
@ -79,6 +82,6 @@ export function filterObject(
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(obj).filter(([key]) => filter.includes(key))
|
Object.entries(obj).filter(([key]) => filter.includes(key)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,13 +32,13 @@ export const saveBeforeExit = (app: Editor): null => {
|
|||||||
export const installWindowBehaviors = (
|
export const installWindowBehaviors = (
|
||||||
app: Editor,
|
app: Editor,
|
||||||
window: Window,
|
window: Window,
|
||||||
preventMultipleTabs: boolean = false
|
preventMultipleTabs: boolean = false,
|
||||||
) => {
|
) => {
|
||||||
window.addEventListener("resize", () =>
|
window.addEventListener("resize", () =>
|
||||||
handleResize(app.interface.scope as HTMLCanvasElement)
|
handleResize(app.interface.scope as HTMLCanvasElement),
|
||||||
);
|
);
|
||||||
window.addEventListener("resize", () =>
|
window.addEventListener("resize", () =>
|
||||||
handleResize(app.interface.feedback as HTMLCanvasElement)
|
handleResize(app.interface.feedback as HTMLCanvasElement),
|
||||||
);
|
);
|
||||||
window.addEventListener("beforeunload", (event) => {
|
window.addEventListener("beforeunload", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -61,11 +61,11 @@ export const installWindowBehaviors = (
|
|||||||
if (e.key == "page_available") {
|
if (e.key == "page_available") {
|
||||||
document.getElementById("all")!.classList.add("invisible");
|
document.getElementById("all")!.classList.add("invisible");
|
||||||
alert(
|
alert(
|
||||||
"Topos is already opened in another tab. Close this tab now to prevent data loss."
|
"Topos is already opened in another tab. Close this tab now to prevent data loss.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
|
|
||||||
public updateValue<T>(
|
public updateValue<T>(
|
||||||
key: string,
|
key: string,
|
||||||
value: T | T[] | SoundParams[] | null
|
value: T | T[] | SoundParams[] | null,
|
||||||
): this {
|
): this {
|
||||||
if (value == null) return this;
|
if (value == null) return this;
|
||||||
this.values[key] = value;
|
this.values[key] = value;
|
||||||
@ -82,7 +82,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
a: number,
|
a: number,
|
||||||
d: number,
|
d: number,
|
||||||
s: number,
|
s: number,
|
||||||
r: number
|
r: number,
|
||||||
) {
|
) {
|
||||||
self.updateValue("fmattack", a);
|
self.updateValue("fmattack", a);
|
||||||
self.updateValue("fmdecay", d);
|
self.updateValue("fmdecay", d);
|
||||||
@ -106,7 +106,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
a: number,
|
a: number,
|
||||||
d: number,
|
d: number,
|
||||||
s: number,
|
s: number,
|
||||||
r: number
|
r: number,
|
||||||
) {
|
) {
|
||||||
self.updateValue("attack", a);
|
self.updateValue("attack", a);
|
||||||
self.updateValue("decay", d);
|
self.updateValue("decay", d);
|
||||||
@ -152,7 +152,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
a: number,
|
a: number,
|
||||||
d: number,
|
d: number,
|
||||||
s: number,
|
s: number,
|
||||||
r: number
|
r: number,
|
||||||
) {
|
) {
|
||||||
self.updateValue("lpenv", depth);
|
self.updateValue("lpenv", depth);
|
||||||
self.updateValue("lpattack", a);
|
self.updateValue("lpattack", a);
|
||||||
@ -198,7 +198,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
a: number,
|
a: number,
|
||||||
d: number,
|
d: number,
|
||||||
s: number,
|
s: number,
|
||||||
r: number
|
r: number,
|
||||||
) {
|
) {
|
||||||
self.updateValue("hpenv", depth);
|
self.updateValue("hpenv", depth);
|
||||||
self.updateValue("hpattack", a);
|
self.updateValue("hpattack", a);
|
||||||
@ -241,7 +241,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
a: number,
|
a: number,
|
||||||
d: number,
|
d: number,
|
||||||
s: number,
|
s: number,
|
||||||
r: number
|
r: number,
|
||||||
) {
|
) {
|
||||||
self.updateValue("bpenv", depth);
|
self.updateValue("bpenv", depth);
|
||||||
self.updateValue("bpattack", a);
|
self.updateValue("bpattack", a);
|
||||||
@ -336,7 +336,10 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(sound: string | string[] | SoundParams, public app: Editor) {
|
constructor(
|
||||||
|
sound: string | string[] | SoundParams,
|
||||||
|
public app: Editor,
|
||||||
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.nudge = app.dough_nudge / 100;
|
this.nudge = app.dough_nudge / 100;
|
||||||
|
|
||||||
@ -367,7 +370,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private processSound = (
|
private processSound = (
|
||||||
sound: string | string[] | SoundParams | SoundParams[]
|
sound: string | string[] | SoundParams | SoundParams[],
|
||||||
): SoundParams => {
|
): SoundParams => {
|
||||||
if (Array.isArray(sound) && typeof sound[0] === "string") {
|
if (Array.isArray(sound) && typeof sound[0] === "string") {
|
||||||
const s: string[] = [];
|
const s: string[] = [];
|
||||||
@ -438,7 +441,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
(event.key as number) || "C4",
|
(event.key as number) || "C4",
|
||||||
(event.pitch as number) || 0,
|
(event.pitch as number) || 0,
|
||||||
(event.parsedScale as number[]) || event.scale || "MAJOR",
|
(event.parsedScale as number[]) || event.scale || "MAJOR",
|
||||||
(event.octave as number) || 0
|
(event.octave as number) || 0,
|
||||||
);
|
);
|
||||||
event.note = note;
|
event.note = note;
|
||||||
event.freq = midiToFreq(note);
|
event.freq = midiToFreq(note);
|
||||||
@ -458,7 +461,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
public invert = (howMany: number = 0) => {
|
public invert = (howMany: number = 0) => {
|
||||||
if (this.values.chord) {
|
if (this.values.chord) {
|
||||||
let notes = this.values.chord.map(
|
let notes = this.values.chord.map(
|
||||||
(obj: { [key: string]: number }) => obj.note
|
(obj: { [key: string]: number }) => obj.note,
|
||||||
);
|
);
|
||||||
notes = howMany < 0 ? [...notes].reverse() : notes;
|
notes = howMany < 0 ? [...notes].reverse() : notes;
|
||||||
for (let i = 0; i < Math.abs(howMany); i++) {
|
for (let i = 0; i < Math.abs(howMany); i++) {
|
||||||
@ -500,7 +503,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
superdough(
|
superdough(
|
||||||
filteredEvent,
|
filteredEvent,
|
||||||
this.nudge - this.app.clock.deviation,
|
this.nudge - this.app.clock.deviation,
|
||||||
filteredEvent.dur
|
filteredEvent.dur,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class Player extends AbstractEvent {
|
|||||||
input: string | number | Generator<number>,
|
input: string | number | Generator<number>,
|
||||||
options: InputOptions,
|
options: InputOptions,
|
||||||
public app: Editor,
|
public app: Editor,
|
||||||
zid: string = ""
|
zid: string = "",
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
@ -159,7 +159,7 @@ export class Player extends AbstractEvent {
|
|||||||
if (this.areWeThereYet()) {
|
if (this.areWeThereYet()) {
|
||||||
const event = this.next() as Pitch | Chord | ZRest;
|
const event = this.next() as Pitch | Chord | ZRest;
|
||||||
const noteLengthInSeconds = this.app.clock.convertPulseToSecond(
|
const noteLengthInSeconds = this.app.clock.convertPulseToSecond(
|
||||||
event.duration * 4 * this.app.clock.ppqn
|
event.duration * 4 * this.app.clock.ppqn,
|
||||||
);
|
);
|
||||||
if (event instanceof Pitch) {
|
if (event instanceof Pitch) {
|
||||||
const obj = event.getExisting(
|
const obj = event.getExisting(
|
||||||
@ -169,7 +169,7 @@ export class Player extends AbstractEvent {
|
|||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
"parsedScale"
|
"parsedScale",
|
||||||
) as SoundParams;
|
) as SoundParams;
|
||||||
if (event.sound) name = event.sound as string;
|
if (event.sound) name = event.sound as string;
|
||||||
if (event.soundIndex) obj.n = event.soundIndex as number;
|
if (event.soundIndex) obj.n = event.soundIndex as number;
|
||||||
@ -184,14 +184,14 @@ export class Player extends AbstractEvent {
|
|||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
"parsedScale"
|
"parsedScale",
|
||||||
);
|
);
|
||||||
}) as SoundParams[];
|
}) as SoundParams[];
|
||||||
const add = { dur: noteLengthInSeconds } as SoundParams;
|
const add = { dur: noteLengthInSeconds } as SoundParams;
|
||||||
if (name) add.s = name;
|
if (name) add.s = name;
|
||||||
let sound = arrayOfObjectsToObjectWithArrays(
|
let sound = arrayOfObjectsToObjectWithArrays(
|
||||||
pitches,
|
pitches,
|
||||||
add
|
add,
|
||||||
) as SoundParams;
|
) as SoundParams;
|
||||||
return new SoundEvent(sound, this.app);
|
return new SoundEvent(sound, this.app);
|
||||||
} else if (event instanceof ZRest) {
|
} else if (event instanceof ZRest) {
|
||||||
@ -212,7 +212,7 @@ export class Player extends AbstractEvent {
|
|||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
"parsedScale"
|
"parsedScale",
|
||||||
) as MidiParams;
|
) as MidiParams;
|
||||||
if (event instanceof Pitch) {
|
if (event instanceof Pitch) {
|
||||||
if (event.soundIndex) obj.channel = event.soundIndex as number;
|
if (event.soundIndex) obj.channel = event.soundIndex as number;
|
||||||
|
|||||||
@ -20,11 +20,11 @@ Some features have been included as a bonus. These features are often about patt
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Hydra integration",
|
"Hydra integration",
|
||||||
`beat(4) :: hydra.osc(3, 0.5, 2).out()`,
|
`beat(4) :: hydra.osc(3, 0.5, 2).out()`,
|
||||||
true
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
Close the documentation to see the effect: ${key_shortcut(
|
Close the documentation to see the effect: ${key_shortcut(
|
||||||
"Ctrl+D"
|
"Ctrl+D",
|
||||||
)}! **Boom, all shiny!**
|
)}! **Boom, all shiny!**
|
||||||
|
|
||||||
Be careful not to call <ic>hydra</ic> too often as it can impact performances. You can use any rhythmical function like <ic>beat()</ic> function to limit the number of function calls. You can write any Topos code like <ic>[1,2,3].beat()</ic> to bring some life and movement in your Hydra sketches.
|
Be careful not to call <ic>hydra</ic> too often as it can impact performances. You can use any rhythmical function like <ic>beat()</ic> function to limit the number of function calls. You can write any Topos code like <ic>[1,2,3].beat()</ic> to bring some life and movement in your Hydra sketches.
|
||||||
@ -37,7 +37,7 @@ ${makeExample(
|
|||||||
beat(4) :: stop_hydra() // this one
|
beat(4) :: stop_hydra() // this one
|
||||||
beat(4) :: hydra.hush() // or this one
|
beat(4) :: hydra.hush() // or this one
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ You can change Hydra resolution using this simple method:
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Changing Hydra resolution",
|
"Changing Hydra resolution",
|
||||||
`hydra.setResolution(1024, 768)`,
|
`hydra.setResolution(1024, 768)`,
|
||||||
true
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
@ -82,7 +82,7 @@ beat(0.25)::gif({
|
|||||||
posX: ir(1,1200), // CSS Horizontal Position
|
posX: ir(1,1200), // CSS Horizontal Position
|
||||||
posY: ir(1, 800), // CSS Vertical Position
|
posY: ir(1, 800), // CSS Vertical Position
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)}
|
)}
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -65,12 +65,12 @@ On this page, you will find an exhaustive list of all the samples currently load
|
|||||||
A very large collection of wavetables for wavetable synthesis. This collection has been released by Kristoffer Ekstrand: [AKWF Waveforms](https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/). Every sound sample that starts with <ic>wt_</ic> will be looped. Look at this demo:
|
A very large collection of wavetables for wavetable synthesis. This collection has been released by Kristoffer Ekstrand: [AKWF Waveforms](https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/). Every sound sample that starts with <ic>wt_</ic> will be looped. Look at this demo:
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Wavetable synthesis made easy :)",
|
"Wavetable synthesis made easy :)",
|
||||||
`
|
`
|
||||||
beat(0.5)::sound('wt_stereo').n([0, 1].pick()).ad(0, .25).out()
|
beat(0.5)::sound('wt_stereo').n([0, 1].pick()).ad(0, .25).out()
|
||||||
`,
|
`,
|
||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
Pick one folder and spend some time exploring it. There is a lot of different waveforms.
|
Pick one folder and spend some time exploring it. There is a lot of different waveforms.
|
||||||
@ -84,12 +84,12 @@ ${samples_to_markdown(application, "Waveforms")}
|
|||||||
A set of 72 classic drum machines created by **Geikha**: [Geikha Drum Machines](https://github.com/geikha/tidal-drum-machines). To use them efficiently, it is best to use the <ic>.bank()</ic> parameter like so:
|
A set of 72 classic drum machines created by **Geikha**: [Geikha Drum Machines](https://github.com/geikha/tidal-drum-machines). To use them efficiently, it is best to use the <ic>.bank()</ic> parameter like so:
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Using a classic drum machine",
|
"Using a classic drum machine",
|
||||||
`
|
`
|
||||||
beat(0.5)::sound(['bd', 'cp'].pick()).bank("AkaiLinn").out()
|
beat(0.5)::sound(['bd', 'cp'].pick()).bank("AkaiLinn").out()
|
||||||
`,
|
`,
|
||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
Here is the complete list of available machines:
|
Here is the complete list of available machines:
|
||||||
|
|
||||||
@ -119,12 +119,12 @@ ${samples_to_markdown(application, "Amiga")}
|
|||||||
A collection of many different amen breaks. Use <ic>.stretch()</ic> to play with these:
|
A collection of many different amen breaks. Use <ic>.stretch()</ic> to play with these:
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Stretching an amen break",
|
"Stretching an amen break",
|
||||||
`
|
`
|
||||||
beat(4)::sound('amen1').stretch(4).out()
|
beat(4)::sound('amen1').stretch(4).out()
|
||||||
`,
|
`,
|
||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
The stretch should be adapted based on the length of each amen break.
|
The stretch should be adapted based on the length of each amen break.
|
||||||
|
|
||||||
|
|||||||
26
src/main.ts
26
src/main.ts
@ -246,7 +246,7 @@ export class Editor {
|
|||||||
* If any required elements or templates are missing, warning messages are logged and the function returns early.
|
* If any required elements or templates are missing, warning messages are logged and the function returns early.
|
||||||
*/
|
*/
|
||||||
let itemTemplate = document.getElementById(
|
let itemTemplate = document.getElementById(
|
||||||
"ui-known-universe-item-template"
|
"ui-known-universe-item-template",
|
||||||
) as HTMLTemplateElement;
|
) as HTMLTemplateElement;
|
||||||
if (!itemTemplate) {
|
if (!itemTemplate) {
|
||||||
console.warn("Missing template #ui-known-universe-item-template");
|
console.warn("Missing template #ui-known-universe-item-template");
|
||||||
@ -274,10 +274,10 @@ export class Editor {
|
|||||||
item
|
item
|
||||||
.querySelector(".delete-universe")
|
.querySelector(".delete-universe")
|
||||||
?.addEventListener("click", () =>
|
?.addEventListener("click", () =>
|
||||||
api._deleteUniverseFromInterface(it)
|
api._deleteUniverseFromInterface(it),
|
||||||
);
|
);
|
||||||
return item;
|
return item;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
existing_universes.innerHTML = "";
|
existing_universes.innerHTML = "";
|
||||||
@ -369,7 +369,7 @@ export class Editor {
|
|||||||
|
|
||||||
this.view.dispatch({
|
this.view.dispatch({
|
||||||
effects: this.chosenLanguage.reconfigure(
|
effects: this.chosenLanguage.reconfigure(
|
||||||
this.editor_mode == "notes" ? [markdown()] : [javascript()]
|
this.editor_mode == "notes" ? [markdown()] : [javascript()],
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ export class Editor {
|
|||||||
|
|
||||||
setButtonHighlighting(
|
setButtonHighlighting(
|
||||||
button: "play" | "pause" | "stop" | "clear",
|
button: "play" | "pause" | "stop" | "clear",
|
||||||
highlight: boolean
|
highlight: boolean,
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Sets the highlighting for a specific button.
|
* Sets the highlighting for a specific button.
|
||||||
@ -432,7 +432,7 @@ export class Editor {
|
|||||||
// All other buttons must lose the highlighting
|
// All other buttons must lose the highlighting
|
||||||
document
|
document
|
||||||
.querySelectorAll(
|
.querySelectorAll(
|
||||||
possible_selectors.filter((_, index) => index != selector).join(",")
|
possible_selectors.filter((_, index) => index != selector).join(","),
|
||||||
)
|
)
|
||||||
.forEach((button) => {
|
.forEach((button) => {
|
||||||
button.children[0].classList.remove("animate-pulse");
|
button.children[0].classList.remove("animate-pulse");
|
||||||
@ -478,28 +478,28 @@ export class Editor {
|
|||||||
*/
|
*/
|
||||||
const domElement = this.view.dom;
|
const domElement = this.view.dom;
|
||||||
const gutters = domElement.getElementsByClassName(
|
const gutters = domElement.getElementsByClassName(
|
||||||
"cm-gutter"
|
"cm-gutter",
|
||||||
) as HTMLCollectionOf<HTMLElement>;
|
) as HTMLCollectionOf<HTMLElement>;
|
||||||
|
|
||||||
domElement.classList.add("fluid-bg-transition");
|
domElement.classList.add("fluid-bg-transition");
|
||||||
Array.from(gutters).forEach((gutter) =>
|
Array.from(gutters).forEach((gutter) =>
|
||||||
gutter.classList.add("fluid-bg-transition")
|
gutter.classList.add("fluid-bg-transition"),
|
||||||
);
|
);
|
||||||
|
|
||||||
domElement.style.backgroundColor = color;
|
domElement.style.backgroundColor = color;
|
||||||
Array.from(gutters).forEach(
|
Array.from(gutters).forEach(
|
||||||
(gutter) => (gutter.style.backgroundColor = color)
|
(gutter) => (gutter.style.backgroundColor = color),
|
||||||
);
|
);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
domElement.style.backgroundColor = "";
|
domElement.style.backgroundColor = "";
|
||||||
Array.from(gutters).forEach(
|
Array.from(gutters).forEach(
|
||||||
(gutter) => (gutter.style.backgroundColor = "")
|
(gutter) => (gutter.style.backgroundColor = ""),
|
||||||
);
|
);
|
||||||
|
|
||||||
domElement.classList.remove("fluid-bg-transition");
|
domElement.classList.remove("fluid-bg-transition");
|
||||||
Array.from(gutters).forEach((gutter) =>
|
Array.from(gutters).forEach((gutter) =>
|
||||||
gutter.classList.remove("fluid-bg-transition")
|
gutter.classList.remove("fluid-bg-transition"),
|
||||||
);
|
);
|
||||||
}, duration);
|
}, duration);
|
||||||
}
|
}
|
||||||
@ -507,7 +507,7 @@ export class Editor {
|
|||||||
private initializeElements(): void {
|
private initializeElements(): void {
|
||||||
for (const [key, value] of Object.entries(singleElements)) {
|
for (const [key, value] of Object.entries(singleElements)) {
|
||||||
this.interface[key] = document.getElementById(
|
this.interface[key] = document.getElementById(
|
||||||
value
|
value,
|
||||||
) as ElementMap[keyof ElementMap];
|
) as ElementMap[keyof ElementMap];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,7 +515,7 @@ export class Editor {
|
|||||||
private initializeButtonGroups(): void {
|
private initializeButtonGroups(): void {
|
||||||
for (const [key, ids] of Object.entries(buttonGroups)) {
|
for (const [key, ids] of Object.entries(buttonGroups)) {
|
||||||
this.buttonElements[key] = ids.map(
|
this.buttonElements[key] = ids.map(
|
||||||
(id) => document.getElementById(id) as HTMLButtonElement
|
(id) => document.getElementById(id) as HTMLButtonElement,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user