@aceshooting/lyra-ui 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -6
- package/custom-elements.json +12015 -0
- package/dist/components/chart/bar-chart.d.ts +14 -0
- package/dist/components/chart/bar-chart.js +14 -0
- package/dist/components/chart/box-plot.d.ts +46 -0
- package/dist/components/chart/box-plot.js +145 -0
- package/dist/components/chart/box-plot.styles.d.ts +1 -0
- package/dist/components/chart/box-plot.styles.js +22 -0
- package/dist/components/chart/bubble-chart.d.ts +19 -0
- package/dist/components/chart/bubble-chart.js +18 -0
- package/dist/components/chart/chart-loader.d.ts +8 -0
- package/dist/components/chart/chart-loader.js +26 -0
- package/dist/components/chart/chart.d.ts +91 -0
- package/dist/components/chart/chart.js +275 -0
- package/dist/components/chart/chart.styles.d.ts +1 -0
- package/dist/components/chart/chart.styles.js +33 -0
- package/dist/components/chart/doughnut-chart.d.ts +15 -0
- package/dist/components/chart/doughnut-chart.js +14 -0
- package/dist/components/chart/histogram-bin.d.ts +6 -0
- package/dist/components/chart/histogram-bin.js +19 -0
- package/dist/components/chart/histogram.d.ts +20 -0
- package/dist/components/chart/histogram.js +70 -0
- package/dist/components/chart/histogram.styles.d.ts +1 -0
- package/dist/components/chart/histogram.styles.js +1 -0
- package/dist/components/chart/line-chart.d.ts +14 -0
- package/dist/components/chart/line-chart.js +14 -0
- package/dist/components/chart/pie-chart.d.ts +16 -0
- package/dist/components/chart/pie-chart.js +15 -0
- package/dist/components/chart/polar-area-chart.d.ts +15 -0
- package/dist/components/chart/polar-area-chart.js +14 -0
- package/dist/components/chart/radar-chart.d.ts +15 -0
- package/dist/components/chart/radar-chart.js +14 -0
- package/dist/components/chart/scatter-chart.d.ts +15 -0
- package/dist/components/chart/scatter-chart.js +15 -0
- package/dist/components/combobox/combobox.d.ts +16 -0
- package/dist/components/combobox/combobox.js +113 -6
- package/dist/components/combobox/combobox.styles.js +68 -7
- package/dist/components/combobox/option.d.ts +2 -2
- package/dist/components/combobox/option.js +11 -7
- package/dist/components/date-picker/date-input.d.ts +12 -1
- package/dist/components/date-picker/date-input.js +68 -6
- package/dist/components/date-picker/date-input.styles.js +58 -6
- package/dist/components/date-picker/date-picker.js +5 -2
- package/dist/components/date-picker/date-picker.styles.js +9 -2
- package/dist/components/empty/empty.d.ts +1 -0
- package/dist/components/empty/empty.js +14 -2
- package/dist/components/export-button/csv.d.ts +10 -0
- package/dist/components/export-button/csv.js +28 -0
- package/dist/components/export-button/export-button.d.ts +41 -0
- package/dist/components/export-button/export-button.js +151 -0
- package/dist/components/export-button/export-button.styles.d.ts +1 -0
- package/dist/components/export-button/export-button.styles.js +79 -0
- package/dist/components/file-input/accept.d.ts +14 -0
- package/dist/components/file-input/accept.js +30 -0
- package/dist/components/file-input/file-input.d.ts +47 -0
- package/dist/components/file-input/file-input.js +182 -0
- package/dist/components/file-input/file-input.styles.d.ts +1 -0
- package/dist/components/file-input/file-input.styles.js +44 -0
- package/dist/components/flag/flag.d.ts +4 -0
- package/dist/components/flag/flag.js +24 -1
- package/dist/components/flag/flag.styles.js +1 -1
- package/dist/components/gauge/gauge.d.ts +29 -0
- package/dist/components/gauge/gauge.js +133 -0
- package/dist/components/gauge/gauge.styles.d.ts +1 -0
- package/dist/components/gauge/gauge.styles.js +60 -0
- package/dist/components/graph/graph.d.ts +68 -0
- package/dist/components/graph/graph.js +276 -0
- package/dist/components/graph/graph.styles.d.ts +1 -0
- package/dist/components/graph/graph.styles.js +34 -0
- package/dist/components/heatmap/heatmap-scale.d.ts +8 -0
- package/dist/components/heatmap/heatmap-scale.js +17 -0
- package/dist/components/heatmap/heatmap.d.ts +66 -0
- package/dist/components/heatmap/heatmap.js +252 -0
- package/dist/components/heatmap/heatmap.styles.d.ts +1 -0
- package/dist/components/heatmap/heatmap.styles.js +39 -0
- package/dist/components/map/map-loader.d.ts +8 -0
- package/dist/components/map/map-loader.js +17 -0
- package/dist/components/map/map.d.ts +49 -0
- package/dist/components/map/map.js +189 -0
- package/dist/components/map/map.styles.d.ts +1 -0
- package/dist/components/map/map.styles.js +48 -0
- package/dist/components/playback/playback.d.ts +51 -0
- package/dist/components/playback/playback.js +146 -0
- package/dist/components/playback/playback.styles.d.ts +1 -0
- package/dist/components/playback/playback.styles.js +40 -0
- package/dist/components/split/split.d.ts +41 -0
- package/dist/components/split/split.js +171 -0
- package/dist/components/split/split.styles.d.ts +1 -0
- package/dist/components/split/split.styles.js +51 -0
- package/dist/components/stat/stat.d.ts +9 -0
- package/dist/components/stat/stat.js +52 -7
- package/dist/components/stat/stat.styles.js +15 -5
- package/dist/components/table/table.d.ts +18 -6
- package/dist/components/table/table.js +76 -24
- package/dist/components/table/table.styles.js +32 -0
- package/dist/components/time-range/time-range.d.ts +40 -0
- package/dist/components/time-range/time-range.js +219 -0
- package/dist/components/time-range/time-range.styles.d.ts +1 -0
- package/dist/components/time-range/time-range.styles.js +78 -0
- package/dist/components/toast/toast-item.js +10 -2
- package/dist/components/toast/toast-item.styles.js +13 -4
- package/dist/components/toast/toast.styles.js +0 -1
- package/dist/components/tree/tree-node.d.ts +50 -0
- package/dist/components/tree/tree-node.js +196 -0
- package/dist/components/tree/tree.d.ts +65 -0
- package/dist/components/tree/tree.js +227 -0
- package/dist/components/tree/tree.styles.d.ts +1 -0
- package/dist/components/tree/tree.styles.js +13 -0
- package/dist/internal/form-associated.js +49 -1
- package/dist/internal/icons.d.ts +11 -0
- package/dist/internal/icons.js +64 -0
- package/dist/internal/tokens.styles.js +41 -1
- package/dist/lyra.d.ts +67 -0
- package/dist/lyra.js +55 -0
- package/llms-full.txt +1425 -0
- package/llms.txt +47 -0
- package/package.json +53 -4
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
/* Sequential ramp endpoints for the data-driven cell colors (canvas can't
|
|
6
|
+
consume var() directly, so heatmap.ts resolves these via
|
|
7
|
+
getComputedStyle and interpolates between them). Componentspecific
|
|
8
|
+
business color per Global Constraints — exposed so hosts can retheme
|
|
9
|
+
the ramp without raw hex leaking into the public API. */
|
|
10
|
+
--lyra-heatmap-scale-lo: #cde2fb;
|
|
11
|
+
--lyra-heatmap-scale-hi: #0969da;
|
|
12
|
+
}
|
|
13
|
+
[part='base'] {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: var(--lyra-space-xs);
|
|
17
|
+
}
|
|
18
|
+
canvas {
|
|
19
|
+
display: block;
|
|
20
|
+
inline-size: 100%;
|
|
21
|
+
}
|
|
22
|
+
[part='legend'] {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: var(--lyra-space-xs);
|
|
26
|
+
font-size: 0.75rem;
|
|
27
|
+
color: var(--lyra-color-text-quiet);
|
|
28
|
+
}
|
|
29
|
+
[part='legend'] .bar {
|
|
30
|
+
inline-size: 6rem;
|
|
31
|
+
block-size: 0.5rem;
|
|
32
|
+
border-radius: 2px;
|
|
33
|
+
background: linear-gradient(
|
|
34
|
+
to right,
|
|
35
|
+
var(--lyra-heatmap-scale-lo),
|
|
36
|
+
var(--lyra-heatmap-scale-hi)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as MaplibreModule from 'maplibre-gl';
|
|
2
|
+
/**
|
|
3
|
+
* Lazily loads the optional peer dependency `maplibre-gl` once per page.
|
|
4
|
+
* Resolves to `null` (with a one-time warning) if it isn't installed —
|
|
5
|
+
* mirrors `<lyra-flag>`'s peer-dependency pattern. Consumers must separately
|
|
6
|
+
* import `maplibre-gl/dist/maplibre-gl.css` once they install the peer.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadMaplibre(): Promise<typeof MaplibreModule | null>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
let maplibre;
|
|
2
|
+
/**
|
|
3
|
+
* Lazily loads the optional peer dependency `maplibre-gl` once per page.
|
|
4
|
+
* Resolves to `null` (with a one-time warning) if it isn't installed —
|
|
5
|
+
* mirrors `<lyra-flag>`'s peer-dependency pattern. Consumers must separately
|
|
6
|
+
* import `maplibre-gl/dist/maplibre-gl.css` once they install the peer.
|
|
7
|
+
*/
|
|
8
|
+
export function loadMaplibre() {
|
|
9
|
+
if (!maplibre) {
|
|
10
|
+
maplibre = import('maplibre-gl').catch(() => {
|
|
11
|
+
console.warn('<lyra-map> needs the optional peer dependency `maplibre-gl` — install it with ' +
|
|
12
|
+
'`pnpm add maplibre-gl` and import `maplibre-gl/dist/maplibre-gl.css` once in your app.');
|
|
13
|
+
return null;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return maplibre;
|
|
17
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import type { Map as MaplibreMap, StyleSpecification } from 'maplibre-gl';
|
|
3
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
4
|
+
import '../skeleton/skeleton.js';
|
|
5
|
+
export interface LegendEntry {
|
|
6
|
+
color: string;
|
|
7
|
+
label: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ChoroplethLayer {
|
|
10
|
+
sourceId: string;
|
|
11
|
+
geojson: GeoJSON.FeatureCollection;
|
|
12
|
+
field: string;
|
|
13
|
+
stops: [number, string][];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* `<lyra-map>` — a maplibre-gl wrapper with a declarative legend and
|
|
17
|
+
* choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
|
|
18
|
+
* optional peer dep `maplibre-gl` (consumers also import its CSS once).
|
|
19
|
+
*
|
|
20
|
+
* @customElement lyra-map
|
|
21
|
+
* @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
|
|
22
|
+
* @event lyra-map-click - `detail: { lngLat, feature? }`.
|
|
23
|
+
* @csspart base, container, legend, legend-swatch
|
|
24
|
+
*/
|
|
25
|
+
export declare class LyraMap extends LyraElement {
|
|
26
|
+
static styles: import("lit").CSSResultGroup[];
|
|
27
|
+
center: [number, number];
|
|
28
|
+
zoom: number;
|
|
29
|
+
mapStyle: StyleSpecification | string;
|
|
30
|
+
legend: LegendEntry[];
|
|
31
|
+
choropleth?: ChoroplethLayer;
|
|
32
|
+
/** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
|
|
33
|
+
private loading;
|
|
34
|
+
private containerEl?;
|
|
35
|
+
private _map?;
|
|
36
|
+
private _styleLoaded;
|
|
37
|
+
/** The raw `maplibregl.Map` instance — escape hatch for anything this wrapper doesn't expose. */
|
|
38
|
+
get map(): MaplibreMap | undefined;
|
|
39
|
+
connectedCallback(): void;
|
|
40
|
+
disconnectedCallback(): void;
|
|
41
|
+
protected updated(changed: PropertyValues): void;
|
|
42
|
+
private applyChoropleth;
|
|
43
|
+
render(): TemplateResult;
|
|
44
|
+
}
|
|
45
|
+
declare global {
|
|
46
|
+
interface HTMLElementTagNameMap {
|
|
47
|
+
'lyra-map': LyraMap;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/// <reference types="geojson" />
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
10
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
11
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
12
|
+
import { loadMaplibre } from './map-loader.js';
|
|
13
|
+
import { styles } from './map.styles.js';
|
|
14
|
+
import '../skeleton/skeleton.js';
|
|
15
|
+
const DEFAULT_STYLE = {
|
|
16
|
+
version: 8,
|
|
17
|
+
sources: {
|
|
18
|
+
'lyra-osm': {
|
|
19
|
+
type: 'raster',
|
|
20
|
+
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
|
|
21
|
+
tileSize: 256,
|
|
22
|
+
attribution: '© OpenStreetMap contributors',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
layers: [{ id: 'lyra-osm', type: 'raster', source: 'lyra-osm' }],
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* `<lyra-map>` — a maplibre-gl wrapper with a declarative legend and
|
|
29
|
+
* choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
|
|
30
|
+
* optional peer dep `maplibre-gl` (consumers also import its CSS once).
|
|
31
|
+
*
|
|
32
|
+
* @customElement lyra-map
|
|
33
|
+
* @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
|
|
34
|
+
* @event lyra-map-click - `detail: { lngLat, feature? }`.
|
|
35
|
+
* @csspart base, container, legend, legend-swatch
|
|
36
|
+
*/
|
|
37
|
+
export class LyraMap extends LyraElement {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(...arguments);
|
|
40
|
+
this.center = [0, 0];
|
|
41
|
+
this.zoom = 2;
|
|
42
|
+
this.mapStyle = DEFAULT_STYLE;
|
|
43
|
+
this.legend = [];
|
|
44
|
+
/** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
|
|
45
|
+
this.loading = true;
|
|
46
|
+
// Tracks whether the style has fired its initial 'load' (i.e. addSource/
|
|
47
|
+
// addLayer/setPaintProperty are now safe to call), rather than re-querying
|
|
48
|
+
// `this._map.isStyleLoaded()`: that also reflects in-flight *tile* loading
|
|
49
|
+
// for every source, so it flips back to `false` as soon as the choropleth's
|
|
50
|
+
// own GeoJSON source is added — which would wrongly block subsequent
|
|
51
|
+
// choropleth updates from ever re-running.
|
|
52
|
+
this._styleLoaded = false;
|
|
53
|
+
}
|
|
54
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
55
|
+
/** The raw `maplibregl.Map` instance — escape hatch for anything this wrapper doesn't expose. */
|
|
56
|
+
get map() {
|
|
57
|
+
return this._map;
|
|
58
|
+
}
|
|
59
|
+
connectedCallback() {
|
|
60
|
+
super.connectedCallback();
|
|
61
|
+
void loadMaplibre().then(async (mod) => {
|
|
62
|
+
this.loading = false;
|
|
63
|
+
if (!mod)
|
|
64
|
+
return;
|
|
65
|
+
// `[part="container"]` only exists once `loading` flips to `false` and
|
|
66
|
+
// Lit re-renders — wait for that render to land before querying it.
|
|
67
|
+
await this.updateComplete;
|
|
68
|
+
// The element may have been removed from the DOM while the async
|
|
69
|
+
// loadMaplibre()/updateComplete window was in flight — don't spin up
|
|
70
|
+
// a maplibre Map (WebGL context + event listeners) for a detached
|
|
71
|
+
// instance (disconnectedCallback's cleanup already ran).
|
|
72
|
+
if (!this.containerEl || !this.isConnected)
|
|
73
|
+
return;
|
|
74
|
+
this._map = new mod.Map({
|
|
75
|
+
container: this.containerEl,
|
|
76
|
+
style: this.mapStyle,
|
|
77
|
+
center: this.center,
|
|
78
|
+
zoom: this.zoom,
|
|
79
|
+
});
|
|
80
|
+
this._map.on('load', () => {
|
|
81
|
+
this._styleLoaded = true;
|
|
82
|
+
this.applyChoropleth();
|
|
83
|
+
this.emit('lyra-map-load');
|
|
84
|
+
});
|
|
85
|
+
this._map.on('click', (e) => {
|
|
86
|
+
// Guard on the fill layer actually existing, not just `this.choropleth` being
|
|
87
|
+
// set: applyChoropleth() only adds it once the style has finished loading, so
|
|
88
|
+
// a click landing in that window (choropleth set before the map's own 'load')
|
|
89
|
+
// would otherwise query a layer id maplibre-gl doesn't know about yet.
|
|
90
|
+
const fillLayerId = this.choropleth ? `${this.choropleth.sourceId}-fill` : undefined;
|
|
91
|
+
const features = fillLayerId && this._map.getLayer(fillLayerId)
|
|
92
|
+
? this._map.queryRenderedFeatures(e.point, { layers: [fillLayerId] })
|
|
93
|
+
: [];
|
|
94
|
+
this.emit('lyra-map-click', {
|
|
95
|
+
lngLat: [e.lngLat.lng, e.lngLat.lat],
|
|
96
|
+
feature: features[0],
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
disconnectedCallback() {
|
|
102
|
+
super.disconnectedCallback();
|
|
103
|
+
this._map?.remove();
|
|
104
|
+
this._map = undefined;
|
|
105
|
+
this._styleLoaded = false;
|
|
106
|
+
}
|
|
107
|
+
updated(changed) {
|
|
108
|
+
if (this.loading)
|
|
109
|
+
this.setAttribute('aria-busy', 'true');
|
|
110
|
+
else
|
|
111
|
+
this.removeAttribute('aria-busy');
|
|
112
|
+
if (changed.has('choropleth') && this._styleLoaded)
|
|
113
|
+
this.applyChoropleth();
|
|
114
|
+
if (changed.has('center') && this._map)
|
|
115
|
+
this._map.setCenter(this.center);
|
|
116
|
+
if (changed.has('zoom') && this._map)
|
|
117
|
+
this._map.setZoom(this.zoom);
|
|
118
|
+
}
|
|
119
|
+
applyChoropleth() {
|
|
120
|
+
if (!this.choropleth || !this._map)
|
|
121
|
+
return;
|
|
122
|
+
const { sourceId, geojson, field, stops } = this.choropleth;
|
|
123
|
+
const fillLayerId = `${sourceId}-fill`;
|
|
124
|
+
const colorExpr = ['interpolate', ['linear'], ['get', field]];
|
|
125
|
+
for (const [value, color] of stops)
|
|
126
|
+
colorExpr.push(value, color);
|
|
127
|
+
const existingSource = this._map.getSource(sourceId);
|
|
128
|
+
if (existingSource) {
|
|
129
|
+
// Re-apply both the data and the color expression: `field`/`stops` may have
|
|
130
|
+
// changed even though `sourceId` didn't (e.g. switching which metric colors
|
|
131
|
+
// the same GeoJSON), so the paint property must be refreshed too.
|
|
132
|
+
existingSource.setData(geojson);
|
|
133
|
+
this._map.setPaintProperty(fillLayerId, 'fill-color', colorExpr);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this._map.addSource(sourceId, { type: 'geojson', data: geojson, promoteId: 'id' });
|
|
137
|
+
this._map.addLayer({
|
|
138
|
+
id: fillLayerId,
|
|
139
|
+
type: 'fill',
|
|
140
|
+
source: sourceId,
|
|
141
|
+
paint: { 'fill-color': colorExpr, 'fill-opacity': 0.75 },
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
render() {
|
|
146
|
+
// Lit's own whitespace/comment marker nodes around the `${...}` binding mean
|
|
147
|
+
// `[part="legend"]` is never truly `:empty` in CSS even with zero entries, so
|
|
148
|
+
// the panel is omitted from the template entirely when `legend` is empty
|
|
149
|
+
// (same `nothing` pattern `stat.ts` uses to omit its optional trend section)
|
|
150
|
+
// rather than relying on a CSS `:empty` selector that can never match.
|
|
151
|
+
return html `
|
|
152
|
+
<div part="base">
|
|
153
|
+
${this.loading
|
|
154
|
+
? html `<lyra-skeleton variant="rect"></lyra-skeleton>`
|
|
155
|
+
: html `<div part="container"></div>`}
|
|
156
|
+
${this.legend.length
|
|
157
|
+
? html `<div part="legend">
|
|
158
|
+
${this.legend.map((entry) => html `<div class="legend-row">
|
|
159
|
+
<span part="legend-swatch" style=${`background:${entry.color}`}></span>
|
|
160
|
+
<span>${entry.label}</span>
|
|
161
|
+
</div>`)}
|
|
162
|
+
</div>`
|
|
163
|
+
: nothing}
|
|
164
|
+
</div>
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
__decorate([
|
|
169
|
+
property({ type: Array })
|
|
170
|
+
], LyraMap.prototype, "center", void 0);
|
|
171
|
+
__decorate([
|
|
172
|
+
property({ type: Number })
|
|
173
|
+
], LyraMap.prototype, "zoom", void 0);
|
|
174
|
+
__decorate([
|
|
175
|
+
property({ attribute: false })
|
|
176
|
+
], LyraMap.prototype, "mapStyle", void 0);
|
|
177
|
+
__decorate([
|
|
178
|
+
property({ attribute: false })
|
|
179
|
+
], LyraMap.prototype, "legend", void 0);
|
|
180
|
+
__decorate([
|
|
181
|
+
property({ attribute: false })
|
|
182
|
+
], LyraMap.prototype, "choropleth", void 0);
|
|
183
|
+
__decorate([
|
|
184
|
+
state()
|
|
185
|
+
], LyraMap.prototype, "loading", void 0);
|
|
186
|
+
__decorate([
|
|
187
|
+
query('[part="container"]')
|
|
188
|
+
], LyraMap.prototype, "containerEl", void 0);
|
|
189
|
+
defineElement('map', LyraMap);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
position: relative;
|
|
6
|
+
inline-size: 100%;
|
|
7
|
+
block-size: 24rem;
|
|
8
|
+
}
|
|
9
|
+
[part='base'] {
|
|
10
|
+
position: relative;
|
|
11
|
+
inline-size: 100%;
|
|
12
|
+
block-size: 100%;
|
|
13
|
+
}
|
|
14
|
+
lyra-skeleton {
|
|
15
|
+
--lyra-skeleton-w: 100%;
|
|
16
|
+
--lyra-skeleton-h: 100%;
|
|
17
|
+
}
|
|
18
|
+
[part='container'] {
|
|
19
|
+
position: absolute;
|
|
20
|
+
inset: 0;
|
|
21
|
+
}
|
|
22
|
+
[part='legend'] {
|
|
23
|
+
position: absolute;
|
|
24
|
+
inset-block-end: var(--lyra-space-s);
|
|
25
|
+
inset-inline-start: var(--lyra-space-s);
|
|
26
|
+
z-index: 1;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
gap: 0.2rem;
|
|
30
|
+
padding: var(--lyra-space-xs) var(--lyra-space-s);
|
|
31
|
+
background: var(--lyra-color-surface);
|
|
32
|
+
border: 1px solid var(--lyra-color-border);
|
|
33
|
+
border-radius: var(--lyra-radius);
|
|
34
|
+
box-shadow: var(--lyra-shadow);
|
|
35
|
+
font-size: 0.75rem;
|
|
36
|
+
}
|
|
37
|
+
.legend-row {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 0.35rem;
|
|
41
|
+
}
|
|
42
|
+
[part='legend-swatch'] {
|
|
43
|
+
inline-size: 0.75rem;
|
|
44
|
+
block-size: 0.75rem;
|
|
45
|
+
border-radius: 2px;
|
|
46
|
+
flex: 0 0 auto;
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<lyra-playback>` — steps an index through `[0, length)` on a fixed
|
|
5
|
+
* interval (play/pause), like the manual play-timers duplicated across
|
|
6
|
+
* per-repo time-series dashboards.
|
|
7
|
+
*
|
|
8
|
+
* @customElement lyra-playback
|
|
9
|
+
* @event lyra-play
|
|
10
|
+
* @event lyra-pause
|
|
11
|
+
* @event lyra-step - `detail: { index }`, fired on every tick and manual step.
|
|
12
|
+
* @csspart base, play-button, slider
|
|
13
|
+
*/
|
|
14
|
+
export declare class LyraPlayback extends LyraElement {
|
|
15
|
+
static styles: import("lit").CSSResultGroup[];
|
|
16
|
+
length: number;
|
|
17
|
+
index: number;
|
|
18
|
+
intervalMs: number;
|
|
19
|
+
playing: boolean;
|
|
20
|
+
loop: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Re-declared as a Lit reactive property (shadowing the inherited plain
|
|
23
|
+
* `HTMLElement.hidden` IDL property) so that setting `el.hidden = true` —
|
|
24
|
+
* or the `hidden` attribute — actually enters Lit's change-tracking system
|
|
25
|
+
* and the `willUpdate` auto-pause guard below can see it via `changed`.
|
|
26
|
+
* `reflect: true` preserves the native attribute-reflection behavior.
|
|
27
|
+
*/
|
|
28
|
+
hidden: boolean;
|
|
29
|
+
private timer?;
|
|
30
|
+
disconnectedCallback(): void;
|
|
31
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
32
|
+
/** Start playback; no-op if there's nothing to advance through. */
|
|
33
|
+
play(): void;
|
|
34
|
+
/** Stop playback. */
|
|
35
|
+
pause(): void;
|
|
36
|
+
toggle(): void;
|
|
37
|
+
private tick;
|
|
38
|
+
private setIndex;
|
|
39
|
+
/** Advance one step without starting playback. */
|
|
40
|
+
next(): void;
|
|
41
|
+
/** Go back one step without starting playback. */
|
|
42
|
+
previous(): void;
|
|
43
|
+
/** Jump to an explicit index, pausing playback. */
|
|
44
|
+
goTo(index: number): void;
|
|
45
|
+
render(): TemplateResult;
|
|
46
|
+
}
|
|
47
|
+
declare global {
|
|
48
|
+
interface HTMLElementTagNameMap {
|
|
49
|
+
'lyra-playback': LyraPlayback;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { playIcon, pauseIcon } from '../../internal/icons.js';
|
|
12
|
+
import { styles } from './playback.styles.js';
|
|
13
|
+
/**
|
|
14
|
+
* `<lyra-playback>` — steps an index through `[0, length)` on a fixed
|
|
15
|
+
* interval (play/pause), like the manual play-timers duplicated across
|
|
16
|
+
* per-repo time-series dashboards.
|
|
17
|
+
*
|
|
18
|
+
* @customElement lyra-playback
|
|
19
|
+
* @event lyra-play
|
|
20
|
+
* @event lyra-pause
|
|
21
|
+
* @event lyra-step - `detail: { index }`, fired on every tick and manual step.
|
|
22
|
+
* @csspart base, play-button, slider
|
|
23
|
+
*/
|
|
24
|
+
export class LyraPlayback extends LyraElement {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.length = 0;
|
|
28
|
+
this.index = 0;
|
|
29
|
+
this.intervalMs = 900;
|
|
30
|
+
this.playing = false;
|
|
31
|
+
this.loop = true;
|
|
32
|
+
/**
|
|
33
|
+
* Re-declared as a Lit reactive property (shadowing the inherited plain
|
|
34
|
+
* `HTMLElement.hidden` IDL property) so that setting `el.hidden = true` —
|
|
35
|
+
* or the `hidden` attribute — actually enters Lit's change-tracking system
|
|
36
|
+
* and the `willUpdate` auto-pause guard below can see it via `changed`.
|
|
37
|
+
* `reflect: true` preserves the native attribute-reflection behavior.
|
|
38
|
+
*/
|
|
39
|
+
this.hidden = false;
|
|
40
|
+
}
|
|
41
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
super.disconnectedCallback();
|
|
44
|
+
this.pause();
|
|
45
|
+
}
|
|
46
|
+
willUpdate(changed) {
|
|
47
|
+
if (changed.has('hidden') && this.hidden)
|
|
48
|
+
this.pause();
|
|
49
|
+
}
|
|
50
|
+
/** Start playback; no-op if there's nothing to advance through. */
|
|
51
|
+
play() {
|
|
52
|
+
if (this.playing || this.length <= 1)
|
|
53
|
+
return;
|
|
54
|
+
this.playing = true;
|
|
55
|
+
this.emit('lyra-play');
|
|
56
|
+
this.timer = window.setInterval(() => this.tick(), this.intervalMs);
|
|
57
|
+
}
|
|
58
|
+
/** Stop playback. */
|
|
59
|
+
pause() {
|
|
60
|
+
if (!this.playing)
|
|
61
|
+
return;
|
|
62
|
+
window.clearInterval(this.timer);
|
|
63
|
+
this.timer = undefined;
|
|
64
|
+
this.playing = false;
|
|
65
|
+
this.emit('lyra-pause');
|
|
66
|
+
}
|
|
67
|
+
toggle() {
|
|
68
|
+
this.playing ? this.pause() : this.play();
|
|
69
|
+
}
|
|
70
|
+
tick() {
|
|
71
|
+
const next = this.index + 1;
|
|
72
|
+
if (next >= this.length) {
|
|
73
|
+
if (this.loop)
|
|
74
|
+
this.setIndex(0);
|
|
75
|
+
else {
|
|
76
|
+
this.setIndex(this.length - 1);
|
|
77
|
+
this.pause();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.setIndex(next);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
setIndex(i) {
|
|
85
|
+
this.index = i;
|
|
86
|
+
this.emit('lyra-step', { index: this.index });
|
|
87
|
+
}
|
|
88
|
+
/** Advance one step without starting playback. */
|
|
89
|
+
next() {
|
|
90
|
+
if (this.index + 1 < this.length)
|
|
91
|
+
this.setIndex(this.index + 1);
|
|
92
|
+
}
|
|
93
|
+
/** Go back one step without starting playback. */
|
|
94
|
+
previous() {
|
|
95
|
+
if (this.index > 0)
|
|
96
|
+
this.setIndex(this.index - 1);
|
|
97
|
+
}
|
|
98
|
+
/** Jump to an explicit index, pausing playback. */
|
|
99
|
+
goTo(index) {
|
|
100
|
+
this.pause();
|
|
101
|
+
this.setIndex(Math.min(this.length - 1, Math.max(0, index)));
|
|
102
|
+
}
|
|
103
|
+
render() {
|
|
104
|
+
return html `
|
|
105
|
+
<div part="base">
|
|
106
|
+
<button
|
|
107
|
+
part="play-button"
|
|
108
|
+
type="button"
|
|
109
|
+
aria-label=${this.playing ? 'Pause' : 'Play'}
|
|
110
|
+
?disabled=${this.length <= 1}
|
|
111
|
+
@click=${() => this.toggle()}
|
|
112
|
+
>
|
|
113
|
+
${this.playing ? pauseIcon() : playIcon()}
|
|
114
|
+
</button>
|
|
115
|
+
<input
|
|
116
|
+
part="slider"
|
|
117
|
+
type="range"
|
|
118
|
+
min="0"
|
|
119
|
+
max=${Math.max(0, this.length - 1)}
|
|
120
|
+
.value=${String(this.index)}
|
|
121
|
+
aria-label="Playback position"
|
|
122
|
+
@input=${(e) => this.goTo(Number(e.target.value))}
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
__decorate([
|
|
129
|
+
property({ type: Number })
|
|
130
|
+
], LyraPlayback.prototype, "length", void 0);
|
|
131
|
+
__decorate([
|
|
132
|
+
property({ type: Number })
|
|
133
|
+
], LyraPlayback.prototype, "index", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
property({ type: Number, attribute: 'interval-ms' })
|
|
136
|
+
], LyraPlayback.prototype, "intervalMs", void 0);
|
|
137
|
+
__decorate([
|
|
138
|
+
property({ type: Boolean, reflect: true })
|
|
139
|
+
], LyraPlayback.prototype, "playing", void 0);
|
|
140
|
+
__decorate([
|
|
141
|
+
property({ type: Boolean })
|
|
142
|
+
], LyraPlayback.prototype, "loop", void 0);
|
|
143
|
+
__decorate([
|
|
144
|
+
property({ type: Boolean, reflect: true })
|
|
145
|
+
], LyraPlayback.prototype, "hidden", void 0);
|
|
146
|
+
defineElement('playback', LyraPlayback);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: var(--lyra-space-s);
|
|
7
|
+
}
|
|
8
|
+
[part='base'] {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: var(--lyra-space-s);
|
|
12
|
+
}
|
|
13
|
+
[part='play-button'] {
|
|
14
|
+
inline-size: 2rem;
|
|
15
|
+
block-size: 2rem;
|
|
16
|
+
border-radius: 50%;
|
|
17
|
+
border: 1px solid var(--lyra-color-border);
|
|
18
|
+
background: var(--lyra-color-surface);
|
|
19
|
+
color: var(--lyra-color-text);
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
font-size: 0.875rem;
|
|
25
|
+
}
|
|
26
|
+
[part='play-button']:hover {
|
|
27
|
+
border-color: var(--lyra-color-brand);
|
|
28
|
+
}
|
|
29
|
+
[part='play-button']:disabled {
|
|
30
|
+
opacity: var(--lyra-opacity-disabled);
|
|
31
|
+
cursor: not-allowed;
|
|
32
|
+
}
|
|
33
|
+
[part='play-button']:focus-visible {
|
|
34
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
35
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
36
|
+
}
|
|
37
|
+
[part='slider'] {
|
|
38
|
+
accent-color: var(--lyra-color-brand);
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<lyra-split>` — resizable panels for dashboard layouts. Direct light-DOM
|
|
5
|
+
* children are the panels; a divider is auto-inserted between each pair.
|
|
6
|
+
*
|
|
7
|
+
* @customElement lyra-split
|
|
8
|
+
* @event lyra-resize - `detail: { sizes }`, fired on every drag step/release
|
|
9
|
+
* and every keyboard step.
|
|
10
|
+
* @csspart base, divider
|
|
11
|
+
*/
|
|
12
|
+
export declare class LyraSplit extends LyraElement {
|
|
13
|
+
static styles: import("lit").CSSResultGroup[];
|
|
14
|
+
sizes: number[];
|
|
15
|
+
min: number;
|
|
16
|
+
orientation: 'horizontal' | 'vertical';
|
|
17
|
+
storageKey?: string;
|
|
18
|
+
private panelCount;
|
|
19
|
+
private dragIndex;
|
|
20
|
+
private dragStartPos;
|
|
21
|
+
private dragStartSizes;
|
|
22
|
+
connectedCallback(): void;
|
|
23
|
+
disconnectedCallback(): void;
|
|
24
|
+
private get storageFullKey();
|
|
25
|
+
private loadPersisted;
|
|
26
|
+
private persist;
|
|
27
|
+
private ensureSizes;
|
|
28
|
+
private clampPair;
|
|
29
|
+
private applyDelta;
|
|
30
|
+
private onPointerDown;
|
|
31
|
+
private onPointerMove;
|
|
32
|
+
private onPointerUp;
|
|
33
|
+
private onDividerKeyDown;
|
|
34
|
+
protected updated(changed: PropertyValues): void;
|
|
35
|
+
render(): TemplateResult;
|
|
36
|
+
}
|
|
37
|
+
declare global {
|
|
38
|
+
interface HTMLElementTagNameMap {
|
|
39
|
+
'lyra-split': LyraSplit;
|
|
40
|
+
}
|
|
41
|
+
}
|