7.8.162-stable Switch to dev

SDK Web

Introduction

GreyCat’s Web SDK is available here @greycat/web and features:

  • Built on top of the Web Component standards and Shoelace
  • Tight integration with GreyCat std library
  • Provides several production-ready components for: charting, forms, virtual tables, etc.

Project Setup

Scaffold a new project with VitePlus+:

vp create github:datathings/greycat-web-template
cd your-project
vp run setup

vp run setup fetches the latest GreyCat core and @greycat/web versions and updates project.gcl and package.json automatically. It also runs pnpm install and greycat install.

The template uses the greycat() VitePlus+ plugin (in vite.config.ts) to configure multi-page app support, relative URLs, and API proxying to the GreyCat backend.

JSX is optional. @greycat/web works with plain document.createElement() or JSX — pick whichever fits the situation. See the Advanced Web App tutorial for examples of both.

How it works

When importing @greycat/web every Web Component that it defines will then be registered globally as Custom Elements.

Because some of those components communicate with GreyCat internally, we need to tell them where to find the current instance. For this, the @greycat/sdk and more generally @greycat/web leverage global scope. All the functions and components that need to communicate directly with GreyCat will look for a GreyCat instance at globalThis.greycat.default.

This implies that the only “initialization” that is needed is the following:

import "@greycat/web";

await gc.sdk.init();

// here you can safely use all of @greycat/web

Components

We offer a range of web components within the web SDK. Please check the Web Components section for further details or use the list below to jump directly to the various components.

Global Timezone

To define the global timezone used by all WebComponents set it at initialization:

import "@greycat/web";

// at initialization
const greycat = await gc.sdk.init({ timezone: "Europe/Luxembourg" });
// or at runtime
greycat.timezone = gc.core.TimeZone["Europe/Luxembourg"];

Formatting (Numbers)

All GUI elements leverage the same instance of Intl for the display of dates and numbers

If you wish to override them, you can initialize GreyCat with a specific formatter or modify it at runtime on the GreyCat instance:

// at initialization
const greycat = await gc.sdk.init({
  numFmt: new Intl.NumberFormat("de-DE", { maximumFractionDigits: 2 }),
});
// or at runtime
greycat.numFmt = new Intl.NumberFormat("de-DE", { maximumFractionDigits: 2 });

Shoelace

Underneath, most of our components leverage Shoelace components. Specifically, all the gui-input components use sl-input. If you wish to style them, refer to the Shoelace documentation.

By default, @greycat/web also comes with all Shoelace components already imported. You don’t require any extra configuration; once our library is imported, you are free to use any of Shoelace’s components.

You can access Shoelace by importing sl from @greycat/web, in case you need to change internal configuration, for example to set a custom icon library.

import { sl } from "@greycat/web";

sl.registerIconLibrary("default", {
  resolver: (name) => `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.0.0/icons/${name}.svg`,
});

d3

The d3.js library is also exposed

import { d3 } from "@greycat/web";

Maplibregl

GreyCat comes with a component gui-map that relies on maplibre-gl in order to work. This library is not vendored with @greycat/web, so you must ensure that maplibregl is globally available prior to initializing the SDK:

import "@greycat/web";
import maplibregl from "maplibre-gl";

await gc.sdk.init({ maplibregl });

Running @expose function as a task

Alternatively, you can spawn a task rather than synchronously execute the function.

import "@greycat/web";

await gc.sdk.init();

// spawns the task (returns a handle immediately)
const task = await gc.project.inc.spawn();

// ...do other work while the task runs in the background...

// wait for the task to complete and get the result
const count = await task.result();

This pattern is ideal when you want to queue multiple tasks or overlap task execution with other work.