Skip to content
Open
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
1 change: 0 additions & 1 deletion apps/jamtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"license": "ISC",
"description": "",
"dependencies": {
"react-router-dom": "catalog:",
"springboard": "workspace:*",
"@jamtools/core": "workspace:*",
"@jamtools/features": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ springboard.registerModule('AppWithSplashScreen', {}, async (moduleAPI) => {
},
});

moduleAPI.registerRoute('/', {}, () => {
moduleAPI.registerRoute('/', () => {
return (
<AppWithSplashScreenComponent
message={messageState.useState()}
Expand Down
1 change: 1 addition & 0 deletions apps/small_apps/test_tanstack_app/test_tanstack_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@springboardjs/platforms-browser/test_tanstack_module';
2 changes: 1 addition & 1 deletion apps/small_apps/tic_tac_toe/tic_tac_toe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ springboard.registerModule('TicTacToe', {}, async (moduleAPI) => {
},
});

moduleAPI.registerRoute('/', {}, () => {
moduleAPI.registerRoute('/', () => {
return (
<TicTacToeBoard
board={boardState.useState()}
Expand Down
2 changes: 1 addition & 1 deletion doks/content/docs/introduction/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ springboard.registerModule('Main', {}, async (moduleAPI) => {
// });
});

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
return (
<div>
<input.components.edit/>
Expand Down
2 changes: 1 addition & 1 deletion doks/content/docs/jamtools/macro-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ springboard.registerModule('midi_thru', {}, async (moduleAPI) => {
myOutput.send(evt.event);
});

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
return (
<div>
<myInput.components.edit/>
Expand Down
2 changes: 1 addition & 1 deletion doks/content/docs/jamtools/midi-io-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ springboard.registerModule('Main', {}, async (moduleAPI) => {
mostRecentMidiEvent.setState(event);
});

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
const midiEvent = mostRecentMidiEvent.useState();

return (
Expand Down
30 changes: 21 additions & 9 deletions doks/content/docs/springboard/guides/registering-ui-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ seo:
---


Springboard currently uses React Router to register UI routes for the application. The plan is to move to [TanStack Router](https://tanstack.com/router) in the future for better type safety and more features.
Springboard currently uses [TanStack Router](https://tanstack.com/router) to register UI routes for the application.

The `moduleAPI.registerRoute` function allows modules to register their own routes. If the specified route begins with a `/`, it's assumed the route starts at the beginning of the URL. Otherwise, the URL is assumed to be relative to the URL `/modules/(module id)`.
There are two ways to register routes:

- The module can return a `routes` array of tanstack router routes. These are assumed to be relative to the root route.
- The `moduleAPI.registerRoute` function allows modules to register their own routes. This circumvents tanstack's type safety.

```jsx
import {useParams} from 'react-router';
import {createRoute} from '@tanstack/react-router';

springboard.registerModule('MyModule', async (moduleAPI) => {
// matches "" and "/"
Expand All @@ -38,24 +41,33 @@ springboard.registerModule('MyModule', async (moduleAPI) => {
});

// matches "/modules/MyModule/things/1"
moduleAPI.registerRoute('things/:thingId', () => {
const params = useParams();
const thingId = params.thingId;
moduleAPI.registerRoute('things/:thingId', ({pathParams}) => {
const thingId = pathParams.thingId;

return (
<div/>
);
});

// matches "/users/1"
moduleAPI.registerRoute('/users/:userId', {}, () => {
const params = useParams();
const userId = params.userId;
moduleAPI.registerRoute('/users/:userId', ({pathParams}) => {
const userId = pathParams.userId;

return (
<div/>
);
});

return {
routes: [
createRoute({
path: '/my-typed-route',
element: () => (
<div/>
),
}),
],
};
});
```

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"fix": "TURBO_NO_UPDATE_NOTIFIER=true turbo run fix",
"ci": "NODE_MODULES_PARENT_FOLDER=$PWD TURBO_NO_UPDATE_NOTIFIER=true turbo run lint check-types build test",
"heroku-postbuild": "NODE_ENV=production npm run build-saas",
"test-tanstack-app": "npx tsx packages/springboard/cli/src/cli.ts dev ./apps/small_apps/test_tanstack_app/test_tanstack_app.tsx",
"build-desktop": "RUN_SIDECAR_FROM_WEBVIEW=true npx tsx packages/springboard/cli/src/cli.ts build ./apps/jamtools/modules/index.ts --platforms desktop",
"build-all": "RUN_SIDECAR_FROM_WEBVIEW=true npx tsx packages/springboard/cli/src/cli.ts build ./apps/small_apps/empty_app/index.ts --platforms all",
"splash-screen-app": "npx tsx packages/springboard/cli/src/cli.ts dev ./apps/small_apps/app_with_splash_screen/app_with_splash_screen.tsx"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ springboard.registerModule('chord_families', {}, async (moduleAPI) => {
});
};

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
const state = rootModeState.useState();

const onClick = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/jamtools/core/modules/io/io_module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '@jamtools/core/modules';
import '@jamtools/core/modules/io/io_module';

import {Springboard} from 'springboard/engine/engine';
import {makeMockCoreDependencies, makeMockExtraDependences} from 'springboard/test/mock_core_dependencies';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,17 @@ export const getMacroInputTestHelpers = () => {
};

const gotoMacroPage = async () => {
const macroPageLink = screen.getByTestId('link-to-/modules/macro');
// const macroPageLink = container.querySelector('a[href="/modules/macro/"]');
expect(macroPageLink).toBeInTheDocument();
const router = (window as any).tsRouter;
if (!router) {
throw new Error('Router not found on window.tsRouter');
}

await act(async () => {
fireEvent.click(macroPageLink!);
await router.navigate({ to: '/modules/macro' });
});

await act(async () => {
await new Promise(r => setTimeout(r, 10));
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {act} from 'react';
import { screen } from 'shadow-dom-testing-library';
import '@testing-library/jest-dom';

import '@jamtools/core/modules';
import '@jamtools/core/modules/macro_module/macro_module';
import {Springboard} from 'springboard/engine/engine';
import springboard from 'springboard';

Expand All @@ -20,7 +20,7 @@ import {getMacroInputTestHelpers} from './macro_input_test_helpers';

describe('MusicalKeyboardInputMacroHandler', () => {
beforeEach(() => {
springboard.reset();
springboard.reset({keepCalls: true});
macroTypeRegistry.reset();
});

Expand Down
13 changes: 9 additions & 4 deletions packages/jamtools/core/modules/macro_module/macro_module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import springboard from 'springboard';
import {CapturedRegisterMacroTypeCall, MacroAPI, MacroCallback} from '@jamtools/core/modules/macro_module/registered_macro_types';
import {ModuleAPI} from 'springboard/engine/module_api';

import {createRoute} from '@tanstack/react-router';

import './macro_handlers';
import {macroTypeRegistry} from './registered_macro_types';
import {rootRoute} from 'springboard/ui/root_route';

type ModuleId = string;

Expand Down Expand Up @@ -52,14 +55,16 @@ export class MacroModule implements Module<MacroConfigState> {

constructor(private coreDeps: CoreDependencies, private moduleDeps: ModuleDependencies) { }

routes = {
'': {
routes = [
createRoute({
getParentRoute: () => rootRoute,
path: '/modules/macro',
component: () => {
const mod = MacroModule.use();
return <MacroPage state={mod.state || this.state} />;
},
},
};
}),
];

state: MacroConfigState = {
configs: {},
Expand Down
2 changes: 2 additions & 0 deletions packages/jamtools/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"module": "./src/index.ts",
"peerDependencies": {
"@springboardjs/platforms-browser": "workspace:*",
"@tanstack/react-router": "^1",
"@tonejs/midi": "^2.0.0",
"springboard": "workspace:*",
"svelte": ">= 5"
Expand All @@ -31,6 +32,7 @@
},
"devDependencies": {
"@springboardjs/platforms-browser": "workspace:*",
"@tanstack/react-router": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"react": "catalog:",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React from 'react';

import {Link} from 'react-router-dom';

import springboard from 'springboard';

import {ModuleAPI} from 'springboard/engine/module_api';
Expand All @@ -28,16 +26,16 @@ springboard.registerModule('Dashboards', {}, async (moduleAPI): Promise<Dashboar
const promises = allDashboards.map(d => d.dashboard(moduleAPI, d.id));
await Promise.all(promises);

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
return (
<div>
<h2>Dashboards:</h2>
<ul>
{allDashboards.map(d => (
<li key={d.id}>
<Link to={`/modules/Dashboards/${d.id}`}>
<a href={`/modules/Dashboards/${d.id}`}>
{d.label}
</Link>
</a>
</li>
))}
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ const KeytarAndFootDashboard = async (moduleAPI: ModuleAPI, dashboardName: strin
singleOctaveSupervisor.initialize(),
]);

moduleAPI.registerRoute('kiosk', {hideApplicationShell: true}, () => (
moduleAPI.registerRoute('kiosk', () => (
<singleOctaveSupervisor.renderKiosk/>
));

moduleAPI.registerRoute(dashboardName, {}, () => (
moduleAPI.registerRoute(dashboardName, () => (
<div>
<h1>
Keytar and Foot Dashboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type States = Awaited<ReturnType<typeof createStates>>;
type Macros = Awaited<ReturnType<typeof createMacros>>;

const registerRoutes = (moduleAPI: ModuleAPI, states: States, macros: Macros, actions: Actions) => {
moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
const myState = states.myState.useState();

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ springboard.registerModule('daw_interaction', {}, async (moduleAPI) => {
state.setState(args.value);
});

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
const sliderPosition1 = sliderPositionState1.useState();
const sliderPosition2 = sliderPositionState2.useState();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ springbord.registerModule('Eventide', {}, async (moduleAPI) => {
};

// hideNavbar should really be "hideApplicationShell", and also be a global option
moduleAPI.registerRoute('', {hideApplicationShell: false}, () => {
moduleAPI.registerRoute('', () => {
const currentPreset = currentPresetState.useState();
const favoritedPresets = favoritedPresetsState.useState();

Expand Down
2 changes: 1 addition & 1 deletion packages/jamtools/features/modules/hand_raiser_module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ springboard.registerModule('HandRaiser', {}, async (m) => {
},
});

m.registerRoute('/', {}, () => {
m.registerRoute('/', () => {
const positions = states.handPositions.useState();

return (
Expand Down
16 changes: 9 additions & 7 deletions packages/jamtools/features/modules/lighting/wled/wled_module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {BaseModule, ModuleHookValue} from 'springboard/modules/base_module/base_
import {Module} from 'springboard/module_registry/module_registry';

import springboard from 'springboard';
import {createRoute} from '@tanstack/react-router';
import {rootRoute} from 'springboard/ui/root_route';

type WledClientStatus = {
url: string;
Expand Down Expand Up @@ -47,19 +49,19 @@ export class WledModule implements Module<WledState> {

cleanup: (() => void)[] = [];

routes = {
'': {
routes = [
createRoute({
getParentRoute: () => rootRoute,
path: '/wled',
component: () => {
const mod = WledModule.use();

return (
<pre>
{JSON.stringify(mod.state)}
{JSON.stringify(this.state)}
</pre>
);
},
},
};
}),
];

// wled controllers need to be stored as hostnames,
// so they are readable and stay consistent for that controller
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ springboard.registerModule('MidiPlayback', {}, async (moduleAPI): Promise<MidiPl
savedMidiFileData.setState(args.data);
});

moduleAPI.registerRoute('', {hideApplicationShell: false}, () => {
moduleAPI.registerRoute('', () => {
const savedState = savedMidiFileData.useState();

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ springboard.registerModule('phone_jam', {}, async (moduleAPI) => {
}, 1000);
};

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
return (
<PhoneJamView
onClickPlaySound={playSound}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React from 'react';

import {Link} from 'react-router-dom';

import springboard from 'springboard';
import {MidiEvent} from '@jamtools/core/modules/macro_module/macro_module_types';

Expand Down Expand Up @@ -137,19 +135,19 @@ springboard.registerModule('song_structures_dashboards', {}, async (moduleAPI):
}
});

moduleAPI.registerRoute('', {}, () => {
moduleAPI.registerRoute('', () => {
return (
<div>
<Link to='/modules/song_structures_dashboards/bass_guitar'>
<a href='/modules/song_structures_dashboards/bass_guitar'>
<button>
Go to Bass Guitar
</button>
</Link>
</a>
</div>
);
});

moduleAPI.registerRoute('bass_guitar', {}, () => {
moduleAPI.registerRoute('bass_guitar', () => {
const props: React.ComponentProps<typeof GuitarTabView> = {
numberOfStrings: 4,
chosenFrets: [
Expand Down
Loading
Loading