kasperikoski / gaugestan-js
Prebuilt browser assets for the dependency-free Gaugestan.js SVG gauge instrument library.
Package info
github.com/kasperikoski/Gaugestan.js
Language:JavaScript
pkg:composer/kasperikoski/gaugestan-js
Requires
- php: >=8.1
README
Gaugestan.js is a lightweight, dependency-free, extensible analog gauge library built with native SVG, JavaScript, and a small optional CSS file.
Gaugestan.js includes eight gauge types:
arc: a clean semicircular gauge with configurable colored or transparent sectors;classic: a framed, white, old-style instrument meter;classic-linear: a cream-faced vintage instrument with a travelling linear indicator;center-zero: a cream heritage bidirectional dial whose resting reference is centered at zero;classic-linear-zero: the framed classic linear instrument with a fixed zero reference;heritage-round: a circular vintage instrument built from the shared classic layers;line-scale: a tick-focused gauge with independently configurable major and minor scale lines;rolling-tape: a heritage aircraft-style moving number tape behind a fixed edge-to-edge reference line.
The runtime has no image, jQuery, canvas, or framework dependency. It can be used from a classic <script> tag, an ES module, a custom element, React, Twig, Blade, or another server-rendered application.
Current release:
1.0.0
Why SVG
SVG is used as the default renderer because it is resolution-independent, responsive without device-pixel-ratio bookkeeping, easy to theme with CSS, accessible through normal DOM attributes, and efficient for the relatively small number of vector elements used by analog gauges. Static parts are rendered once. During animation, Gaugestan.js normally updates only the active pointer, linear indicator, or rolling tape slots together with readout text and the ARIA value.
Browser installation with separate files
This is the recommended browser installation. It keeps JavaScript and CSS separately cacheable.
<link rel="stylesheet" href="gaugestan.min.css"> <div id="score-gauge"></div> <script src="gaugestan.umd.min.js"></script> <script> const gauge = Gaugestan.createGauge('#score-gauge', { type: 'arc', min: 0, max: 3000, value: 625, zones: [ { min: 0, max: 500, color: '#ef4444' }, { min: 500, max: 1000, color: '#facc15' }, { min: 1000, max: 2100, color: '#22c55e' }, { min: 2100, max: 2500, color: '#facc15' }, { min: 2500, max: 3000, color: '#ef4444' } ] }); gauge.setValue(1420); </script>
Open example.html directly in a browser to see all eight built-in types, live controls,
and a four-instrument customization gallery that replaces preset colors entirely through options.
One-file standalone browser installation
The standalone bundle exposes the same window.Gaugestan API and injects the complete
responsive stylesheet automatically. The stable #gaugestan-styles marker ensures that
the stylesheet is injected only once.
<div id="gauge"></div> <script src="gaugestan.standalone.min.js"></script> <script> Gaugestan.createGauge('#gauge', { type: 'classic', value: 72 }); </script>
The standalone and separate-file builds are generated from the same canonical
src/gaugestan.css source. Neither contains a separately maintained CSS copy.
Native browser ES module
<link rel="stylesheet" href="./dist/gaugestan.css"> <div id="temperature"></div> <script type="module"> import Gaugestan, { createGauge } from './dist/gaugestan.esm.js'; const gauge = createGauge(document.querySelector('#temperature'), { type: 'classic', min: -20, max: 120, value: 68, readout: { title: { visible: true, text: 'COOLANT' }, unit: { visible: true, text: '°C' } } }); console.log(Gaugestan.VERSION); </script>
npm installation
npm install gaugestan.js@1.0.0
import { createGauge } from 'gaugestan.js'; import 'gaugestan.js/css'; const gauge = createGauge('#gauge', { type: 'arc', value: 64 });
npm consumers receive prebuilt JavaScript, CSS, declarations, and source maps.
Applications normally do not modify anything in dist/.
CommonJS
const { createGauge } = require('gaugestan.js'); const gauge = createGauge(document.querySelector('#gauge'), { value: 64 });
CDN installation
Use exact versions in production. CDN consumers need no installation or compilation.
jsDelivr, recommended two-file installation
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gaugestan.js@1.0.0/dist/gaugestan.min.css" > <script src="https://cdn.jsdelivr.net/npm/gaugestan.js@1.0.0/dist/gaugestan.umd.min.js" ></script>
jsDelivr, one-file installation
<script src="https://cdn.jsdelivr.net/npm/gaugestan.js@1.0.0/dist/gaugestan.standalone.min.js" ></script>
UNPKG
<link rel="stylesheet" href="https://unpkg.com/gaugestan.js@1.0.0/dist/gaugestan.min.css" > <script src="https://unpkg.com/gaugestan.js@1.0.0/dist/gaugestan.umd.min.js" ></script>
The UNPKG one-file equivalent is
https://unpkg.com/gaugestan.js@1.0.0/dist/gaugestan.standalone.min.js.
Built-in gauge gallery
Arc zones. A clean semicircular gauge with configurable colored sectors, tapered zones, and true transparent gaps.
Classic instrument. A framed white instrument with a glass highlight, fine scale markings, and a traditional spear pointer.
Heritage round. A circular vintage instrument built from the shared classic face, bezel, scale, and pointer layers.
Line scale. A tick-focused gauge with independently configurable major divisions, minor ticks, labels, and pointer styling.
Classic linear instrument. A cream-faced vintage scale with configurable zones, fine ticks, and a travelling hairline indicator.
Center zero. A signed bidirectional dial with a fixed center reference and pointer movement on both sides of zero.
Classic linear center zero. The classic linear instrument with a permanent zero marker and signed indicator travel in both directions.
Heritage rolling tape. An aircraft-style numeric tape that moves behind a fixed edge-to-edge reference line.
Customization example
Rose balance. The heritage center-zero instrument recolored entirely through ordinary Gaugestan.js configuration options.
Minimal configuration
Only the target and value are required in ordinary use. Every gauge type supplies its own visual defaults.
const gauge = Gaugestan.createGauge('#gauge', { type: 'line-scale', value: 72 });
True transparent zones
A zone with color: 'transparent', color: 'none', or no color creates a real gap. The base track is not drawn under that interval unless track.showUnderZones is explicitly enabled.
zones: [ { min: 0, max: 25, color: '#ef4444' }, { min: 25, max: 40, color: 'transparent' }, { min: 40, max: 80, color: '#22c55e' }, { min: 80, max: 100, color: '#facc15' } ]
For compatibility with Gauge.js-style configuration, strokeStyle is accepted as an alias for a zone's color.
Radial zones may also taper smoothly. width remains the uniform fallback, while
taper.startWidth and taper.endWidth define the thickness at the zone's numeric
min and max endpoints. The direction therefore follows the value mapping even when
invert is enabled:
zones: [ { min: 0, max: 60, color: '#06b6d4', width: 18, taper: { startWidth: 0, endWidth: 36, segments: 56 } } ]
segments controls curve smoothness and is clamped between 2 and 256. Tapered zones
are rendered as filled SVG annular segments because a native SVG stroke cannot change
width along one path. Uniform zones continue to use the lighter stroke representation.
Inverted scales
Set the top-level invert option to true to mirror the value direction while keeping
the configured geometry unchanged. The minimum and maximum swap visual endpoints, and
ticks, labels, zones, and the pointer all follow the same value-based mapping:
createGauge('#fuel', { type: 'heritage-round', min: 0, max: 100, invert: true });
invert defaults to false. Zones remain defined with their normal numeric min and
max values; low-value warning zones therefore move automatically with the inverted
scale and do not need to be rewritten.
Major and minor ticks
scale: { radius: 124, position: 'inside', // inside, outside, or cross major: { interval: 20, // explicit value interval divisions: 5, // used only when interval is null length: 24, width: 2.5, color: '#111827' }, minor: { subdivisions: 4, // four minor lines between major ticks length: 11, width: 1, color: '#64748b' } }
Pointer types
Built-in pointer shapes are:
needle: traditional tapered needle;line: rounded line pointer;arrow: arrow-shaped pointer;spear: vintage instrument pointer.
pointer: { type: 'spear', length: 98, shaftLength: 67, // optional; null preserves the type-specific shape tailLength: 14, width: 9, color: '#111827', colorByZone: false, cap: { visible: true, stackOrder: 'above', // above or below the pointer shape radius: 9, color: '#20242a', strokeColor: '#ffffff', strokeWidth: 2 } }
Built-in gauge types paint their pointer or linear indicator after the readout, so it
always crosses above title, value, and unit text. Caps default to
stackOrder: 'above'. A custom type can use 'below' when its pointer should cross
over the center cap. This uses deterministic SVG paint order rather than CSS
z-index.
Classic linear instrument
classic-linear reuses the classic cream panel, bezel, glass, readouts, scale
configuration, zones, animation, jitter, and accessibility lifecycle. Its value moves a
straight indicator instead of rotating a pointer:
createGauge('#signal', { type: 'classic-linear', min: 0, max: 100, value: 62, linear: { originY: 142, startX: 38, startY: 0, endX: 282, endY: 0, tickSide: 'negative', labelOffset: 38, zoneOffset: -16 }, indicator: { type: 'hairline', // hairline | marker | carriage position: 'cross', length: 84, centerOffset: 0, // positive moves upward on a horizontal axis width: 2.4, cap: { visible: false } }, zones: [ { min: 0, max: 20, color: '#b91c1c' }, { min: 20, max: 70, color: 'transparent' }, { min: 70, max: 100, color: '#15803d' } ] });
The axis is defined by two points, so custom types may use horizontal, vertical, or
diagonal linear scales. Linear Y coordinates use a Cartesian convention around
linear.originY: 0 is the preset baseline, positive values move upward, and negative
values move downward. X coordinates continue to increase to the right. The built-in
classic-linear fallback therefore uses startY: 0, endY: 0, and title y: 60.
labelOffset, zoneOffset, and indicator.centerOffset use the same positive-up
convention for a left-to-right horizontal scale. invert: true reverses value direction
without changing axis or zone definitions. Major and minor tick lengths remain
independently configurable through scale.major.length and scale.minor.length.
Center-zero and rolling-tape gauges
The specialized built-ins use the same lifecycle, animation, jitter, zones, accessibility, responsive layout, and runtime update API as the other instruments.
The cream-faced radial center-zero preset keeps an automatically symmetric range
around a custom reference value. Its title is an ordinary readout part and defaults
between the pointer hub and the lower numeric value; readout.title.x and
readout.title.y can move it anywhere in the dial:
createGauge('#trim', { type: 'center-zero', min: -50, max: 50, value: 12, centerZero: { zeroValue: 0, symmetric: true, marker: { color: '#5b4636', length: 26, width: 3 } } });
For a straight scale, classic-linear-zero reuses the complete classic linear face,
axis, ticks, labels, zones, indicator, clipping, and sizing system. It adds only a fixed
zero-reference layer:
createGauge('#deviation', { type: 'classic-linear-zero', min: -100, max: 100, value: -28, geometry: { width: 520, height: 220 }, centerZero: { zeroValue: 0, symmetric: true, marker: { visible: true, length: 34, centerOffset: 0 } } });
rolling-tape keeps an edge-to-edge reference line fixed while the numerical scale
moves smoothly underneath it. Its cream face is only a preset: every face, window,
strip, tick, label, fade, reference-line, and zone color remains configurable.
createGauge('#altitude', { type: 'rolling-tape', geometry: { width: 300, height: 480 }, min: 0, max: 10000, value: 4250, tape: { interval: 2000, minorSubdivisions: 3, majorSpacing: 58, stripColor: '#fff9ea', textColor: '#211f1a', indicatorColor: '#991b1b', windowInnerStrokeColor: '#d8cfbd' }, readout: { title: { visible: true, text: 'ALTITUDE' }, value: { visible: true, x: 150, y: 390 }, unit: { visible: true, text: 'FT' } } });
The optional separate tape value uses the same independently configurable x and y
coordinates as every other readout part. It may be hidden when the moving tape itself
is the only numeric display required.
All three presets accept normal updateOptions() calls, invert, custom formatters,
custom CSS classes, and per-zone colors. Omitting an option always falls back to the
type preset.
Warning lights and annunciators
Every built-in gauge type can host the shared optional light layer. The lamp is SVG,
so its coordinates and radius scale with the gauge viewBox, it respects framed face
clipping, and it remains correctly positioned at every rendered size. The component is
disabled by default.
createGauge('#fuel', { type: 'heritage-round', min: 0, max: 100, value: 12, light: { visible: true, x: 93, y: 110, radius: 8, glowRadius: 20, glowSharpness: 0, glowOpacity: 0.15, color: 'red', offColor: '#f3ead6', pulse: false, blink: false, blinkInterval: 1000, flicker: true, flickerIntensity: 0.1, flickerGlowRadius: 0.1, flickerMinInterval: 45, flickerMaxInterval: 140, trigger: { mode: 'below', source: 'target', value: 15 } } });
Built-in palettes are red, green, blue, amber, yellow, orange,
white, halogen, cyan, and brown. Use customColor for an application-specific
active color. The unlit lamp deliberately uses a softly diffused cream lens rather than
a black bulb; offColor, offEdgeColor, bezelColor, and bezelHighlightColor can
customize that hardware appearance. radius controls the physical lamp while
glowRadius controls the halo independently and defaults to 20. Set it to null to
derive the halo radius from radius * 1.82. glowSharpness controls the halo blur:
0 uses a soft Gaussian glow, while 1 removes blur for a completely sharp
edge. Intermediate values reduce the blur continuously. glowOpacity controls only the
halo and defaults to 0.15, independently from the illuminated lens opacity.
The halo is painted below the opaque lamp hardware, so it becomes visible beyond the
lamp edges instead of covering the lens. pulse adds a deliberately subtle steady-light
breathing effect. blink alternates the complete illuminated and unlit lens states, so
the dark half-cycle looks exactly like the normal switched-off lamp rather than a faded
transparent bulb. Blink takes precedence if both blink and pulse are enabled.
flicker adds rapid random changes to the amount of emitted light. flickerIntensity
sets the maximum random loss from full light: 0 is steady and 1 may momentarily
reach the real unlit-lens appearance. It never darkens the lit lens toward black.
flickerGlowRadius independently varies the halo radius by a relative plus/minus amount:
with glowRadius: 20, the default 0.1 produces radii between 18 and 22.
Each change waits a random duration between flickerMinInterval and
flickerMaxInterval. Flicker is independent and may be combined with
either pulse or blink. Flicker is enabled by default, but has no visual effect while the
lamp is hidden or inactive. Trigger modes are manual, below, above, and between. The trigger source
defaults to target, so a low-value lamp does not flash merely because a startup
animation begins at the minimum. Use displayed to follow the animated readout value
or pointer to include visual jitter. For linear gauges, light.y follows the same
positive-up coordinate convention as the linear axis.
opacity controls only the illuminated lens layered over an always-opaque unlit lens.
The physical lamp and bezel therefore remain fully visible even at opacity: 0;
glowOpacity remains the separate control for the halo.
Custom types can opt in with Gaugestan.layers.light; all built-in types already include
the layer and use the same shared light defaults. The lamp remains disabled until
light.visible is true. The interactive example.html explicitly enables blink and
disables flicker for its heritage-round demonstration.
Intrinsic dimensions and host sizing
classic-linear, classic-linear-zero, and rolling-tape can change their internal
instrument proportions through geometry.width and geometry.height. The type's
configuration hook scales only fallback geometry; any explicitly supplied coordinate
remains authoritative. geometry.aspectRatio may derive the missing dimension:
createGauge('#wide-signal', { type: 'classic-linear', geometry: { width: 560, aspectRatio: 2.8 } });
These logical dimensions control composition and the SVG viewBox. Page layout can still size any gauge host independently with normal CSS. Gaugestan provides optional custom properties for common integrations:
#wide-signal { --gaugestan-width: 100%; --gaugestan-height: 220px; --gaugestan-aspect-ratio: 14 / 5; }
Use layout.mode: 'contain' when both host width and height are constrained and the
whole instrument must scale inside that box. Leave the default intrinsic mode when
the SVG's natural aspect ratio should determine document height.
Optional readout text
The title, numeric value, and unit are independent SVG text elements. The numeric
value and unit are hidden by default so a gauge starts as a pure analog instrument.
x: 'auto' centers a part in its instrument reference box. y: 'auto' uses
position: 'top', center, or bottom, with optional margin, offsetX, and
offsetY. Offsets refine automatic placement only. Numeric coordinates are final
SVG positions for radial gauges. In linear gauges, numeric Y coordinates are relative
to linear.originY and increase upward, while numeric X coordinates increase rightward:
readout: { visible: true, title: { visible: true, text: 'PRESSURE', x: 160, y: 24 }, value: { visible: true, x: 160, y: 50, fractionDigits: 0 }, unit: { visible: true, text: 'kPa', x: 160, y: 72 } }
For the built-in arc type, the title defaults to x: 'auto', y: 35. An enabled
numeric value defaults to x: 160, y: 130, inside the arc between the upper scale
labels and the pointer pivot.
Custom arc sweep and responsive layout
geometry.startAngle and geometry.endAngle define the pointer and scale sweep.
For example, a centered 240-degree arc uses startAngle: 150 and endAngle: 390.
Interactive controls can use Gaugestan.geometry.centeredArcAngles(sweep, centerAngle): a
center angle of 0 means the normal upright orientation (internally SVG angle 270),
while positive values rotate clockwise. The difference may be configured up to 360
degrees. Full circles are rendered as two
SVG half-arcs, and the maximum tick/label endpoint is deduplicated by default so it
does not overlap the minimum endpoint.
The default layout.mode: 'intrinsic' computes a content-aware viewBox. Increasing a
sweep to 360 degrees therefore increases the gauge's natural height and pushes the
following document content down instead of overflowing it. Use layout.mode: 'contain'
when the host has an explicit CSS width and height and the complete instrument should
scale down to fit that box:
layout: { mode: 'contain', // intrinsic | contain padding: 10 }
Classic panel faces use face.fit: 'content', so the face expands when a larger sweep
or moved readout needs more drawing space. face.minWidth and face.minHeight define
optional lower limits for a content-fitted frame. The built-in framed instruments also
use face.clipContent: true, which clips pointers, indicators, zones, ticks, labels,
and readouts to the inner bezel instead of allowing them to overflow the frame.
Circular faces remain available through shape: 'circle' and the ready-made
heritage-round type.
Startup animation
animation: { enabled: true, duration: 900, easing: 'easeOutCubic', animateOnInit: true, startFrom: 'min', // min, max, value, or a number respectReducedMotion: true }
Set startFrom: 'value' or animateOnInit: false when the pointer must already be at its final position on first paint.
Realistic pointer jitter
Jitter is a pointer-like visual effect. It randomizes the radial pointer angle or linear indicator position without changing the readout, getValue(), getDisplayedValue(), accessibility value, or application data.
effects: { jitter: { enabled: true, amplitude: 0.8, amplitudeUnit: 'value', // value or percent frequency: 5, smoothing: 0.88, whenIdleOnly: true } }
Animation and jitter automatically pause when the page is hidden. They also pause when the gauge is offscreen when IntersectionObserver is available.
Updating an instance
gauge.setValue(76); gauge.setValue(18, { duration: 1400, easing: 'easeInOutCubic' }); gauge.setValue(50, { animate: false }); gauge.updateOptions({ pointer: { type: 'line', color: '#dc2626' }, labels: { fractionDigits: 1 } }); // Replace the complete instance configuration and discard earlier overrides. gauge.replaceOptions({ type: 'classic', min: 0, max: 100 }); gauge.pause(); gauge.resume(); gauge.refresh(); gauge.destroy();
set(value) and setOptions(options) are convenience aliases. updateOptions()
merges a partial patch, while replaceOptions() replaces the complete user-option
object and is useful for declarative framework adapters.
Data-attribute initialization
<div data-gaugestan data-gaugestan-type="arc" data-gaugestan-min="0" data-gaugestan-max="100" data-gaugestan-value="63" data-gaugestan-options='{"animation":{"startFrom":"value"}}' ></div> <script src="dist/gaugestan.umd.min.js"></script> <script> Gaugestan.autoMount(); </script>
Auto mounting is duplicate-safe.
Custom element
<script src="dist/gaugestan.umd.min.js"></script> <script>Gaugestan.defineGaugestanElement();</script> <gaugestan-gauge type="classic" min="0" max="240" value="88" options='{"readout":{"title":{"visible":true,"text":"VOLTAGE"}}}' ></gaugestan-gauge>
The value property or attribute can be changed later.
With npm, the same API is available through the explicit Web Component subpath:
import { defineGaugestanElement } from 'gaugestan.js/web-component'; import 'gaugestan.js/css'; defineGaugestanElement();
React
import { useState } from 'react'; import Gaugestan from 'gaugestan.js/react'; import 'gaugestan.js/css'; export default function DashboardGauge() { const [value, setValue] = useState(62); return ( <Gaugestan value={value} options={{ type: 'arc', min: 0, max: 100, zones: [ { min: 0, max: 40, color: '#ef4444' }, { min: 40, max: 75, color: '#facc15' }, { min: 75, max: 100, color: '#22c55e' } ] }} /> ); }
The React adapter is intentionally thin. React owns the host node and Gaugestan.js owns
only the generated content inside it. The published gaugestan.js/react entry is normal
browser-ready ESM JavaScript and does not require a package consumer to transpile JSX
inside node_modules. It replaces the complete options prop when that prop changes,
keeps an explicit value prop authoritative, destroys the instance on unmount, and
forwards a ref to the live Gauge instance.
Laravel, Twig, or plain PHP
Copy the prebuilt files into a public vendor directory, include the CSS and UMD bundle, and initialize from the page module. No PHP integration is required.
A Blade example is included in examples/laravel-blade.blade.php.
Composer distribution
The package includes Composer metadata and a cross-platform vendor binary.
composer require kasperikoski/gaugestan-js:^1.0 vendor/bin/gaugestan-install-assets public/assets/vendor/gaugestan
The default command copies the recommended gaugestan.umd.min.js and
gaugestan.min.css. Use --standalone for the one-file build, --all for all
browser assets, or --clean to remove only known old Gaugestan.js assets before
copying. Unrelated destination files are never removed.
Composer consumers receive prebuilt assets and do not need Node.js, npm, esbuild,
or a frontend compilation step. A consuming project can automate the explicit
asset command in its own composer.json:
{
"scripts": {
"assets:gaugestan": "vendor/bin/gaugestan-install-assets public/assets/vendor/gaugestan",
"post-install-cmd": [
"@assets:gaugestan"
],
"post-update-cmd": [
"@assets:gaugestan"
]
}
}
The dependency itself deliberately does not write into an application's public directory during Composer installation.
For server-rendered applications, install the assets into a versioned public vendor path, load them through the application's asset helper, and initialize gauges from a reusable module or duplicate-safe data-attribute initializer.
Extending gauge types
A type is a name, a defaults object, and an ordered array of layers. A layer renders static SVG and may return a small controller whose update(value, state) method is called for dynamic changes.
Gaugestan.registerGaugeType('football-score', { description: 'A compact score-performance meter.', defaults: { geometry: { startAngle: 200, endAngle: 340 }, pointer: { type: 'arrow', color: '#0f172a' }, readout: { title: { visible: true, text: 'FORM' } } }, layers: [ Gaugestan.layers.face, Gaugestan.layers.zones, Gaugestan.layers.ticks, Gaugestan.layers.labels, Gaugestan.layers.pointer, Gaugestan.layers.readout ] });
Custom layers can add SVG decorations, markers, secondary pointers, trend arrows, warning lights, or a completely different visual language without changing the animation core.
See docs/creating-gauge-types.md for a complete custom layer example.
Accessibility
The generated root uses role="meter" and receives aria-valuemin, aria-valuemax, and aria-valuenow. Provide a meaningful label and optional value text:
accessibility: { label: 'Prediction accuracy', description: 'Accuracy across the last 50 predictions.', valueText: (value) => `${Math.round(value)} percent accurate` }
Color should not be the only way to communicate meaning. Keep labels, text, or surrounding explanations available for important status information.
Browser support
Gaugestan.js targets current evergreen browsers with native SVG, ES2018+, requestAnimationFrame, and modern DOM APIs. The UMD build works as a classic script. The ESM build works in modern module-aware browsers and bundlers.
Optional optimizations degrade safely:
- no
IntersectionObserver: the gauge continues running while offscreen; - no
matchMedia: reduced-motion detection is skipped; - no
customElements: only the optional web-component adapter is unavailable.
Build and tests
Maintainers edit files in src/, adapters, tests, documentation, and build scripts.
Install the locked development toolchain and regenerate every distribution format:
npm ci
npm run clean
npm run build
npm run dev
npm run typecheck
npm test
npm run test:browser
npm run check
npm pack --dry-run
npm publish --dry-run
npm run build uses esbuild to recreate the complete dist/ directory, including
normal and minified ESM, UMD, CommonJS, standalone bundles, source maps, CSS,
declarations, and the manifest. npm run dev watches source files. npm run check
starts from a clean directory and runs the build, declaration validation, automated
tests, DOM smoke test, npm package-content dry run, and Composer validation when
Composer is available. prepublishOnly runs the same full check.
Minified files, source maps, embedded standalone CSS, declarations in dist/, and
other generated files must never be edited manually. Change their canonical sources
and run npm run build.
The optional npm run test:chromium command starts a temporary local HTTP server and
uses a globally available Chromium executable. It is intentionally separate from the
portable default checks.
Distribution policy
dist/ is intentionally committed. GitHub source downloads, Composer
installations, and CDN/npm consumers receive ready-to-use browser files
without requiring Node.js. CI runs a clean build and can detect differences in the
committed output. Package users receive prebuilt assets; only maintainers run the
distribution build.
Package layout
Gaugestan.js/
├── src/ Canonical modular source and CSS
├── dist/ Reproducible, committed distribution files
├── adapters/react/ Optional React adapter and declarations
├── docs/ Architecture, API, and development documentation
├── examples/ Framework and custom-type examples
├── tests/ Unit, DOM, packaging, and installer tests
├── scripts/ Build and local validation scripts
├── bin/ Composer asset installer
└── example.html Interactive standalone demonstration
Release metadata
Version: 1.0.0. npm package: gaugestan.js. Composer package:
kasperikoski/gaugestan-js. Repository: https://github.com/kasperikoski/Gaugestan.js.
Build and CI workflows validate release artifacts. Publishing to GitHub, npm, and Packagist is a manual maintainer action.
Contributing and security
Contribution setup and pull-request requirements are documented in
CONTRIBUTING.md. Report suspected vulnerabilities privately as described in
SECURITY.md; do not disclose them in public issues.
License
MIT License. See LICENSE.








