React-based Toolkit for writing Panorama UI in the Source engine, inspired by Next.js
- Start writing Panorama components using React, no configuration required
- TypeScript compilation supported out of the box, includes definitions for most Panorama APIs
- Supports styled components including automatic extraction of static styles into external stylesheet files
- Includes PreCSS and CSS Modules, seamlessly import CSS files into JavaScript
- Automatically generates static XML layouts from your components and rehydrates them at runtime for better startup performances
In an empty directory, create a package.json
file with this content:
{
"name": "my-finnby-project",
"version": "1.0.0",
"scripts": {
"build": "finnby build",
"watch": "finnby watch"
},
"dependencies": {
"@team-abyss-p2/finnby": "0.2.0"
}
}
Run yarn install
or npm install
, and you'll be ready to create your first
component !
Create a new directory called components
and add a new .js
file (or .tsx
if you want to use TypeScript):
import * as React from "react";
import { Panel, Label } from "@team-abyss-p2/finnby";
export default function MyComponent() {
return (
<Panel style={{ width: "100%", height: "100%" }}>
<Label text="Hello World" />
</Panel>
);
}
If you run yarn run build
or npm run build
, Finnby will create a new code
directory in your project containing everything Panorama needs to run your new
panel. In addition to this generated code, you will need to patch your
base_jsregistration.xml
file to load the Finnby runtime for everything to work
correctly:
<root>
<scripts>
<include src="file://{resources}/scripts/common/panelregistration.js" />
<include src="file://{resources}/scripts/common/eventdefinition.js" />
<!-- Add this line -->
<include src="file://{resources}/scripts/common/finnby.js" />
</scripts>
<Panel hittest="false" />
</root>
In a development process, running the build command on every change is
fastidious so you might want to use yarn run watch
or npm run watch
instead:
it will start the Finnby CLI in watch mode, rebuilding your code automatically
on every change.
Now what if we want our panel to fade in when it get loaded ? In Panorama animations use CSS keyframes, but while Finnby does support importing CSS files it's generally simpler to declare the styles alongside the components using styled components:
import * as React from "react";
import { keyframes, styled, Label } from "@team-abyss-p2/finnby";
const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;
const AnimatedPanel = styled.Panel`
height: 100%;
width: 100%;
animation-name: ${fadeIn};
animation-duration: 750ms;
animation-timing-function: ease-out;
`;
export default function MyComponent() {
return (
<AnimatedPanel>
<Label text="Hello World" />
</AnimatedPanel>
);
}
During compilation Finnby will automatically analyze your JavaScript source files and pull all these styles into a CSS file that gets automatically imported into your layout
If you need more control on how the Finnby toolchain is configured, you can
create a finnby.config.js
file at the root of your workspace that supports the
following options:
module.exports = {
// Directory used to search for panel files
componentsDir: path.join(process.pwd(), "components"),
// Output directory for the compiled panels
outDir: path.join(process.pwd(), "code/panorama"),
// This function is passed the list of PostCSS plugins
// used to build the stylesheet files and can be used
// to add more as needed
postcss: (plugins) => plugins,
// This hook is passed the Rollup configuration used
// internally to build the panel bundles, and allows
// for fine configuration of the bundling options
rollup: (config) => config,
};
- Watch mode doesn't detect new components yet, the CLI needs to be restarted to pickup new files
- More / better TypeScript declarations: right now the ones included are extremely barebone
- The CLI is using Rollup as a bundler for simplicity since it's also what's used to package the CLI and runtime, but if the capabilities needed for hot reloading get unlocked in the engine this will get switched over to Metro.
- Automatically patch the
base_jsregistration.xml
file if it exists in the code directory, create it otherwise - Setup a
@team-abyss-p2/create-finnby
package to make bootstrapping a project even easier withyarn create @team-abyss-p2/finnby
ornpm create @team-abyss-p2/finnby
- Automatically create a
tsconfig.json
file in the project directory like create-react-app and next.js do if a.ts
or.tsx
file is detected to make moving to TypeScript easier