@rebasepro/plugin-insights 0.22.0 → 0.24.0
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 +76 -49
- package/dist/components/CollectionInsightsInline.d.ts +1 -5
- package/dist/components/HomeCardInsightSlot.d.ts +2 -7
- package/dist/components/HomeInsightsSlot.d.ts +0 -2
- package/dist/components/InsightWidget.d.ts +2 -15
- package/dist/components/InsightsRow.d.ts +13 -0
- package/dist/components/InsightsScorecardView.d.ts +14 -13
- package/dist/engine/InsightsEngine.d.ts +48 -0
- package/dist/engine/InsightsProvider.d.ts +8 -10
- package/dist/engine/useInsightSource.d.ts +12 -0
- package/dist/format.d.ts +21 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.es.js +403 -425
- package/dist/index.es.js.map +1 -1
- package/dist/types/engine.d.ts +81 -53
- package/dist/types/widgets.d.ts +6 -37
- package/dist/useInsightsPlugin.d.ts +28 -17
- package/dist/validateConfig.d.ts +7 -0
- package/package.json +5 -5
- package/dist/components/InsightWidgetSkeleton.d.ts +0 -29
- package/dist/engine/InsightsCache.d.ts +0 -18
- package/dist/engine/useInsightsData.d.ts +0 -17
package/README.md
CHANGED
|
@@ -16,99 +16,122 @@ of it resolves too: Node has supported `require(esm)` since 22.12.
|
|
|
16
16
|
|
|
17
17
|
## What This Package Does
|
|
18
18
|
|
|
19
|
-
This plugin
|
|
19
|
+
This plugin puts figures — revenue, orders, open tickets — into the Rebase admin
|
|
20
|
+
UI, each beside its change over a comparison period. You declare named
|
|
21
|
+
`sources`, functions that fetch one record of figures for that period: use the
|
|
22
|
+
Rebase SDK, call a backend function, or hit any API. Each insight names the
|
|
23
|
+
source and the field it reads. The plugin fetches each source once per signed-in
|
|
24
|
+
user, caches it, works out the change, and renders it in the right slots.
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
Figures appear in three places:
|
|
22
27
|
|
|
23
|
-
- **Home page header
|
|
24
|
-
- **Collection list view
|
|
25
|
-
- **Home page cards
|
|
28
|
+
- **Home page header**: a row of KPI cards via the `home.children.start` slot
|
|
29
|
+
- **Collection list view**: a row of figures below the title, above the list, via `collection.widgets`
|
|
30
|
+
- **Home page cards**: compact figures on each collection's card via `home.card.widget`
|
|
26
31
|
|
|
27
|
-
Collection
|
|
32
|
+
Collection insights are defined once, under `collections.<slug>`, and render
|
|
33
|
+
both in the collection's list view and on its home card. Every insight that
|
|
34
|
+
reads a source shares one fetch of it, so a figure shown in two places is the
|
|
35
|
+
same number.
|
|
28
36
|
|
|
29
37
|
## Key Exports
|
|
30
38
|
|
|
31
39
|
| Export | Type | Description |
|
|
32
40
|
|---|---|---|
|
|
33
41
|
| `useInsightsPlugin` | Hook | Creates the plugin from an `InsightsPluginConfig`. Returns a `RebasePlugin` |
|
|
34
|
-
| `InsightsPluginConfig` | Type | Top-level config: `insights` (home + collections)
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
42
|
+
| `InsightsPluginConfig` | Type | Top-level config: `sources`, `insights` (home + collections), optional `period` and `cacheTTL` |
|
|
43
|
+
| `InsightSource` | Type | `(context: { period }) => Promise<DataRow>`: fetches one record of figures |
|
|
44
|
+
| `InsightSourceContext` | Type | What a source is called with: `{ period: InsightPeriod }` |
|
|
45
|
+
| `InsightPeriod` | Type | The resolved windows: `days`, `from`, `to`, `previousFrom` |
|
|
46
|
+
| `InsightPeriodConfig` | Type | `{ days }`, the comparison window |
|
|
47
|
+
| `InsightDefinition` | Type | One figure: `id`, `title`, `source`, `value`, optional `comparison` and `icon` |
|
|
48
|
+
| `InsightComparison` | Type | `previous` field, `intent`, and `show` (`percent` or `absolute`) |
|
|
49
|
+
| `InsightFormat` | Type | Number formatting: `style` (decimal/currency/percent), `notation`, `currency`, `decimals` |
|
|
37
50
|
| `DataRow` | Type | `Record<string, string \| number \| boolean \| null>` |
|
|
38
|
-
| `ScorecardConfig` | Type | Field mapping for value, comparison, icon, dateRange |
|
|
39
|
-
| `ScorecardFormat` | Type | Number formatting: style (decimal/currency/percent), notation, currency, decimals, showSign |
|
|
40
51
|
| `InsightsProvider` | Component | React context provider (injected automatically by the plugin) |
|
|
41
52
|
| `useInsightsEngine` | Hook | Access the insights engine from context (advanced) |
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
53
|
+
| `InsightsEngine` | Class | Fetches and caches sources per user, and anchors the period (advanced) |
|
|
54
|
+
| `resolvePeriod` | Function | `(days, to) => InsightPeriod` (advanced) |
|
|
55
|
+
| `useInsightSource` | Hook | Reads one source for the signed-in user (custom layouts) |
|
|
56
|
+
| `InsightsRow` | Component | A row of insights under the period label (custom layouts) |
|
|
57
|
+
| `InsightsScorecardView` | Component | Renders one figure from a record and its definition (custom layouts) |
|
|
58
|
+
| `InsightWidget` | Component | Single insight container (custom layouts) |
|
|
47
59
|
|
|
48
60
|
### `InsightsPluginConfig`
|
|
49
61
|
|
|
50
62
|
| Prop | Type | Default | Description |
|
|
51
63
|
|---|---|---|---|
|
|
64
|
+
| `sources` | `Record<string, InsightSource>` | — | Where the figures come from, by name. Required |
|
|
52
65
|
| `insights.home` | `InsightDefinition[]` | — | Insights shown at the top of the home page |
|
|
53
66
|
| `insights.collections` | `Record<string, InsightDefinition[]>` | — | Insights per collection slug |
|
|
54
|
-
| `
|
|
67
|
+
| `period.days` | `number` | `30` | The comparison window: the last N days against the N days before them |
|
|
68
|
+
| `cacheTTL` | `number` | `60_000` | How long a fetched source is reused, in milliseconds |
|
|
55
69
|
|
|
56
|
-
|
|
70
|
+
Creating the plugin throws when an insight names a source that `sources` does
|
|
71
|
+
not declare, or when `period.days` is not a whole number of at least 1. Pass a
|
|
72
|
+
memoized config: a new `sources` object starts a new cache.
|
|
73
|
+
|
|
74
|
+
### `InsightDefinition`
|
|
57
75
|
|
|
58
76
|
| Prop | Type | Description |
|
|
59
77
|
|---|---|---|
|
|
60
|
-
| `
|
|
61
|
-
| `value.
|
|
62
|
-
| `
|
|
63
|
-
| `comparison.
|
|
64
|
-
| `comparison.intent` | `"increase_is_good" \| "decrease_is_good"` |
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
78
|
+
| `source` | `string` | The key in `sources` this insight reads |
|
|
79
|
+
| `value.field` | `string` | The field holding the figure |
|
|
80
|
+
| `value.format` | `InsightFormat` | How to write it, in the admin panel's language |
|
|
81
|
+
| `comparison.previous` | `string` | The field holding the same figure for the previous period |
|
|
82
|
+
| `comparison.intent` | `"increase_is_good" \| "decrease_is_good"` | Which direction reads as good news |
|
|
83
|
+
| `comparison.show` | `"percent" \| "absolute"` | The relative change (default), or the difference. Use `absolute` for small counts |
|
|
84
|
+
| `icon` | `string` | Icon key (e.g., `"ShoppingCart"`), resolved via `getIcon` |
|
|
67
85
|
|
|
68
86
|
## Quick Start
|
|
69
87
|
|
|
70
88
|
```tsx
|
|
89
|
+
import { useMemo } from "react";
|
|
71
90
|
import { Rebase } from "@rebasepro/app";
|
|
72
91
|
import { RebaseShell } from "@rebasepro/cms";
|
|
73
92
|
import { useInsightsPlugin } from "@rebasepro/plugin-insights";
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
import type { DataRow, InsightPeriod } from "@rebasepro/plugin-insights";
|
|
94
|
+
|
|
95
|
+
const windowQuery = (period: InsightPeriod) => new URLSearchParams({
|
|
96
|
+
previousFrom: period.previousFrom.toISOString(),
|
|
97
|
+
from: period.from.toISOString(),
|
|
98
|
+
to: period.to.toISOString()
|
|
99
|
+
}).toString();
|
|
100
|
+
|
|
101
|
+
const insightsPlugin = useInsightsPlugin(useMemo(() => ({
|
|
102
|
+
period: { days: 30 },
|
|
103
|
+
sources: {
|
|
104
|
+
// One request answers every insight below: { revenue, previousRevenue, shipped, previousShipped }
|
|
105
|
+
orders: ({ period }) => rebaseClient.functions.invoke<DataRow>("insights", undefined, {
|
|
106
|
+
method: "GET",
|
|
107
|
+
path: `orders?${windowQuery(period)}`
|
|
108
|
+
})
|
|
109
|
+
},
|
|
77
110
|
insights: {
|
|
78
111
|
home: [
|
|
79
112
|
{
|
|
80
113
|
id: "revenue",
|
|
81
114
|
title: "Revenue",
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
scorecard: {
|
|
87
|
-
value: { field: "total", format: { style: "currency", currency: "USD", notation: "compact" } },
|
|
88
|
-
comparison: { field: "delta_pct", format: { style: "percent", decimals: 1 }, intent: "increase_is_good" },
|
|
89
|
-
icon: "attach_money",
|
|
90
|
-
dateRange: "Last 30 days"
|
|
91
|
-
}
|
|
115
|
+
source: "orders",
|
|
116
|
+
icon: "DollarSign",
|
|
117
|
+
value: { field: "revenue", format: { style: "currency", currency: "USD", notation: "compact" } },
|
|
118
|
+
comparison: { previous: "previousRevenue", intent: "increase_is_good" }
|
|
92
119
|
}
|
|
93
120
|
],
|
|
94
121
|
collections: {
|
|
95
122
|
orders: [
|
|
96
123
|
{
|
|
97
|
-
id: "
|
|
98
|
-
title: "
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
scorecard: {
|
|
104
|
-
value: { field: "total", format: { style: "decimal", notation: "compact" } },
|
|
105
|
-
icon: "shopping_cart"
|
|
106
|
-
}
|
|
124
|
+
id: "shipped",
|
|
125
|
+
title: "Shipped",
|
|
126
|
+
source: "orders",
|
|
127
|
+
icon: "Truck",
|
|
128
|
+
value: { field: "shipped" },
|
|
129
|
+
comparison: { previous: "previousShipped", intent: "increase_is_good", show: "absolute" }
|
|
107
130
|
}
|
|
108
131
|
]
|
|
109
132
|
}
|
|
110
133
|
}
|
|
111
|
-
});
|
|
134
|
+
}), []));
|
|
112
135
|
|
|
113
136
|
// Pass to your Rebase app:
|
|
114
137
|
<Rebase client={rebaseClient} plugins={[insightsPlugin]}>
|
|
@@ -116,6 +139,10 @@ const insightsPlugin = useInsightsPlugin({
|
|
|
116
139
|
</Rebase>
|
|
117
140
|
```
|
|
118
141
|
|
|
142
|
+
A source runs in the browser under the signed-in user's permissions. The demo
|
|
143
|
+
app's `insights` backend function (`app/backend/functions/insights.ts`) is one
|
|
144
|
+
way to compute both windows in a single query.
|
|
145
|
+
|
|
119
146
|
## Related Packages
|
|
120
147
|
|
|
121
148
|
- `@rebasepro/app` — Core framework providing the plugin system
|
|
@@ -6,11 +6,7 @@ import type { InsightDefinition } from "../types/index.js";
|
|
|
6
6
|
*
|
|
7
7
|
* Injected via the `collection.widgets` slot.
|
|
8
8
|
*/
|
|
9
|
-
export declare function CollectionInsightsInline({ insights
|
|
10
|
-
path: string;
|
|
11
|
-
collection: unknown;
|
|
12
|
-
parentCollectionSlugs: string[];
|
|
13
|
-
parentEntityIds: string[];
|
|
9
|
+
export declare function CollectionInsightsInline({ insights }: {
|
|
14
10
|
insights: InsightDefinition[];
|
|
15
11
|
}): React.JSX.Element | null;
|
|
16
12
|
export declare namespace CollectionInsightsInline {
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { InsightDefinition } from "../types/index.js";
|
|
3
3
|
/**
|
|
4
|
-
* Renders compact insight
|
|
4
|
+
* Renders compact insight readouts inside a home page collection card.
|
|
5
5
|
* Injected via the `home.card.widget` slot.
|
|
6
|
-
*
|
|
7
|
-
* Uses a horizontal flex layout so multiple cards sit side by side.
|
|
8
6
|
*/
|
|
9
|
-
export declare function HomeCardInsightSlot({
|
|
10
|
-
slug: string;
|
|
11
|
-
collection: unknown;
|
|
12
|
-
context: unknown;
|
|
7
|
+
export declare function HomeCardInsightSlot({ insights }: {
|
|
13
8
|
insights: InsightDefinition[];
|
|
14
9
|
}): React.JSX.Element | null;
|
|
15
10
|
export declare namespace HomeCardInsightSlot {
|
|
@@ -3,8 +3,6 @@ import type { InsightDefinition } from "../types/index.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Scorecard insights panel rendered at the top of the home page.
|
|
5
5
|
* Injected via the `home.children.start` slot.
|
|
6
|
-
*
|
|
7
|
-
* Renders scorecards in a responsive grid (up to 4 columns).
|
|
8
6
|
*/
|
|
9
7
|
export declare function HomeInsightsSlot({ insights }: {
|
|
10
8
|
insights: InsightDefinition[];
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { InsightDefinition } from "../types/index.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* Wraps skeleton and loaded states in a fixed-height container
|
|
7
|
-
* (computed from the scorecard config) to prevent layout shift.
|
|
8
|
-
*
|
|
9
|
-
* All theme-awareness is handled via Tailwind `dark:` classes.
|
|
10
|
-
*/
|
|
11
|
-
export declare function InsightWidget({ definition, collectionSlug, path, parentCollectionSlugs, parentEntityIds, compact, embedded }: {
|
|
3
|
+
/** One insight, reading its source through the shared engine. */
|
|
4
|
+
export declare function InsightWidget({ definition, compact }: {
|
|
12
5
|
definition: InsightDefinition;
|
|
13
|
-
collectionSlug?: string;
|
|
14
|
-
path?: string;
|
|
15
|
-
parentCollectionSlugs?: string[];
|
|
16
|
-
parentEntityIds?: string[];
|
|
17
6
|
compact?: boolean;
|
|
18
|
-
/** When true, inner views skip their own borders since the parent card provides them. */
|
|
19
|
-
embedded?: boolean;
|
|
20
7
|
}): React.JSX.Element;
|
|
21
8
|
export declare namespace InsightWidget {
|
|
22
9
|
var displayName: string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { InsightDefinition } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* A row of insight tiles. When any of them compares with the previous period,
|
|
5
|
+
* the row says which period once, above the tiles, rather than on each.
|
|
6
|
+
*/
|
|
7
|
+
export declare function InsightsRow({ insights, className }: {
|
|
8
|
+
insights: InsightDefinition[];
|
|
9
|
+
className?: string;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
export declare namespace InsightsRow {
|
|
12
|
+
var displayName: string;
|
|
13
|
+
}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { InsightDefinition } from "../types/index.js";
|
|
3
|
+
import type { SourceResult } from "../engine/InsightsEngine.js";
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* One insight: its label, its value and its change on the previous period.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* The label and icon are known before the figures are, so they render while
|
|
8
|
+
* the source loads and only the figures pulse. Loading, loaded and failed
|
|
9
|
+
* share one shell, so nothing moves when the data arrives.
|
|
10
|
+
*
|
|
11
|
+
* `compact` is the inline readout on a home-page card; the default is a tile.
|
|
9
12
|
*/
|
|
10
|
-
export declare function InsightsScorecardView({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
export declare function InsightsScorecardView({ definition, result, loading, error, compact }: {
|
|
14
|
+
definition: InsightDefinition;
|
|
15
|
+
/** The source's record and the period it was fetched for. */
|
|
16
|
+
result: SourceResult | null;
|
|
17
|
+
loading?: boolean;
|
|
18
|
+
error?: Error | null;
|
|
14
19
|
compact?: boolean;
|
|
15
|
-
/** When true, skip own border/bg since the parent card provides them. */
|
|
16
|
-
embedded?: boolean;
|
|
17
|
-
/** Explicit height to prevent layout shift between skeleton → loaded. */
|
|
18
|
-
fixedHeight?: number;
|
|
19
20
|
}): React.JSX.Element;
|
|
20
21
|
export declare namespace InsightsScorecardView {
|
|
21
22
|
var displayName: string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DataRow, InsightPeriod, InsightSource } from "../types/index.js";
|
|
2
|
+
export declare const DEFAULT_PERIOD_DAYS = 30;
|
|
3
|
+
/** The current and previous windows of `days` days, ending at `to`. */
|
|
4
|
+
export declare function resolvePeriod(days: number, to: Date): InsightPeriod;
|
|
5
|
+
/** A source's record, with the period it was fetched for. */
|
|
6
|
+
export interface SourceResult {
|
|
7
|
+
row: DataRow;
|
|
8
|
+
period: InsightPeriod;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The cache key for one source, for one user.
|
|
12
|
+
*
|
|
13
|
+
* The engine lives at the root of the app and outlives a sign-out, and a figure
|
|
14
|
+
* is computed under the permissions and row-level security of whoever asked
|
|
15
|
+
* for it. A key without the user would serve the previous account's numbers to
|
|
16
|
+
* the next one that signs in on the same tab, until the TTL ran out.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sourceCacheKey(sourceId: string, userId: string | null): string;
|
|
19
|
+
/**
|
|
20
|
+
* Fetches and caches the plugin's sources.
|
|
21
|
+
*
|
|
22
|
+
* Every insight that reads a source shares one fetch of it: concurrent reads
|
|
23
|
+
* join the request in flight, later ones read the cache until the TTL passes.
|
|
24
|
+
* That is what keeps a figure shown on the home page and in a collection view
|
|
25
|
+
* the same number.
|
|
26
|
+
*/
|
|
27
|
+
export declare class InsightsEngine {
|
|
28
|
+
private readonly sources;
|
|
29
|
+
readonly periodDays: number;
|
|
30
|
+
private readonly ttl;
|
|
31
|
+
private readonly now;
|
|
32
|
+
private readonly cache;
|
|
33
|
+
private readonly inflight;
|
|
34
|
+
private anchor;
|
|
35
|
+
constructor(sources: Record<string, InsightSource>, periodDays?: number, ttl?: number, now?: () => number);
|
|
36
|
+
/**
|
|
37
|
+
* The period a fetch starting now is asked for. Its end is fixed by the
|
|
38
|
+
* first fetch and kept until the TTL passes, so sources fetched for the
|
|
39
|
+
* same screen describe the same window.
|
|
40
|
+
*/
|
|
41
|
+
period(): InsightPeriod;
|
|
42
|
+
/** The cached result for this source and user, if it is still fresh. */
|
|
43
|
+
peek(sourceId: string, userId: string | null): SourceResult | null;
|
|
44
|
+
/** The source's record for this user: from the cache, the fetch in flight, or a new fetch. */
|
|
45
|
+
load(sourceId: string, userId: string | null): Promise<SourceResult>;
|
|
46
|
+
/** Drops every cached result and fetch in flight, and re-anchors the period on the next fetch. */
|
|
47
|
+
invalidate(): void;
|
|
48
|
+
}
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import React, { type PropsWithChildren } from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
cache: InsightsCache;
|
|
5
|
-
}
|
|
2
|
+
import type { InsightSource } from "../types/index.js";
|
|
3
|
+
import { InsightsEngine } from "./InsightsEngine.js";
|
|
6
4
|
/**
|
|
7
5
|
* Root-level provider for the insights data engine.
|
|
8
6
|
* Injected automatically by the plugin via `providers: [{ scope: "root" }]`.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
* for TTL-based caching and inflight request deduplication.
|
|
8
|
+
* Holds the one `InsightsEngine` every insight widget reads its source from.
|
|
12
9
|
*/
|
|
13
|
-
export declare function InsightsProvider({ cacheTTL, children }: PropsWithChildren<{
|
|
10
|
+
export declare function InsightsProvider({ sources, periodDays, cacheTTL, children }: PropsWithChildren<{
|
|
11
|
+
sources: Record<string, InsightSource>;
|
|
12
|
+
periodDays?: number;
|
|
14
13
|
cacheTTL?: number;
|
|
15
14
|
}>): React.JSX.Element;
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
16
|
+
* The insights engine (for advanced usage).
|
|
18
17
|
* Returns null when called outside of an `InsightsProvider`
|
|
19
18
|
* (e.g. during auth-loading phase before plugin providers mount).
|
|
20
19
|
*/
|
|
21
|
-
export declare function useInsightsEngine():
|
|
22
|
-
export {};
|
|
20
|
+
export declare function useInsightsEngine(): InsightsEngine | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type SourceResult } from "./InsightsEngine.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reads one source for the signed-in user.
|
|
4
|
+
*
|
|
5
|
+
* Waits for auth to settle: a source runs under the caller's permissions, so
|
|
6
|
+
* fetching before the user is known would compute the figures for nobody.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useInsightSource(sourceId: string): {
|
|
9
|
+
result: SourceResult | null;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
};
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { InsightComparison, InsightFormat } from "./types/index.js";
|
|
2
|
+
/** Writes a value the way its insight asks, in the admin panel's language. */
|
|
3
|
+
export declare function formatValue(value: number, format: InsightFormat | undefined, locale: string | undefined): string;
|
|
4
|
+
export type ChangeDirection = "up" | "down" | "flat";
|
|
5
|
+
export interface FormattedChange {
|
|
6
|
+
direction: ChangeDirection;
|
|
7
|
+
/** The size of the change, unsigned: the direction carries the sign. */
|
|
8
|
+
magnitude: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The change from `previous` to `current`, written as the comparison asks.
|
|
12
|
+
*
|
|
13
|
+
* A percentage needs a previous figure to be a percentage of, so a change
|
|
14
|
+
* from zero is written as the difference instead. Under 10% keeps one
|
|
15
|
+
* decimal (`0.2%`), above it none (`42%`): the decimal stops carrying
|
|
16
|
+
* information once the change is that large.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatChange(current: number, previous: number, comparison: InsightComparison, format: InsightFormat | undefined, locale: string | undefined): FormattedChange;
|
|
19
|
+
export type ChangeTone = "positive" | "negative" | "neutral";
|
|
20
|
+
/** Whether a change in this direction is good news for this insight. */
|
|
21
|
+
export declare function changeTone(direction: ChangeDirection, intent: InsightComparison["intent"]): ChangeTone;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export type { DataRow,
|
|
1
|
+
export type { DataRow, InsightFormat, InsightComparison, InsightDefinition, InsightPeriod, InsightPeriodConfig, InsightSource, InsightSourceContext, InsightsPluginConfig } from "./types/index.js";
|
|
2
2
|
export { useInsightsPlugin } from "./useInsightsPlugin.js";
|
|
3
3
|
export { InsightsProvider, useInsightsEngine } from "./engine/InsightsProvider.js";
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
4
|
+
export { InsightsEngine, resolvePeriod } from "./engine/InsightsEngine.js";
|
|
5
|
+
export type { SourceResult } from "./engine/InsightsEngine.js";
|
|
6
|
+
export { useInsightSource } from "./engine/useInsightSource.js";
|
|
6
7
|
export { InsightsScorecardView } from "./components/InsightsScorecardView.js";
|
|
7
8
|
export { InsightWidget } from "./components/InsightWidget.js";
|
|
8
|
-
export {
|
|
9
|
+
export { InsightsRow } from "./components/InsightsRow.js";
|