A collection of Svelte components and utilities for WebApp, RESTApp and Widget configurations.
Installation
Section titled “Installation”Install locally in your app:
npm install @soleil-se/config-svelteRead here for usage with TypeScript.
Components
Section titled “Components”Sitevision
Section titled “Sitevision”Wrappers for Sitevision components.
Regular inputs
Custom
Section titled “Custom”Custom components
Structure
Section titled “Structure”Only standard config:
DirectoryMyApp
Directoryconfig
- App.svelte
- config.js
Directorysrc/
- …
- …
With global config:
DirectoryMyApp
Directoryconfig
- App.svelte
- config.js
Directoryconfig_global
- App.svelte
- config.js
Directorysrc/
- …
- …
With server side code:
DirectoryMyApp
Directoryconfig
- App.svelte
- config.js
- index.js
Directorysrc/
- …
- …
Examples
Section titled “Examples”Using Sitevision default functions with name attributes as usual.
import { createConfigApp } from '@soleil-se/config-svelte';import { mount } from 'svelte';
import App from './App.svelte';
createConfigApp(({ target, props }) => mount(App, { target, props }));<script> import { Panel, InputField } from '@soleil-se/config-svelte';</script>
<Panel heading="Inställningar"> <InputField name="text" label="Text" /></Panel>import { createConfigApp } from '@soleil-se/config-svelte';
import App from './App.svelte';
createConfigApp(({ target, props }) => new App({ target, props }));<script> import { Panel, InputField } from '@soleil-se/config-svelte';</script>
<Panel heading="Inställningar"> <InputField name="text" label="Text" /></Panel>import { createConfigApp } from '@soleil-se/config-svelte';
import App from './App.svelte';
createConfigApp(App);<script> import { Panel, InputField } from '@soleil-se/config-svelte';</script>
<Panel heading="Inställningar"> <InputField name="text" label="Text" /></Panel>Advanced
Binding values. Sometimes you need full control over the data that is saved to the server, but usually the default functions are enough. Import a utility function that saves values to the server.
import { createConfigApp } from '@soleil-se/config-svelte';import { mount } from 'svelte';
import App from './App.svelte';
createConfigApp(({ target, props }) => mount(App, { target, props }));import { createConfigApp } from '@soleil-se/config-svelte';
import App from './App.svelte';
createConfigApp(({ target, props }) => new App({ target, props }));import { createConfigApp } from '@soleil-se/config-svelte';
import App from './App.svelte';
createConfigApp(App);<script> import { Panel, InputField } from '@soleil-se/config-svelte'; import { onSave } from '@soleil-se/config-svelte/utils';
// Values are available as a prop on root component export let values;
// Set default values if needed values = { text: '', ...values };
onSave(() => values);</script>
<Panel heading="Inställningar"> <InputField bind:value={values.text} label="Text" /></Panel>Saved values
Section titled “Saved values”The values object is available as a prop and CONFIG_VALUES global variable.
<script> import { Panel, InputField } from '@soleil-se/config-svelte';
let { values } = $props();
console.log(values, '===', window.CONFIG_VALUES);</script>
<Panel heading="Inställningar"> <InputField name="text" label="Text" /></Panel>The values object is available as a prop and CONFIG_VALUES global variable.
<script> import { Panel, InputField } from '@soleil-se/config-svelte';
export let values;
console.log(values, '===', window.CONFIG_VALUES);</script>
<Panel heading="Inställningar"> <InputField name="text" label="Text" /></Panel>Using saved values with TypeScript
Since 1.6.0Simple i18n utility for translating the configuration.
import { createI18n } from '@soleil-se/config-svelte/utils';
export default createI18n({ sv: { label: 'Välj sida', hello: 'Hej {name}!', }, no: { label: 'Velg side', hello: 'Hallo {name}!', }, en: { label: 'Select page', hello: 'Hello {name}!', },});<script> import { Panel, NodeSelector } from '@soleil-se/config-svelte'; import i18n from './i18n.js';
const hello = i18n('hello', { name: 'Foo' });</script>
<Panel> <NodeSelector name="page" type="page-selector" label={i18n('label')} /></Panel>generateId
Section titled “generateId”Generates a unique ID inside the configuration context.
Prefixed with input per default;
import { generateId } from '@soleil-se/config-svelte/utils';
const id = generateId(); // input_pcp61fn1uconst idCustomPrefix = generateId('foo'); // foo_pcp61fn1usetupComponent
Section titled “setupComponent”Triggers the setup-component event on the element with passed ID.
Read more on developer.sitevision.se
import { setupComponent } from '@soleil-se/config-svelte/utils';
setupComponent('myId');getAppProps
Section titled “getAppProps”Get props passed to the app when using server data.
import { getAppProps } from '@soleil-se/config-svelte/utils';
const appProps = getAppProps();const { myProp } = getAppProps();getAppContext
Section titled “getAppContext”Get app context value or object that is created for app when rendering with createAppContext.
import { getAppContext } from '@soleil-se/config-svelte/utils';
const appContext = getAppContext();const { siteName } = getAppContext();const siteName = getAppContext('siteName');fetchRestApi
Section titled “fetchRestApi”It’s not uncommon to need to fetch data from the REST-API in a configuration, for example to populate a dropdown.
This utility function is a wrapper around the native fetch that prefixes the URL, handles data format and the response.
| Param | Type | Default | Description |
|---|---|---|---|
| uri | String | URI path for the REST-API resource, e.g. ${nodeId}/properties | |
| [options] | Object | {} | Options object, two custom options, rest is standard fetch options |
| [options.data] | Object | {} | Data to be passed as JSON query parameter |
| [options.model] | 'offline' | 'online' | 'offline' | Selects which REST-API model path to use |
Returns: Promise<unknown> - Promise containing parsed JSON data.
Throws FetchError - Error object with status property, plus any additional JSON properties returned by the response.
import { fetchRestApi } from '@soleil-se/config-svelte/utils';
// GET – fetch node propertiesconst data = await fetchRestApi(`${nodeId}/properties`);
// GET – fetch node specific propertiesconst data = await fetchRestApi(`${nodeId}/properties`, { data: { properties: ['displayName', 'URL'] },});
// GET – fetch online (published) dataconst data = await fetchRestApi(`${nodeId}/properties`, { model: 'online' });Use inside a Svelte component with error handling:
<script> import { Panel, NodeSelector, SelectField } from '@soleil-se/config-svelte'; import { fetchRestApi } from '@soleil-se/config-svelte/utils';
let node = $state(undefined); let options = $state([]); let fetchError = $state(null);
async function onNodeChange() { fetchError = null; if (!node) return; try { const response = await fetchRestApi(`${node}/nodes`); options = (response ?? []).map(({ id, name }) => ({ value: id, label: name })); } catch (error) { console.error('Error fetching data:', error); fetchError = error; } }</script>
<Panel heading="Inställningar"> {#if fetchError} <p class="alert alert-danger" role="alert">Kunde inte ladda data ({fetchError.status}).</p> {/if} <NodeSelector name="node" label="Välj nod" on:change={onNodeChange} bind:value={node} /> <SelectField name="child" label="Välj barn" {options} /></Panel><script> import { Panel, NodeSelector, SelectField } from '@soleil-se/config-svelte'; import { fetchRestApi } from '@soleil-se/config-svelte/utils';
let node = undefined; let options = []; let fetchError = null;
async function onNodeChange() { fetchError = null; if (!node) return; try { const response = await fetchRestApi(`${node}/nodes`); options = (response ?? []).map(({ id, name }) => ({ value: id, label: name })); } catch (error) { console.error('Error fetching data:', error); fetchError = error; } }</script>
<Panel heading="Inställningar"> {#if fetchError} <p class="alert alert-danger" role="alert">Kunde inte ladda data ({fetchError.status}).</p> {/if} <NodeSelector name="node" label="Välj nod" on:change={onNodeChange} bind:value={node} /> <SelectField name="child" label="Välj barn" {options} /></Panel>onSave
Section titled “onSave”Runs the supplied callback when config is saved.
The callback should return the values to be saved as an Object.
import { onSave } from '@soleil-se/config-svelte/utils';
onSave(() => ({ foo: 'bar' }));pluckPrefix
Section titled “pluckPrefix”Plucks object properties with keys prefixed with ‘link’ and removes the prefix.
{ linkType, linkValue, linkNewWindow } will be converted to { type, value, newWindow }.
If no object is passed the saved config data from CONFIG_VALUES will be used.
Sitevision needs a flat object structure to manage ID
when exporting and importing a site.import { pluckPrefix } from '@soleil-se/config-svelte/utils';
const link1 = pluckPrefix('link'); // Will pluck from window.CONFIG_VALUESconst link2 = pluckPrefix('link', { linkType: 'internal', linkValue: '4.xxxx', linkNewWindow: false, willNotBePlucked: 'Wrong prefix' });addPrefix
Section titled “addPrefix”Prefixes keys in an object
{ type, value, newWindow } will be converted to { linkType, linkValue, linkNewWindow }.
Sitevision needs a flat object structure to manage ID
when exporting and importing a site.import { addPrefix } from '@soleil-se/config-svelte/utils';
const link = { type: 'internal', value: '4.xxxx', newWindow: false }const prefixed = addPrefix('link', link);Server
Section titled “Server”If you need to pass data from a server context to the app you can use the utility function createAppProps.
Data will be avalilable as props in the root component and with getAppProps.
import router from '@sitevision/api/common/router';import { createAppProps } from '@soleil-se/config-svelte/server';
router.get('/', (req, res) => { const props = { foo: 'bar', fizz: 'buzz', }; createAppProps(props, res);});import router from '@sitevision/api/common/router';import { createAppProps } from '@soleil-se/config-svelte/server';
router.get('/', (req, res) => { const props = { foo: 'bar', fizz: 'buzz', }; res.send(createAppProps(props));});import router from '@sitevision/api/common/router';import { createAppData } from '@soleil-se/config-svelte/server';
router.get('/', (req, res) => { const props = { foo: 'bar', fizz: 'buzz', }; res.send(createAppData(props));});<script> let { foo, fizz } = $props();</script>
<p>{foo}</p><p>{fizz}</p><script> export let foo; export let fizz;</script>
<p>{foo}</p><p>{fizz}</p>Context
Section titled “Context”Contains information about app context.
pageId- ID of current page.portletId- ID of current portlet.siteId- ID of site.siteName- Name of site.- @sitevision/api/server/appInfo
Is needed for some components to function.
import router from '@sitevision/api/common/router';import { createAppContext } from '@soleil-se/config-svelte/server';
router.get('/', (req, res) => { createAppContext(res);});<script> import { getAppContext } from '@soleil-se/config-svelte/utils';
const { siteName } = getAppContext()</script>
<h1>{siteName}</h1>Global configuration
Section titled “Global configuration”For global configuration to work you need an index.html file in the global folder with a div where the app can be mounted.
This file is added automatically when using @soleil-se/app-build.
Validation
Section titled “Validation”All components are compatible with @soleil-se/config-validate.