@shamar/core 1.0.6 → 1.0.8
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/dist/dashboard-page.d.ts +27 -0
- package/dist/dashboard-page.d.ts.map +1 -1
- package/dist/dashboard-page.js +60 -0
- package/dist/dashboard-page.js.map +1 -1
- package/dist/dashboard-widgets.d.ts +16 -0
- package/dist/dashboard-widgets.d.ts.map +1 -1
- package/dist/widget.d.ts +23 -0
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +31 -0
- package/dist/widget.js.map +1 -1
- package/dist/widgets/stat.d.ts +41 -3
- package/dist/widgets/stat.d.ts.map +1 -1
- package/dist/widgets/stat.js +124 -5
- package/dist/widgets/stat.js.map +1 -1
- package/dist/widgets/stats-overview-widget.d.ts +35 -1
- package/dist/widgets/stats-overview-widget.d.ts.map +1 -1
- package/dist/widgets/stats-overview-widget.js +93 -1
- package/dist/widgets/stats-overview-widget.js.map +1 -1
- package/package.json +1 -1
package/dist/dashboard-page.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Page } from './page.js';
|
|
2
|
+
import { FormBuilder } from './form.js';
|
|
2
3
|
import type { WidgetClass } from './widget.js';
|
|
4
|
+
import type { FormSchema, SchemaNode } from './types.js';
|
|
3
5
|
/** Reserved slug — dashboard pages are not registered as `/:slug` routes. */
|
|
4
6
|
export declare const DASHBOARD_PAGE_SLUG = "__dashboard__";
|
|
5
7
|
/**
|
|
@@ -13,8 +15,33 @@ export declare abstract class DashboardPage extends Page {
|
|
|
13
15
|
/** Responsive grid columns for widget layout (1–4). */
|
|
14
16
|
static columns: number;
|
|
15
17
|
static widgets(): WidgetClass[];
|
|
18
|
+
/**
|
|
19
|
+
* Optional filters form (Filament `HasFiltersForm` / `getFiltersForm`).
|
|
20
|
+
* Submitted via GET on the dashboard; values land in `WidgetRequestContext.filters`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* static override filtersForm(form: FormBuilder) {
|
|
25
|
+
* return form.schema([
|
|
26
|
+
* Select.make('period').options([
|
|
27
|
+
* { label: 'Today', value: 'today' },
|
|
28
|
+
* { label: 'MTD', value: 'mtd' },
|
|
29
|
+
* ]).default('today'),
|
|
30
|
+
* ])
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
static filtersForm(_form: FormBuilder): FormBuilder | FormSchema | void;
|
|
16
35
|
}
|
|
17
36
|
export type DashboardPageClass = typeof DashboardPage;
|
|
18
37
|
/** True when `value` is DashboardPage or a subclass. */
|
|
19
38
|
export declare function isDashboardPage(value: unknown): value is DashboardPageClass;
|
|
39
|
+
/** Resolve the optional filters form schema for a dashboard page. */
|
|
40
|
+
export declare function resolveDashboardFiltersForm(DashboardClass: DashboardPageClass): FormSchema | undefined;
|
|
41
|
+
/** Flatten filter field names from a filters form schema. */
|
|
42
|
+
export declare function dashboardFilterFieldNames(schema: FormSchema | undefined): string[];
|
|
43
|
+
/** Collect filter values from a query/body bag for known filter fields. */
|
|
44
|
+
export declare function pickDashboardFilters(source: Record<string, unknown>, schema: FormSchema | undefined): Record<string, unknown>;
|
|
45
|
+
/** Schema nodes for rendering the filters form. */
|
|
46
|
+
export declare function dashboardFilterSchemaNodes(schema: FormSchema | undefined): SchemaNode[];
|
|
20
47
|
//# sourceMappingURL=dashboard-page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-page.d.ts","sourceRoot":"","sources":["../src/dashboard-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-page.d.ts","sourceRoot":"","sources":["../src/dashboard-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAc,MAAM,WAAW,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD;;;GAGG;AACH,8BAAsB,aAAc,SAAQ,IAAI;IAC9C,OAAgB,IAAI,SAAuB;IAC3C,OAAgB,KAAK,SAAe;IACpC,OAAgB,gBAAgB,UAAQ;IAExC,uDAAuD;IACvD,MAAM,CAAC,OAAO,SAAK;IAEnB,MAAM,CAAC,OAAO,IAAI,WAAW,EAAE;IAI/B;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI;CAGxE;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,aAAa,CAAC;AAEtD,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAQ3E;AAED,qEAAqE;AACrE,wBAAgB,2BAA2B,CACzC,cAAc,EAAE,kBAAkB,GACjC,UAAU,GAAG,SAAS,CAMxB;AAED,6DAA6D;AAC7D,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,EAAE,CAGlF;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,UAAU,GAAG,SAAS,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,mDAAmD;AACnD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,EAAE,CAQvF"}
|
package/dist/dashboard-page.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Page } from './page.js';
|
|
2
|
+
import { FormBuilder, acceptForm } from './form.js';
|
|
2
3
|
import { NavigationCardsWidget } from './widgets/navigation-cards-widget.js';
|
|
3
4
|
/** Reserved slug — dashboard pages are not registered as `/:slug` routes. */
|
|
4
5
|
export const DASHBOARD_PAGE_SLUG = '__dashboard__';
|
|
@@ -15,6 +16,25 @@ export class DashboardPage extends Page {
|
|
|
15
16
|
static widgets() {
|
|
16
17
|
return [NavigationCardsWidget];
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Optional filters form (Filament `HasFiltersForm` / `getFiltersForm`).
|
|
21
|
+
* Submitted via GET on the dashboard; values land in `WidgetRequestContext.filters`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* static override filtersForm(form: FormBuilder) {
|
|
26
|
+
* return form.schema([
|
|
27
|
+
* Select.make('period').options([
|
|
28
|
+
* { label: 'Today', value: 'today' },
|
|
29
|
+
* { label: 'MTD', value: 'mtd' },
|
|
30
|
+
* ]).default('today'),
|
|
31
|
+
* ])
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
static filtersForm(_form) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
18
38
|
}
|
|
19
39
|
/** True when `value` is DashboardPage or a subclass. */
|
|
20
40
|
export function isDashboardPage(value) {
|
|
@@ -28,4 +48,44 @@ export function isDashboardPage(value) {
|
|
|
28
48
|
}
|
|
29
49
|
return false;
|
|
30
50
|
}
|
|
51
|
+
/** Resolve the optional filters form schema for a dashboard page. */
|
|
52
|
+
export function resolveDashboardFiltersForm(DashboardClass) {
|
|
53
|
+
const builder = new FormBuilder();
|
|
54
|
+
const result = DashboardClass.filtersForm(builder);
|
|
55
|
+
if (result === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
const built = acceptForm(result, builder);
|
|
58
|
+
return built.fields.length || built.schema?.length ? built : undefined;
|
|
59
|
+
}
|
|
60
|
+
/** Flatten filter field names from a filters form schema. */
|
|
61
|
+
export function dashboardFilterFieldNames(schema) {
|
|
62
|
+
if (!schema)
|
|
63
|
+
return [];
|
|
64
|
+
return schema.fields.map((field) => field.name);
|
|
65
|
+
}
|
|
66
|
+
/** Collect filter values from a query/body bag for known filter fields. */
|
|
67
|
+
export function pickDashboardFilters(source, schema) {
|
|
68
|
+
const names = dashboardFilterFieldNames(schema);
|
|
69
|
+
if (!names.length)
|
|
70
|
+
return {};
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const name of names) {
|
|
73
|
+
if (Object.prototype.hasOwnProperty.call(source, name)) {
|
|
74
|
+
out[name] = source[name];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
/** Schema nodes for rendering the filters form. */
|
|
80
|
+
export function dashboardFilterSchemaNodes(schema) {
|
|
81
|
+
if (!schema)
|
|
82
|
+
return [];
|
|
83
|
+
if (schema.schema?.length)
|
|
84
|
+
return schema.schema;
|
|
85
|
+
return schema.fields.map((field) => ({
|
|
86
|
+
kind: 'field',
|
|
87
|
+
name: field.name,
|
|
88
|
+
field,
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
31
91
|
//# sourceMappingURL=dashboard-page.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../src/dashboard-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../src/dashboard-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,14 +12,27 @@ export interface ResolvedDashboardWidget {
|
|
|
12
12
|
id: string;
|
|
13
13
|
kind: DashboardWidgetKind;
|
|
14
14
|
heading?: string;
|
|
15
|
+
description?: string;
|
|
15
16
|
columnSpan: number | 'full';
|
|
16
17
|
sort: number;
|
|
17
18
|
view?: string;
|
|
19
|
+
/** Parsed polling interval in ms; `null` disables. */
|
|
20
|
+
pollingIntervalMs: number | null;
|
|
21
|
+
/** When true, payload may be deferred until the client loads the widget. */
|
|
22
|
+
isLazy: boolean;
|
|
23
|
+
/** Panel-relative URL to re-fetch this widget’s HTML fragment. */
|
|
24
|
+
refreshUrl?: string;
|
|
18
25
|
payload: DashboardWidgetPayload;
|
|
19
26
|
}
|
|
20
27
|
export type DashboardWidgetPayload = StatsOverviewPayload | CardPayload | ListPayload | ChartPayload | NavigationCardsPayload;
|
|
21
28
|
export interface StatsOverviewPayload {
|
|
22
29
|
stats: StatData[];
|
|
30
|
+
/** Resolved cards-per-row config. */
|
|
31
|
+
columns: Partial<Record<string, number>>;
|
|
32
|
+
/** Inline CSS vars for `.shamar-stats-overview__grid`. */
|
|
33
|
+
gridStyle: string;
|
|
34
|
+
/** True when stats were not resolved yet (lazy placeholder). */
|
|
35
|
+
deferred?: boolean;
|
|
23
36
|
}
|
|
24
37
|
export interface CardPayload {
|
|
25
38
|
content: CardWidgetContent;
|
|
@@ -28,14 +41,17 @@ export interface ListPayload {
|
|
|
28
41
|
columns: ListWidgetColumn[];
|
|
29
42
|
records: ListWidgetRecord[];
|
|
30
43
|
limit: number;
|
|
44
|
+
deferred?: boolean;
|
|
31
45
|
}
|
|
32
46
|
export interface ChartPayload {
|
|
33
47
|
chartType: ChartType;
|
|
34
48
|
library: ChartLibrary;
|
|
35
49
|
data: ChartData;
|
|
50
|
+
deferred?: boolean;
|
|
36
51
|
}
|
|
37
52
|
export interface NavigationCardsPayload {
|
|
38
53
|
cards: NavigationCardItem[];
|
|
39
54
|
emptyMessage?: string;
|
|
55
|
+
deferred?: boolean;
|
|
40
56
|
}
|
|
41
57
|
//# sourceMappingURL=dashboard-widgets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-widgets.d.ts","sourceRoot":"","sources":["../src/dashboard-widgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEpF,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,MAAM,GACN,MAAM,GACN,OAAO,GACP,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED,MAAM,MAAM,sBAAsB,GAC9B,oBAAoB,GACpB,WAAW,GACX,WAAW,GACX,YAAY,GACZ,sBAAsB,CAAC;AAE3B,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-widgets.d.ts","sourceRoot":"","sources":["../src/dashboard-widgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEpF,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,MAAM,GACN,MAAM,GACN,OAAO,GACP,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAC;IAChB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED,MAAM,MAAM,sBAAsB,GAC9B,oBAAoB,GACpB,WAAW,GACX,WAAW,GACX,YAAY,GACZ,sBAAsB,CAAC;AAE3B,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
|
package/dist/widget.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export interface WidgetRequestContext {
|
|
|
5
5
|
panelId?: string;
|
|
6
6
|
/** Panel base path for building widget links. */
|
|
7
7
|
basePath?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Dashboard page filters (Filament `$pageFilters` / `InteractsWithPageFilters`).
|
|
10
|
+
* Populated from the dashboard filters form query string.
|
|
11
|
+
*/
|
|
12
|
+
filters?: Record<string, unknown>;
|
|
8
13
|
}
|
|
9
14
|
export type WidgetColumnSpan = number | 'full';
|
|
10
15
|
/**
|
|
@@ -17,11 +22,29 @@ export declare abstract class Widget {
|
|
|
17
22
|
static sort: number;
|
|
18
23
|
static columnSpan: WidgetColumnSpan;
|
|
19
24
|
static heading?: string;
|
|
25
|
+
/** Optional subtitle under the heading (Filament `$description`). */
|
|
26
|
+
static description?: string;
|
|
20
27
|
/** Optional Edge view override (`shamar::widgets/...` or app view path). */
|
|
21
28
|
static view?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Poll interval (Filament `$pollingInterval`), e.g. `'5s'`, `'500ms'`.
|
|
31
|
+
* `null` disables polling.
|
|
32
|
+
*/
|
|
33
|
+
static pollingInterval: string | null;
|
|
34
|
+
/**
|
|
35
|
+
* When true, defer data until the widget is visible (Filament `$isLazy`).
|
|
36
|
+
* Base default is `false` (SSR-friendly); {@link StatsOverviewWidget} defaults to `true`.
|
|
37
|
+
*/
|
|
38
|
+
static isLazy: boolean;
|
|
22
39
|
static canView(_user: ShamarUser | null | undefined): boolean;
|
|
23
40
|
}
|
|
24
41
|
export type WidgetClass = typeof Widget;
|
|
42
|
+
/** Parse Filament-style `'5s'` / `'500ms'` into milliseconds. */
|
|
43
|
+
export declare function parsePollingIntervalMs(value: string | null | undefined): number | null;
|
|
44
|
+
/**
|
|
45
|
+
* Filament `InteractsWithPageFilters` — read dashboard filter values from context.
|
|
46
|
+
*/
|
|
47
|
+
export declare function pageFilters(ctx: WidgetRequestContext): Record<string, unknown>;
|
|
25
48
|
/** True when `value` extends {@link Widget}. */
|
|
26
49
|
export declare function isWidgetClass(value: unknown): value is WidgetClass;
|
|
27
50
|
//# sourceMappingURL=widget.d.ts.map
|
package/dist/widget.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C;;;GAGG;AACH,8BAAsB,MAAM;IAC1B,sFAAsF;IACtF,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,IAAI,SAAK;IAChB,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAK;IACxC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7C;;;OAGG;IACH,MAAM,CAAC,MAAM,UAAS;IAEtB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;CAG9D;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,MAAM,CAAC;AAExC,iEAAiE;AACjE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQtF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAQlE"}
|
package/dist/widget.js
CHANGED
|
@@ -8,12 +8,43 @@ export class Widget {
|
|
|
8
8
|
static sort = 0;
|
|
9
9
|
static columnSpan = 1;
|
|
10
10
|
static heading;
|
|
11
|
+
/** Optional subtitle under the heading (Filament `$description`). */
|
|
12
|
+
static description;
|
|
11
13
|
/** Optional Edge view override (`shamar::widgets/...` or app view path). */
|
|
12
14
|
static view;
|
|
15
|
+
/**
|
|
16
|
+
* Poll interval (Filament `$pollingInterval`), e.g. `'5s'`, `'500ms'`.
|
|
17
|
+
* `null` disables polling.
|
|
18
|
+
*/
|
|
19
|
+
static pollingInterval = null;
|
|
20
|
+
/**
|
|
21
|
+
* When true, defer data until the widget is visible (Filament `$isLazy`).
|
|
22
|
+
* Base default is `false` (SSR-friendly); {@link StatsOverviewWidget} defaults to `true`.
|
|
23
|
+
*/
|
|
24
|
+
static isLazy = false;
|
|
13
25
|
static canView(_user) {
|
|
14
26
|
return true;
|
|
15
27
|
}
|
|
16
28
|
}
|
|
29
|
+
/** Parse Filament-style `'5s'` / `'500ms'` into milliseconds. */
|
|
30
|
+
export function parsePollingIntervalMs(value) {
|
|
31
|
+
if (value == null || value === '')
|
|
32
|
+
return null;
|
|
33
|
+
const match = /^(\d+(?:\.\d+)?)\s*(ms|s)?$/i.exec(value.trim());
|
|
34
|
+
if (!match)
|
|
35
|
+
return null;
|
|
36
|
+
const amount = Number(match[1]);
|
|
37
|
+
if (!Number.isFinite(amount) || amount < 0)
|
|
38
|
+
return null;
|
|
39
|
+
const unit = (match[2] ?? 's').toLowerCase();
|
|
40
|
+
return unit === 'ms' ? Math.round(amount) : Math.round(amount * 1000);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Filament `InteractsWithPageFilters` — read dashboard filter values from context.
|
|
44
|
+
*/
|
|
45
|
+
export function pageFilters(ctx) {
|
|
46
|
+
return ctx.filters ?? {};
|
|
47
|
+
}
|
|
17
48
|
/** True when `value` extends {@link Widget}. */
|
|
18
49
|
export function isWidgetClass(value) {
|
|
19
50
|
if (typeof value !== 'function')
|
package/dist/widget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,MAAM,OAAgB,MAAM;IAC1B,sFAAsF;IACtF,MAAM,CAAC,EAAE,CAAU;IACnB,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAChB,MAAM,CAAC,UAAU,GAAqB,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,CAAU;IACxB,qEAAqE;IACrE,MAAM,CAAC,WAAW,CAAU;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,IAAI,CAAU;IACrB;;;OAGG;IACH,MAAM,CAAC,eAAe,GAAkB,IAAI,CAAC;IAC7C;;;OAGG;IACH,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;IAEtB,MAAM,CAAC,OAAO,CAAC,KAAoC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;;AAKH,iEAAiE;AACjE,MAAM,UAAU,sBAAsB,CAAC,KAAgC;IACrE,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAyB;IACnD,OAAO,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,OAAO,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACrC,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/widgets/stat.d.ts
CHANGED
|
@@ -1,27 +1,65 @@
|
|
|
1
1
|
export type StatColor = 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'gray';
|
|
2
|
+
/** Trusted HTML fragment (Filament `Htmlable`). */
|
|
3
|
+
export type HtmlContent = {
|
|
4
|
+
html: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function html(content: string): HtmlContent;
|
|
7
|
+
export declare function isHtmlContent(value: unknown): value is HtmlContent;
|
|
8
|
+
export type StatScalar = string | number | null | undefined;
|
|
2
9
|
export interface StatData {
|
|
3
10
|
label: string;
|
|
11
|
+
labelHtml?: string;
|
|
4
12
|
value: string | number;
|
|
13
|
+
valueHtml?: string;
|
|
5
14
|
description?: string;
|
|
15
|
+
descriptionHtml?: string;
|
|
6
16
|
descriptionIcon?: string;
|
|
7
17
|
descriptionIconPosition?: 'before' | 'after';
|
|
18
|
+
descriptionColor?: StatColor;
|
|
8
19
|
color?: StatColor;
|
|
20
|
+
icon?: string;
|
|
9
21
|
url?: string;
|
|
22
|
+
openUrlInNewTab?: boolean;
|
|
10
23
|
/** Sparkline values rendered under the stat. */
|
|
11
24
|
chart?: number[];
|
|
25
|
+
chartColor?: StatColor;
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
extraAttributes?: Record<string, string>;
|
|
28
|
+
/** Pre-escaped HTML attribute string for Edge (built at serialize time). */
|
|
29
|
+
extraAttributesHtml?: string;
|
|
30
|
+
/** Cards this stat spans inside the overview grid (Filament Schema columnSpan). */
|
|
31
|
+
columnSpan?: number;
|
|
12
32
|
}
|
|
33
|
+
export type StatConfigurator = (stat: Stat) => void;
|
|
13
34
|
/**
|
|
14
35
|
* Filament-style stat card descriptor for {@link StatsOverviewWidget}.
|
|
15
36
|
*/
|
|
16
37
|
export declare class Stat {
|
|
17
38
|
private readonly data;
|
|
39
|
+
private rawValue;
|
|
40
|
+
private placeholderText?;
|
|
18
41
|
private constructor();
|
|
19
|
-
static make(label: string, value
|
|
20
|
-
|
|
42
|
+
static make(label: string | HtmlContent, value?: StatScalar | HtmlContent): Stat;
|
|
43
|
+
/** Filament `Stat::configureUsing()` — runs on every {@link Stat.make}. */
|
|
44
|
+
static configureUsing(callback: StatConfigurator): void;
|
|
45
|
+
/** Test helper — clears global configurators. */
|
|
46
|
+
static clearConfigureUsing(): void;
|
|
47
|
+
description(text: string | HtmlContent): this;
|
|
21
48
|
descriptionIcon(icon: string, position?: 'before' | 'after'): this;
|
|
49
|
+
descriptionColor(color: StatColor): this;
|
|
22
50
|
color(color: StatColor): this;
|
|
51
|
+
icon(icon: string): this;
|
|
23
52
|
url(href: string): this;
|
|
24
|
-
|
|
53
|
+
openUrlInNewTab(value?: boolean): this;
|
|
54
|
+
chart(values: number[] | null | undefined): this;
|
|
55
|
+
chartColor(color: StatColor): this;
|
|
56
|
+
placeholder(text: string): this;
|
|
57
|
+
extraAttributes(attrs: Record<string, string>, options?: {
|
|
58
|
+
merge?: boolean;
|
|
59
|
+
}): this;
|
|
60
|
+
columnSpan(span: number): this;
|
|
61
|
+
value(next: StatScalar | HtmlContent): this;
|
|
62
|
+
private applyValue;
|
|
25
63
|
toJSON(): StatData;
|
|
26
64
|
}
|
|
27
65
|
//# sourceMappingURL=stat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/widgets/stat.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/widgets/stat.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvF,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3C,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAEjD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAOlE;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7C,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;AAQpD;;GAEG;AACH,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,eAAe,CAAC,CAAS;IAEjC,OAAO;IAUP,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,KAAK,GAAE,UAAU,GAAG,WAAkB,GAAG,IAAI;IAMtF,2EAA2E;IAC3E,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIvD,iDAAiD;IACjD,MAAM,CAAC,mBAAmB,IAAI,IAAI;IAIlC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAW7C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAQ,GAAG,OAAiB,GAAG,IAAI;IAM3E,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKxC,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAK7B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKvB,eAAe,CAAC,KAAK,UAAO,GAAG,IAAI;IAKnC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAMhD,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKlC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO/B,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAOnF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAM3C,OAAO,CAAC,UAAU;IAclB,MAAM,IAAI,QAAQ;CA2BnB"}
|
package/dist/widgets/stat.js
CHANGED
|
@@ -1,16 +1,56 @@
|
|
|
1
|
+
export function html(content) {
|
|
2
|
+
return { html: content };
|
|
3
|
+
}
|
|
4
|
+
export function isHtmlContent(value) {
|
|
5
|
+
return (!!value &&
|
|
6
|
+
typeof value === 'object' &&
|
|
7
|
+
'html' in value &&
|
|
8
|
+
typeof value.html === 'string');
|
|
9
|
+
}
|
|
10
|
+
const configurators = [];
|
|
11
|
+
function isBlank(value) {
|
|
12
|
+
return value == null || value === '';
|
|
13
|
+
}
|
|
1
14
|
/**
|
|
2
15
|
* Filament-style stat card descriptor for {@link StatsOverviewWidget}.
|
|
3
16
|
*/
|
|
4
17
|
export class Stat {
|
|
5
18
|
data;
|
|
19
|
+
rawValue;
|
|
20
|
+
placeholderText;
|
|
6
21
|
constructor(label, value) {
|
|
7
|
-
|
|
22
|
+
if (isHtmlContent(label)) {
|
|
23
|
+
this.data = { label: '', labelHtml: label.html, value: '' };
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.data = { label: String(label), value: '' };
|
|
27
|
+
}
|
|
28
|
+
this.rawValue = value;
|
|
29
|
+
this.applyValue(value);
|
|
8
30
|
}
|
|
9
|
-
static make(label, value) {
|
|
10
|
-
|
|
31
|
+
static make(label, value = null) {
|
|
32
|
+
const stat = new Stat(label, value);
|
|
33
|
+
for (const configure of configurators)
|
|
34
|
+
configure(stat);
|
|
35
|
+
return stat;
|
|
36
|
+
}
|
|
37
|
+
/** Filament `Stat::configureUsing()` — runs on every {@link Stat.make}. */
|
|
38
|
+
static configureUsing(callback) {
|
|
39
|
+
configurators.push(callback);
|
|
40
|
+
}
|
|
41
|
+
/** Test helper — clears global configurators. */
|
|
42
|
+
static clearConfigureUsing() {
|
|
43
|
+
configurators.length = 0;
|
|
11
44
|
}
|
|
12
45
|
description(text) {
|
|
13
|
-
|
|
46
|
+
if (isHtmlContent(text)) {
|
|
47
|
+
this.data.descriptionHtml = text.html;
|
|
48
|
+
this.data.description = undefined;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.data.description = text;
|
|
52
|
+
this.data.descriptionHtml = undefined;
|
|
53
|
+
}
|
|
14
54
|
return this;
|
|
15
55
|
}
|
|
16
56
|
descriptionIcon(icon, position = 'after') {
|
|
@@ -18,20 +58,99 @@ export class Stat {
|
|
|
18
58
|
this.data.descriptionIconPosition = position;
|
|
19
59
|
return this;
|
|
20
60
|
}
|
|
61
|
+
descriptionColor(color) {
|
|
62
|
+
this.data.descriptionColor = color;
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
21
65
|
color(color) {
|
|
22
66
|
this.data.color = color;
|
|
23
67
|
return this;
|
|
24
68
|
}
|
|
69
|
+
icon(icon) {
|
|
70
|
+
this.data.icon = icon;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
25
73
|
url(href) {
|
|
26
74
|
this.data.url = href;
|
|
27
75
|
return this;
|
|
28
76
|
}
|
|
77
|
+
openUrlInNewTab(value = true) {
|
|
78
|
+
this.data.openUrlInNewTab = value;
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
29
81
|
chart(values) {
|
|
82
|
+
if (values == null)
|
|
83
|
+
return this;
|
|
30
84
|
this.data.chart = values;
|
|
31
85
|
return this;
|
|
32
86
|
}
|
|
87
|
+
chartColor(color) {
|
|
88
|
+
this.data.chartColor = color;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
placeholder(text) {
|
|
92
|
+
this.placeholderText = text;
|
|
93
|
+
this.data.placeholder = text;
|
|
94
|
+
this.applyValue(this.rawValue);
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
extraAttributes(attrs, options) {
|
|
98
|
+
this.data.extraAttributes = options?.merge
|
|
99
|
+
? { ...this.data.extraAttributes, ...attrs }
|
|
100
|
+
: { ...attrs };
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
columnSpan(span) {
|
|
104
|
+
this.data.columnSpan = Math.max(1, Math.floor(span));
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
value(next) {
|
|
108
|
+
this.rawValue = next;
|
|
109
|
+
this.applyValue(next);
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
applyValue(value) {
|
|
113
|
+
if (isHtmlContent(value)) {
|
|
114
|
+
this.data.valueHtml = value.html;
|
|
115
|
+
this.data.value = '';
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.data.valueHtml = undefined;
|
|
119
|
+
if (isBlank(value)) {
|
|
120
|
+
this.data.value = this.placeholderText ?? '';
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.data.value = value;
|
|
124
|
+
}
|
|
33
125
|
toJSON() {
|
|
34
|
-
|
|
126
|
+
const out = {
|
|
127
|
+
label: this.data.label,
|
|
128
|
+
value: this.data.value,
|
|
129
|
+
};
|
|
130
|
+
const copy = (key) => {
|
|
131
|
+
const value = this.data[key];
|
|
132
|
+
if (value !== undefined)
|
|
133
|
+
out[key] = value;
|
|
134
|
+
};
|
|
135
|
+
copy('labelHtml');
|
|
136
|
+
copy('valueHtml');
|
|
137
|
+
copy('description');
|
|
138
|
+
copy('descriptionHtml');
|
|
139
|
+
copy('descriptionIcon');
|
|
140
|
+
copy('descriptionIconPosition');
|
|
141
|
+
copy('descriptionColor');
|
|
142
|
+
copy('color');
|
|
143
|
+
copy('icon');
|
|
144
|
+
copy('url');
|
|
145
|
+
copy('openUrlInNewTab');
|
|
146
|
+
copy('chartColor');
|
|
147
|
+
copy('placeholder');
|
|
148
|
+
copy('columnSpan');
|
|
149
|
+
if (this.data.extraAttributes)
|
|
150
|
+
out.extraAttributes = { ...this.data.extraAttributes };
|
|
151
|
+
if (this.data.chart)
|
|
152
|
+
out.chart = [...this.data.chart];
|
|
153
|
+
return out;
|
|
35
154
|
}
|
|
36
155
|
}
|
|
37
156
|
//# sourceMappingURL=stat.js.map
|
package/dist/widgets/stat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/widgets/stat.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/widgets/stat.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
import { Widget, type WidgetClass, type WidgetRequestContext } from '../widget.js';
|
|
1
|
+
import { Widget, parsePollingIntervalMs, type WidgetClass, type WidgetRequestContext } from '../widget.js';
|
|
2
2
|
import { Stat, type StatData } from './stat.js';
|
|
3
|
+
export type StatsOverviewBreakpoint = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
4
|
+
/**
|
|
5
|
+
* Cards-per-row for {@link StatsOverviewWidget} (Filament `getColumns()`).
|
|
6
|
+
* - `number` — that many columns from the `sm` breakpoint up (1 column on the smallest screens)
|
|
7
|
+
* - object — responsive map, e.g. `{ sm: 2, lg: 4 }`
|
|
8
|
+
*/
|
|
9
|
+
export type StatsOverviewColumns = number | Partial<Record<StatsOverviewBreakpoint, number>>;
|
|
10
|
+
export type StatsOverviewConfigurator = (widget: typeof StatsOverviewWidget) => void;
|
|
11
|
+
export declare function clampStatsOverviewColumns(value: number): number;
|
|
12
|
+
/** Filament auto `getColumns()` heuristic from stat count. */
|
|
13
|
+
export declare function autoStatsOverviewColumns(statsCount: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Normalize widget `columns` into a breakpoint map.
|
|
16
|
+
* When `columns` is null/undefined, uses Filament’s count-based default.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveStatsOverviewColumns(columns: StatsOverviewColumns | null | undefined, statsCount?: number): Partial<Record<StatsOverviewBreakpoint, number>>;
|
|
19
|
+
/** Inline CSS custom properties consumed by `.shamar-stats-overview__grid`. */
|
|
20
|
+
export declare function statsOverviewGridStyle(columns: StatsOverviewColumns | null | undefined, statsCount?: number): string;
|
|
3
21
|
/**
|
|
4
22
|
* Grid of KPI stat cards (Filament StatsOverviewWidget).
|
|
5
23
|
*/
|
|
6
24
|
export declare abstract class StatsOverviewWidget extends Widget {
|
|
25
|
+
/**
|
|
26
|
+
* Cards per row inside this widget (Filament `getColumns()`).
|
|
27
|
+
* Leave `null` for Filament’s count-based auto layout (3 or 4).
|
|
28
|
+
*/
|
|
29
|
+
static columns: StatsOverviewColumns | null;
|
|
30
|
+
/** Filament default: refresh every 5 seconds. Set `null` to disable. */
|
|
31
|
+
static pollingInterval: string | null;
|
|
32
|
+
/** Filament default: lazy-load when visible. */
|
|
33
|
+
static isLazy: boolean;
|
|
7
34
|
static stats(_ctx: WidgetRequestContext): Stat[] | StatData[] | Promise<Stat[] | StatData[]>;
|
|
35
|
+
/** Filament-style global defaults for every stats overview widget class. */
|
|
36
|
+
static configureUsing(callback: StatsOverviewConfigurator): void;
|
|
37
|
+
/** Test helper. */
|
|
38
|
+
static clearConfigureUsing(): void;
|
|
39
|
+
/** Apply {@link configureUsing} callbacks onto a concrete widget class (once). */
|
|
40
|
+
static applyConfigurators(WidgetClass: typeof StatsOverviewWidget): void;
|
|
8
41
|
}
|
|
9
42
|
export declare function isStatsOverviewWidget(value: WidgetClass): value is typeof StatsOverviewWidget;
|
|
43
|
+
export { parsePollingIntervalMs };
|
|
10
44
|
//# sourceMappingURL=stats-overview-widget.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats-overview-widget.d.ts","sourceRoot":"","sources":["../../src/widgets/stats-overview-widget.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"stats-overview-widget.d.ts","sourceRoot":"","sources":["../../src/widgets/stats-overview-widget.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;AAEpF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,CAAC;AAe7F,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,OAAO,mBAAmB,KAAK,IAAI,CAAC;AAIrF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKnE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,EAChD,UAAU,SAAI,GACb,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,CAsBlD;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,EAChD,UAAU,SAAI,GACb,MAAM,CAQR;AAED;;GAEG;AACH,8BAAsB,mBAAoB,SAAQ,MAAM;IACtD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAQ;IAEnD,wEAAwE;IACxE,OAAgB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEtD,gDAAgD;IAChD,OAAgB,MAAM,UAAQ;IAE9B,MAAM,CAAC,KAAK,CACV,IAAI,EAAE,oBAAoB,GACzB,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;IAIrD,4EAA4E;IAC5E,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAIhE,mBAAmB;IACnB,MAAM,CAAC,mBAAmB,IAAI,IAAI;IAKlC,kFAAkF;IAClF,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,mBAAmB,GAAG,IAAI;CAKzE;AAID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,KAAK,IAAI,OAAO,mBAAmB,CAO7F;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -1,12 +1,103 @@
|
|
|
1
|
-
import { Widget } from '../widget.js';
|
|
1
|
+
import { Widget, parsePollingIntervalMs, } from '../widget.js';
|
|
2
|
+
const COL_MIN = 1;
|
|
3
|
+
const COL_MAX = 12;
|
|
4
|
+
const BREAKPOINTS = ['default', 'sm', 'md', 'lg', 'xl', '2xl'];
|
|
5
|
+
const CSS_VARS = {
|
|
6
|
+
default: '--shamar-stats-cols',
|
|
7
|
+
sm: '--shamar-stats-cols-sm',
|
|
8
|
+
md: '--shamar-stats-cols-md',
|
|
9
|
+
lg: '--shamar-stats-cols-lg',
|
|
10
|
+
xl: '--shamar-stats-cols-xl',
|
|
11
|
+
'2xl': '--shamar-stats-cols-2xl',
|
|
12
|
+
};
|
|
13
|
+
const widgetConfigurators = [];
|
|
14
|
+
export function clampStatsOverviewColumns(value) {
|
|
15
|
+
if (!Number.isFinite(value))
|
|
16
|
+
return COL_MIN;
|
|
17
|
+
return Math.min(COL_MAX, Math.max(COL_MIN, Math.floor(value)));
|
|
18
|
+
}
|
|
19
|
+
/** Filament auto `getColumns()` heuristic from stat count. */
|
|
20
|
+
export function autoStatsOverviewColumns(statsCount) {
|
|
21
|
+
const count = Math.max(0, Math.floor(statsCount));
|
|
22
|
+
if (count < 3)
|
|
23
|
+
return 3;
|
|
24
|
+
if (count % 3 !== 1)
|
|
25
|
+
return 3;
|
|
26
|
+
return 4;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Normalize widget `columns` into a breakpoint map.
|
|
30
|
+
* When `columns` is null/undefined, uses Filament’s count-based default.
|
|
31
|
+
*/
|
|
32
|
+
export function resolveStatsOverviewColumns(columns, statsCount = 0) {
|
|
33
|
+
if (columns == null) {
|
|
34
|
+
const n = autoStatsOverviewColumns(statsCount);
|
|
35
|
+
return { default: 1, sm: n };
|
|
36
|
+
}
|
|
37
|
+
if (typeof columns === 'number') {
|
|
38
|
+
const n = clampStatsOverviewColumns(columns);
|
|
39
|
+
return { default: 1, sm: n };
|
|
40
|
+
}
|
|
41
|
+
const out = {};
|
|
42
|
+
for (const bp of BREAKPOINTS) {
|
|
43
|
+
const raw = columns[bp];
|
|
44
|
+
if (raw != null)
|
|
45
|
+
out[bp] = clampStatsOverviewColumns(raw);
|
|
46
|
+
}
|
|
47
|
+
if (!Object.keys(out).length) {
|
|
48
|
+
const n = autoStatsOverviewColumns(statsCount);
|
|
49
|
+
return { default: 1, sm: n };
|
|
50
|
+
}
|
|
51
|
+
if (out.default == null)
|
|
52
|
+
out.default = 1;
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/** Inline CSS custom properties consumed by `.shamar-stats-overview__grid`. */
|
|
56
|
+
export function statsOverviewGridStyle(columns, statsCount = 0) {
|
|
57
|
+
const resolved = resolveStatsOverviewColumns(columns, statsCount);
|
|
58
|
+
const parts = [];
|
|
59
|
+
for (const bp of BREAKPOINTS) {
|
|
60
|
+
const n = resolved[bp];
|
|
61
|
+
if (n != null)
|
|
62
|
+
parts.push(`${CSS_VARS[bp]}: ${n}`);
|
|
63
|
+
}
|
|
64
|
+
return parts.join('; ');
|
|
65
|
+
}
|
|
2
66
|
/**
|
|
3
67
|
* Grid of KPI stat cards (Filament StatsOverviewWidget).
|
|
4
68
|
*/
|
|
5
69
|
export class StatsOverviewWidget extends Widget {
|
|
70
|
+
/**
|
|
71
|
+
* Cards per row inside this widget (Filament `getColumns()`).
|
|
72
|
+
* Leave `null` for Filament’s count-based auto layout (3 or 4).
|
|
73
|
+
*/
|
|
74
|
+
static columns = null;
|
|
75
|
+
/** Filament default: refresh every 5 seconds. Set `null` to disable. */
|
|
76
|
+
static pollingInterval = '5s';
|
|
77
|
+
/** Filament default: lazy-load when visible. */
|
|
78
|
+
static isLazy = true;
|
|
6
79
|
static stats(_ctx) {
|
|
7
80
|
return [];
|
|
8
81
|
}
|
|
82
|
+
/** Filament-style global defaults for every stats overview widget class. */
|
|
83
|
+
static configureUsing(callback) {
|
|
84
|
+
widgetConfigurators.push(callback);
|
|
85
|
+
}
|
|
86
|
+
/** Test helper. */
|
|
87
|
+
static clearConfigureUsing() {
|
|
88
|
+
widgetConfigurators.length = 0;
|
|
89
|
+
configuredWidgets = new WeakSet();
|
|
90
|
+
}
|
|
91
|
+
/** Apply {@link configureUsing} callbacks onto a concrete widget class (once). */
|
|
92
|
+
static applyConfigurators(WidgetClass) {
|
|
93
|
+
if (configuredWidgets.has(WidgetClass))
|
|
94
|
+
return;
|
|
95
|
+
for (const configure of widgetConfigurators)
|
|
96
|
+
configure(WidgetClass);
|
|
97
|
+
configuredWidgets.add(WidgetClass);
|
|
98
|
+
}
|
|
9
99
|
}
|
|
100
|
+
let configuredWidgets = new WeakSet();
|
|
10
101
|
export function isStatsOverviewWidget(value) {
|
|
11
102
|
let current = value;
|
|
12
103
|
while (typeof current === 'function') {
|
|
@@ -16,4 +107,5 @@ export function isStatsOverviewWidget(value) {
|
|
|
16
107
|
}
|
|
17
108
|
return false;
|
|
18
109
|
}
|
|
110
|
+
export { parsePollingIntervalMs };
|
|
19
111
|
//# sourceMappingURL=stats-overview-widget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats-overview-widget.js","sourceRoot":"","sources":["../../src/widgets/stats-overview-widget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+
|
|
1
|
+
{"version":3,"file":"stats-overview-widget.js","sourceRoot":"","sources":["../../src/widgets/stats-overview-widget.ts"],"names":[],"mappings":"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"}
|