@valnivo_labs/widgets
| Install | |
|---|---|
npm install @valnivo_labs/widgets |
|
| Latest Version: | 0.3.2 |
| Vue: | 3 |
| License: | Custom |
| Last Updated: | Sep 27, 2026 |
| Links: | npm |
@valnivo_labs/widgets
Financial calculators as components: a projection, a mortgage, a loan, rent against buying, a card at its minimum, and seventeen more. Standalone by choice — the calculators run in your own page and make no network request of any kind, so they keep working whatever happens to us.
npm install @valnivo_labs/widgets
Two modes, and the trade between them
render(el, { widget: 'projection' }) // standalone: the calculator, in your page
mount(el, { widget: 'projection' }) // framed: an iframe on valnivo.eu
Standalone (/standalone) |
Framed (the default export) | |
|---|---|---|
| Needs valnivo.eu | No — never | Yes, at view time |
| If valnivo.eu goes away | Keeps working | Shows an empty frame |
| Fixes to a model | When you npm update |
Immediately, with no update |
| Weight | ~54 kB gzipped, loaded on demand | ~1 kB |
| Isolation | Closed shadow root | Cross-origin iframe |
| Server rendering | Client-side only | Client-side only |
No font files are bundled. Inter is what valnivo.eu serves; standalone falls back to
system-ui so the package stays 54 kB rather than 500, and so it fetches nothing. Load the face
yourself if you want it — the widget will use it.
Pick standalone if the page must not depend on us. That is what it is for: a dependency should outlive the person who published it. Pick framed if you would rather a correction to an arithmetic model reach your visitors the day it ships.
Where it runs
| Framed | Standalone | |
|---|---|---|
| React 17, 18, 19 | ✓ | React-DOM 18+ (createRoot) |
| Vue 3.0 – 3.5 | ✓ | ✓ |
Angular 2 – 21, via <valnivo-widget> + CUSTOM_ELEMENTS_SCHEMA |
✓ | ✓ |
| Svelte, Solid, Lit, Astro, plain HTML, via the same element | ✓ | ✓ |
| Next.js, Nuxt, SvelteKit | ✓ client-side | ✓ client-side |
| Node / SSR | renders on hydration | renders on hydration |
| Browsers | anything with <iframe> |
anything with shadow DOM — Chrome/Edge 53+, Firefox 63+, Safari 10+ |
React, React-DOM and Vue are optional peer dependencies: install only the one your project already has. The custom element needs none of them.
Nothing about your page or your visitor reaches Valnivo, in either mode. Standalone makes no
request at all — no frame, no fetch, no font, no beacon. Framed, the iframe sends no referrer and
the widget's own policy is connect-src 'none'. Neither touches storage, and there is one
implementation of every calculation behind both, so the two cannot disagree about an answer.
React
import { ValnivoWidget } from '@valnivo_labs/widgets/react'
<ValnivoWidget widget="projection" params={{ currency: 'EUR', locale: 'fr-LU', have: 40000, save: 500 }} />
Vue 3
<script setup>
import { ValnivoWidget } from '@valnivo_labs/widgets/vue'
</script>
<template>
<ValnivoWidget widget="loan" :params="{ currency: 'EUR', years: 7 }" />
</template>
Angular
Angular's own route for a component from outside its compiler is a custom element, so the Angular
entry defines <valnivo-widget> and needs nothing from @angular/core and no compilation — it
works in an AOT build as it is.
// main.ts, once
import '@valnivo_labs/widgets/angular'
// a standalone component
@Component({
selector: 'app-savings',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<valnivo-widget widget="projection" [params]="figures"></valnivo-widget>`,
})
export class SavingsComponent {
figures = { currency: 'EUR', have: 40000, save: 500 }
}
[params] is a property binding: a new object re-points the frame. In an NgModule application,
CUSTOM_ELEMENTS_SCHEMA goes in the module's schemas.
Svelte, Solid, Lit, Astro, plain HTML — the custom element
<script type="module">import 'https://cdn.example/@valnivo_labs/widgets/element.js'</script>
<valnivo-widget widget="mortgage" params='{"currency":"EUR","years":25}'></valnivo-widget>
The params attribute takes JSON; the params property takes an object, which is what a
framework binding sets. Changing widget, origin, height or title makes a new frame;
changing params re-points the existing one.
Standalone, in any framework
import { render } from '@valnivo_labs/widgets/standalone'
const handle = render(document.getElementById('box'), {
widget: 'projection',
params: { have: 40000, save: 500 },
currency: 'EUR',
locale: 'fr-LU', // how numbers are written
lang: 'fr', // the words: en (default), fr, de, es, it, pt, nl, pl
theme: 'auto', // dark (default), light, or auto
})
handle.update({ have: 50000 })
handle.destroy()
The translations ship in the package, one small chunk per language, loaded only when a lang
other than English is asked for — from wherever your bundler serves the rest of the package, never
from us. The words are page-wide: a page has one language, and the last lang given is the one
every standalone calculator on it shows.
In a component, pass standalone:
<ValnivoWidget standalone widget="projection" params={{ have: 40000 }} />
<valnivo-widget standalone widget="mortgage" currency="EUR"></valnivo-widget>
It renders into a closed shadow root: our styles cannot reach your page, yours cannot reach
ours, and element.shadowRoot is null. The Valnivo mark and each calculator's "an illustration,
not a forecast or advice" line are inside it and are put back if anything removes them — a
white-label licence is the one way the mark comes off.
Anything else
import { mount } from '@valnivo_labs/widgets'
const handle = mount(document.getElementById('box'), { widget: 'mortgage', params: { currency: 'EUR' } })
handle.update({ years: 25 })
handle.destroy()
Parameters are the documented ones — currency, locale, lang, theme, accent, and each
calculator's own figures — at https://valnivo.eu/developers.html#params. locale decides how numbers
are written and lang the language of the words (en, the default, fr, de, es, it, pt,
nl or pl); they are separate on purpose, so { locale: 'fr-LU' } alone stays in English. widget="page" with widgets= composes
several in one frame, exactly as the loader does.
Conditions of use
The same as the loader's: https://valnivo.eu/developers.html#rules — see LICENSE.md.
Related Packages
Cord Elements: cotizador embebible con Shadow DOM, Builder headless dirigido por...
Native Web Component chat widget with complete CSS isolation using Shadow DOM
Framework-agnostic Web Component for Azure Voice Live interactive avatar assista...
Version History
| Version | Released | License |
|---|---|---|
| 0.3.2 | Custom | |
| 0.3.1 | Custom | |
| 0.3.0 | Custom | |
| 0.2.2 | Custom | |
| 0.2.1 | Custom | |
| 0.2.0 | Custom | |
| 0.1.0 | Custom |