@bicharts/chart-host 0.5.106 → 0.5.108
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/{chunk-HLNXXQA5.mjs → chunk-RHBT4HTP.mjs} +329 -301
- package/dist/index.mjs +246 -102
- package/dist/react.mjs +13 -2
- package/dist/types/host.d.ts +16 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/invalidSentinel.d.ts +14 -0
- package/dist/types/productFeedback.d.ts +88 -0
- package/dist/types/react.d.ts +7 -0
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
createChartHost,
|
|
5
5
|
geoFromCache,
|
|
6
6
|
loadGeo
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RHBT4HTP.mjs";
|
|
8
8
|
import "./chunk-A2GMXZP7.mjs";
|
|
9
9
|
import "./chunk-GHODWOAL.mjs";
|
|
10
10
|
|
|
@@ -53,6 +53,7 @@ function BicChart(props) {
|
|
|
53
53
|
viewState,
|
|
54
54
|
labelContrast,
|
|
55
55
|
onLabelContrast,
|
|
56
|
+
onInvalidSentinel,
|
|
56
57
|
id,
|
|
57
58
|
filteredBy,
|
|
58
59
|
respondsWith,
|
|
@@ -78,6 +79,8 @@ function BicChart(props) {
|
|
|
78
79
|
onSelectRef.current = onSelect;
|
|
79
80
|
const onLabelContrastRef = useRef(onLabelContrast);
|
|
80
81
|
onLabelContrastRef.current = onLabelContrast;
|
|
82
|
+
const onInvalidSentinelRef = useRef(onInvalidSentinel);
|
|
83
|
+
onInvalidSentinelRef.current = onInvalidSentinel;
|
|
81
84
|
const [geoTick, setGeoTick] = useState(0);
|
|
82
85
|
useEffect(() => {
|
|
83
86
|
if (!geoKind || geoFromCache(geoKind)) return;
|
|
@@ -104,7 +107,15 @@ function BicChart(props) {
|
|
|
104
107
|
geoKind,
|
|
105
108
|
viewState,
|
|
106
109
|
labelContrast,
|
|
107
|
-
onLabelContrast: (r) => onLabelContrastRef.current?.(r)
|
|
110
|
+
onLabelContrast: (r) => onLabelContrastRef.current?.(r),
|
|
111
|
+
// A GETTER, not a wrapper: the host decides whether to
|
|
112
|
+
// swallow the sentinel throw by whether this is SET, so
|
|
113
|
+
// an always-present wrapper would hide the throw from a
|
|
114
|
+
// page that never asked. Read at throw time, so the
|
|
115
|
+
// newest prop wins without a rebuild.
|
|
116
|
+
get onInvalidSentinel() {
|
|
117
|
+
return onInvalidSentinelRef.current ? (info) => onInvalidSentinelRef.current?.(info) : void 0;
|
|
118
|
+
}
|
|
108
119
|
});
|
|
109
120
|
hostRef.current = host;
|
|
110
121
|
const off = host.selection.onChange((payloadIdxs, source) => {
|
package/dist/types/host.d.ts
CHANGED
|
@@ -165,6 +165,22 @@ export interface ChartHostConfig {
|
|
|
165
165
|
labelContrast?: boolean | LabelContrastOptions;
|
|
166
166
|
/** What the label-contrast pass did after each render - counts, so a host can log them. */
|
|
167
167
|
onLabelContrast?: (report: LabelContrastReport) => void;
|
|
168
|
+
/**
|
|
169
|
+
* THE CHART SAID THE DATA LACKS SOMETHING IT IS BUILT ON. Generated code has one sanctioned
|
|
170
|
+
* hard stop at runtime: a column the chart needs is gone from `data.columns`, and it throws
|
|
171
|
+
* `new Error('INVALID:column "<name>" not found')`. That is a DATA STATE, not a broken chart -
|
|
172
|
+
* the same code draws again once the column is back - so a host should say what is missing,
|
|
173
|
+
* keep the code, and re-render on the next data change rather than report a crash.
|
|
174
|
+
*
|
|
175
|
+
* Supplied: render() clears the container, calls this with the chart's reason (the text after
|
|
176
|
+
* `INVALID:` on that line) and the full message, and returns normally - nothing was drawn, so
|
|
177
|
+
* no post-render pass (label contrast, hit-target heal, census, fit) runs. Absent: render()
|
|
178
|
+
* throws exactly as it always has, so an existing host is untouched.
|
|
179
|
+
*/
|
|
180
|
+
onInvalidSentinel?: (info: {
|
|
181
|
+
reason: string;
|
|
182
|
+
message: string;
|
|
183
|
+
}) => void;
|
|
168
184
|
}
|
|
169
185
|
export interface ChartHost {
|
|
170
186
|
render(): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { planTrivialChart, compileTrivialSource, type TrivialPlan, type TrivialS
|
|
|
12
12
|
export { captureSvgSnapshot, svgToDataUrl, svgNaturalSize, rasterizeSvgToPngDataUrl, type SnapshotOptions } from "./snapshot";
|
|
13
13
|
export { shouldReview, buildReviewWire, bareBase64, actionFor, type ReviewGate, type ReviewWire, type ReviewVerdict, type ReviewAction } from "./review";
|
|
14
14
|
export { askApplyImprovements, type ReviewDialogOptions, type ReviewDialogText } from "./reviewDialog";
|
|
15
|
+
export { mountProductFeedbackBox, normaliseProductFeedbackText, productFeedbackSendable, buildProductFeedbackPayload, PRODUCT_FEEDBACK_MAX_CHARS, PRODUCT_FEEDBACK_MIN_CHARS, type ProductFeedbackBox, type ProductFeedbackBoxOptions, type ProductFeedbackText, type ProductFeedbackSendResult, type ProductFeedbackPayload, type ProductFeedbackIdentity, type ProductFeedbackHost, } from "./productFeedback";
|
|
15
16
|
export { qualifyGroupHeadingFor, newQualifyGroupState, type QualifyGroupRow, type QualifyGroupState, type QualifyGroupHeading, orderRefusalsForDisplay, refusalIsSelectable, hasRefusalsToShow, qualifyRefusalHeadingFor, newQualifyRefusalGroupState, qualifyRefusalReason, QUALIFY_REFUSAL_UNSPECIFIED, type QualifyRefusalRow, type QualifyRefusalGroupState, type QualifyRefusalHeading, } from "./qualifyGroups";
|
|
16
17
|
export { qualifyPick, qualifyAuto, qualifyCancel, launchGenerates, launchFavorStyle, chooserFitsViewport, shouldOpenChooserOnGenerate, shouldOpenInlineChooserOnGenerate, canConfirmLaunch, confirmLaunch, qualifyFailureFallsOpen, CHOOSER_MIN_WIDTH_PX, CHOOSER_MIN_HEIGHT_PX, type QualifyLaunchOutcome, type ChooserGateInput, } from "./qualifyLaunch";
|
|
17
18
|
export { normalizeFilterTerm, filterQualifyRows, readQualifyChartRow, readQualifyRefusalRow, filterFitsChooser, listNeedsFilter, qualifyFilterGate, inlineFilterGate, FILTER_MIN_TERM_CHARS, FILTER_ROW_PX, FILTER_MIN_WIDTH_PX, FILTER_MIN_HEIGHT_PX, INLINE_FILTER_MIN_ROWS, computeQualifyFilterView, qualifyFilterCountText, type QualifyFilterTier, type QualifyFilterResult, type QualifyFilterRead, type QualifyFilterGateReason, type QualifyFilterGateInput, type QualifyFilterRow, type QualifyFilterGroup, type QualifyFilterView, type QualifyFilterNoteKind, } from "./qualifyFilter";
|
|
@@ -22,6 +23,7 @@ export { ensureCrossfilterHitTargets, type HitTargetReport } from "./hitTargets"
|
|
|
22
23
|
export { applyLabelContrast, LABEL_CONTRAST_DONE_ATTR, LABEL_CONTRAST_CAP, type LabelContrastOptions, type LabelContrastReport, } from "./labelContrastDom";
|
|
23
24
|
export { decideLabelColor, toRGBA, compositeOver, relativeLuminance, contrastRatio, isPillBackdropAlpha, pillBacksGlyph, backingHoldsGlyph, cellSuppressesNormalize, glyphSampleGrid, DARK_TEXT, LIGHT_TEXT, MIN_CONTRAST, WHITE_TEXT_BG_LUM, PILL_MIN_ALPHA, PILL_OPAQUE_ALPHA, PILL_MIN_COVERAGE, PAGE_MATCH_TOLERANCE, BACKING_MAJORITY, GLYPH_SAMPLE_N, type LabelDecision, } from "./labelContrast";
|
|
24
25
|
export { censusMarks, isBlankRender, blankRenderFlag, type MarkCensus, type BlankVerdictInput } from "./blankRender";
|
|
26
|
+
export { isInvalidSentinelError, invalidSentinelReason } from "./invalidSentinel";
|
|
25
27
|
export { censusHitBands, hitBandFlag, MIN_HIT_BAND_PX, type HitBandCensus } from "./hitBands";
|
|
26
28
|
export { censusColourSpread, colourSpreadFlag, SAME_SHADE_DELTA_E, MIN_RAMP_FILLS, type ColourSpreadCensus } from "./colourSpread";
|
|
27
29
|
export { censusValuePlacement, valuePlacementFlag, VALUE_AXIS_MIN_FIT, type ValuePlacementCensus } from "./valuePlacement";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when an error message, Python traceback or "Error:"-prefixed result carries the generated
|
|
3
|
+
* code's INVALID sentinel. Matches the uppercase marker followed by a colon (space allowed before
|
|
4
|
+
* the colon) anywhere in the text - Python surfaces it inside `ValueError: INVALID:...` at the END
|
|
5
|
+
* of a multi-line traceback; a D3 throw surfaces it directly in `Error.message`. Lowercase
|
|
6
|
+
* "Invalid" and the bare word without a colon are ordinary errors.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isInvalidSentinelError(text: string | null | undefined): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The reason the chart gave: the text after the first `INVALID:` up to the end of that line,
|
|
11
|
+
* trimmed, and capped at `max` characters with an ASCII "..." so a host can put it in a one-line
|
|
12
|
+
* status. Empty string when the text carries no sentinel.
|
|
13
|
+
*/
|
|
14
|
+
export declare function invalidSentinelReason(text: string | null | undefined, max?: number): string;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** The longest message a host will send. Mirrored by the service's own cap. */
|
|
2
|
+
export declare const PRODUCT_FEEDBACK_MAX_CHARS = 2000;
|
|
3
|
+
/** Below this there is nothing a person could act on ("ok", "hi"). */
|
|
4
|
+
export declare const PRODUCT_FEEDBACK_MIN_CHARS = 3;
|
|
5
|
+
/** Which host a message came from. The service files it under that host. */
|
|
6
|
+
export type ProductFeedbackHost = "PBI" | "EXCEL";
|
|
7
|
+
/**
|
|
8
|
+
* Clean a typed message for sending: control characters other than line breaks and tabs removed,
|
|
9
|
+
* trailing spaces on each line removed, runs of blank lines collapsed to one, trimmed, and capped.
|
|
10
|
+
* Pure, so every host sends the same bytes for the same keystrokes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function normaliseProductFeedbackText(raw: string | null | undefined, maxChars?: number): string;
|
|
13
|
+
/** True when a message is long enough to send. */
|
|
14
|
+
export declare function productFeedbackSendable(raw: string | null | undefined, maxChars?: number): boolean;
|
|
15
|
+
/** The credentials a host already holds, forwarded so the service can attach an account when there is one. The
|
|
16
|
+
* service resolves identity itself; nothing here names an account. Absent fields are sent empty. */
|
|
17
|
+
export interface ProductFeedbackIdentity {
|
|
18
|
+
licenseKey?: string;
|
|
19
|
+
licensee?: string;
|
|
20
|
+
secretKey?: string;
|
|
21
|
+
freemiumKey?: string;
|
|
22
|
+
linkNonce?: string;
|
|
23
|
+
instanceKey?: string;
|
|
24
|
+
clientId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ProductFeedbackPayload {
|
|
27
|
+
text: string;
|
|
28
|
+
host: ProductFeedbackHost;
|
|
29
|
+
surface: string;
|
|
30
|
+
clientVersion: string;
|
|
31
|
+
correlationId: string;
|
|
32
|
+
clientId: string;
|
|
33
|
+
licenseKey: string;
|
|
34
|
+
licensee: string;
|
|
35
|
+
secretKey: string;
|
|
36
|
+
freemiumKey: string;
|
|
37
|
+
linkNonce: string;
|
|
38
|
+
instanceKey: string;
|
|
39
|
+
}
|
|
40
|
+
/** The request body every host sends (before its own encoding and signing). */
|
|
41
|
+
export declare function buildProductFeedbackPayload(input: {
|
|
42
|
+
text: string;
|
|
43
|
+
host: ProductFeedbackHost;
|
|
44
|
+
surface?: string;
|
|
45
|
+
clientVersion: string;
|
|
46
|
+
correlationId: string;
|
|
47
|
+
identity?: ProductFeedbackIdentity;
|
|
48
|
+
}): ProductFeedbackPayload;
|
|
49
|
+
/** What a host's send callback reports. `message` is shown to the reader when present. */
|
|
50
|
+
export interface ProductFeedbackSendResult {
|
|
51
|
+
ok: boolean;
|
|
52
|
+
message?: string;
|
|
53
|
+
}
|
|
54
|
+
/** The words a reader sees. Hosts localize; every field has an English default. */
|
|
55
|
+
export interface ProductFeedbackText {
|
|
56
|
+
label?: string;
|
|
57
|
+
placeholder?: string;
|
|
58
|
+
hint?: string;
|
|
59
|
+
send?: string;
|
|
60
|
+
sending?: string;
|
|
61
|
+
sent?: string;
|
|
62
|
+
failed?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface ProductFeedbackBoxOptions {
|
|
65
|
+
/** Delivers the cleaned text. Resolve { ok: false } (or throw) on failure; the box keeps the text either way. */
|
|
66
|
+
send: (text: string) => Promise<ProductFeedbackSendResult>;
|
|
67
|
+
text?: ProductFeedbackText;
|
|
68
|
+
/** Added to the wrapper so the host can skin it; the structure stays the same. */
|
|
69
|
+
className?: string;
|
|
70
|
+
maxChars?: number;
|
|
71
|
+
/** Called once, when the box is mounted - the host's "shown" counter. */
|
|
72
|
+
onShown?: () => void;
|
|
73
|
+
/** Called after a successful send - the host's "sent" counter. */
|
|
74
|
+
onSent?: () => void;
|
|
75
|
+
/** Called after a failed send, with what failed, so the host can log it. */
|
|
76
|
+
onFailed?: (reason: string) => void;
|
|
77
|
+
}
|
|
78
|
+
export interface ProductFeedbackBox {
|
|
79
|
+
element: HTMLElement;
|
|
80
|
+
/** Removes the box and its listeners. */
|
|
81
|
+
destroy(): void;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build the box inside `container`. The wrapper carries `bic-product-feedback` (plus the host's
|
|
85
|
+
* class); the textarea, button and status line carry `bic-product-feedback-input`, `-send` and
|
|
86
|
+
* `-status`, so hosts and tests can find them without depending on the order of elements.
|
|
87
|
+
*/
|
|
88
|
+
export declare function mountProductFeedbackBox(container: HTMLElement, opts: ProductFeedbackBoxOptions): ProductFeedbackBox;
|
package/dist/types/react.d.ts
CHANGED
|
@@ -34,6 +34,13 @@ export interface BicChartProps {
|
|
|
34
34
|
labelContrast?: ChartHostConfig["labelContrast"];
|
|
35
35
|
/** What the label-contrast pass did after each render - counts, for a page that logs. */
|
|
36
36
|
onLabelContrast?: ChartHostConfig["onLabelContrast"];
|
|
37
|
+
/**
|
|
38
|
+
* THE CHART STOPPED BECAUSE THE DATA LACKS A COLUMN IT IS BUILT ON. Supplied: the chart's
|
|
39
|
+
* container is left empty and this is called with the chart's reason, instead of the throw
|
|
40
|
+
* reaching React - so a page can say what is missing where the chart would be. Absent: the
|
|
41
|
+
* throw propagates as before. See createChartHost's `onInvalidSentinel`.
|
|
42
|
+
*/
|
|
43
|
+
onInvalidSentinel?: ChartHostConfig["onInvalidSentinel"];
|
|
37
44
|
/** Identity within a <BicChartGroup> — the key other charts filter by. */
|
|
38
45
|
id?: string;
|
|
39
46
|
/** Take this group member's selection as a filter on THIS chart's rows. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.108",
|
|
4
4
|
"description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|