@bicharts/chart-host 0.5.105 → 0.5.107
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/index.mjs +153 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/productFeedback.d.ts +88 -0
- package/dist/types/sourceDateFormat.d.ts +19 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -649,6 +649,140 @@ function askApplyImprovements(container, reason, opts = {}) {
|
|
|
649
649
|
});
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
+
// src/productFeedback.ts
|
|
653
|
+
var PRODUCT_FEEDBACK_MAX_CHARS = 2e3;
|
|
654
|
+
var PRODUCT_FEEDBACK_MIN_CHARS = 3;
|
|
655
|
+
function normaliseProductFeedbackText(raw, maxChars = PRODUCT_FEEDBACK_MAX_CHARS) {
|
|
656
|
+
const s2 = String(raw ?? "").replace(/\r\n?/g, "\n").replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, "").split("\n").map((line) => line.replace(/[ \t]+$/, "")).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
657
|
+
return s2.length > maxChars ? s2.slice(0, maxChars).trimEnd() : s2;
|
|
658
|
+
}
|
|
659
|
+
function productFeedbackSendable(raw, maxChars = PRODUCT_FEEDBACK_MAX_CHARS) {
|
|
660
|
+
return normaliseProductFeedbackText(raw, maxChars).length >= PRODUCT_FEEDBACK_MIN_CHARS;
|
|
661
|
+
}
|
|
662
|
+
function buildProductFeedbackPayload(input) {
|
|
663
|
+
const id = input.identity ?? {};
|
|
664
|
+
return {
|
|
665
|
+
text: normaliseProductFeedbackText(input.text),
|
|
666
|
+
host: input.host,
|
|
667
|
+
surface: input.surface || "landing",
|
|
668
|
+
clientVersion: input.clientVersion || "",
|
|
669
|
+
correlationId: input.correlationId || "",
|
|
670
|
+
clientId: id.clientId || "",
|
|
671
|
+
licenseKey: id.licenseKey || "",
|
|
672
|
+
licensee: id.licensee || "",
|
|
673
|
+
secretKey: id.secretKey || "",
|
|
674
|
+
freemiumKey: id.freemiumKey || "",
|
|
675
|
+
linkNonce: id.linkNonce || "",
|
|
676
|
+
instanceKey: id.instanceKey || ""
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
var DEFAULT_TEXT2 = {
|
|
680
|
+
label: "Your suggestions",
|
|
681
|
+
placeholder: "An idea, a missing chart, or something that got in your way",
|
|
682
|
+
hint: "Sent to our team. It is never used to draw a chart.",
|
|
683
|
+
send: "Send",
|
|
684
|
+
sending: "Sending...",
|
|
685
|
+
sent: "Thank you - your suggestion was sent.",
|
|
686
|
+
failed: "Your suggestion could not be sent. It is still in the box - please try again."
|
|
687
|
+
};
|
|
688
|
+
function mountProductFeedbackBox(container, opts) {
|
|
689
|
+
const doc = container.ownerDocument ?? document;
|
|
690
|
+
const text = { ...DEFAULT_TEXT2, ...opts.text ?? {} };
|
|
691
|
+
const maxChars = Math.max(PRODUCT_FEEDBACK_MIN_CHARS, Math.floor(opts.maxChars ?? PRODUCT_FEEDBACK_MAX_CHARS));
|
|
692
|
+
const wrap = doc.createElement("div");
|
|
693
|
+
wrap.className = "bic-product-feedback" + (opts.className ? " " + opts.className : "");
|
|
694
|
+
const inputId = "bic-product-feedback-" + ++mounted;
|
|
695
|
+
const label = doc.createElement("label");
|
|
696
|
+
label.className = "bic-product-feedback-label";
|
|
697
|
+
label.htmlFor = inputId;
|
|
698
|
+
label.textContent = text.label;
|
|
699
|
+
const input = doc.createElement("textarea");
|
|
700
|
+
input.className = "bic-product-feedback-input";
|
|
701
|
+
input.id = inputId;
|
|
702
|
+
input.rows = 2;
|
|
703
|
+
input.maxLength = maxChars;
|
|
704
|
+
input.placeholder = text.placeholder;
|
|
705
|
+
input.setAttribute("aria-describedby", inputId + "-hint");
|
|
706
|
+
const hint = doc.createElement("div");
|
|
707
|
+
hint.className = "bic-product-feedback-hint";
|
|
708
|
+
hint.id = inputId + "-hint";
|
|
709
|
+
hint.textContent = text.hint;
|
|
710
|
+
const row = doc.createElement("div");
|
|
711
|
+
row.className = "bic-product-feedback-row";
|
|
712
|
+
const button = doc.createElement("button");
|
|
713
|
+
button.type = "button";
|
|
714
|
+
button.className = "bic-product-feedback-send";
|
|
715
|
+
button.textContent = text.send;
|
|
716
|
+
const status = doc.createElement("span");
|
|
717
|
+
status.className = "bic-product-feedback-status";
|
|
718
|
+
status.setAttribute("role", "status");
|
|
719
|
+
status.setAttribute("aria-live", "polite");
|
|
720
|
+
row.append(button, status);
|
|
721
|
+
wrap.append(label, input, hint, row);
|
|
722
|
+
container.appendChild(wrap);
|
|
723
|
+
let sending = false;
|
|
724
|
+
const sync = () => {
|
|
725
|
+
button.disabled = sending || !productFeedbackSendable(input.value, maxChars);
|
|
726
|
+
};
|
|
727
|
+
const onInput = () => {
|
|
728
|
+
if (!sending && status.textContent) {
|
|
729
|
+
status.textContent = "";
|
|
730
|
+
status.removeAttribute("data-state");
|
|
731
|
+
}
|
|
732
|
+
sync();
|
|
733
|
+
};
|
|
734
|
+
const onClick = async () => {
|
|
735
|
+
if (sending || !productFeedbackSendable(input.value, maxChars)) return;
|
|
736
|
+
const message = normaliseProductFeedbackText(input.value, maxChars);
|
|
737
|
+
sending = true;
|
|
738
|
+
sync();
|
|
739
|
+
button.textContent = text.sending;
|
|
740
|
+
status.textContent = "";
|
|
741
|
+
status.removeAttribute("data-state");
|
|
742
|
+
let result;
|
|
743
|
+
let failure = "";
|
|
744
|
+
try {
|
|
745
|
+
result = await opts.send(message);
|
|
746
|
+
if (!result?.ok) failure = result?.message || "not sent";
|
|
747
|
+
} catch (e2) {
|
|
748
|
+
result = { ok: false };
|
|
749
|
+
failure = String(e2?.message ?? e2);
|
|
750
|
+
}
|
|
751
|
+
sending = false;
|
|
752
|
+
button.textContent = text.send;
|
|
753
|
+
if (result?.ok) {
|
|
754
|
+
input.value = "";
|
|
755
|
+
status.textContent = result.message || text.sent;
|
|
756
|
+
status.setAttribute("data-state", "sent");
|
|
757
|
+
safely(() => opts.onSent?.());
|
|
758
|
+
} else {
|
|
759
|
+
status.textContent = result?.message || text.failed;
|
|
760
|
+
status.setAttribute("data-state", "failed");
|
|
761
|
+
safely(() => opts.onFailed?.(failure));
|
|
762
|
+
}
|
|
763
|
+
sync();
|
|
764
|
+
};
|
|
765
|
+
input.addEventListener("input", onInput);
|
|
766
|
+
button.addEventListener("click", onClick);
|
|
767
|
+
sync();
|
|
768
|
+
safely(() => opts.onShown?.());
|
|
769
|
+
return {
|
|
770
|
+
element: wrap,
|
|
771
|
+
destroy() {
|
|
772
|
+
input.removeEventListener("input", onInput);
|
|
773
|
+
button.removeEventListener("click", onClick);
|
|
774
|
+
wrap.remove();
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
var mounted = 0;
|
|
779
|
+
function safely(fn) {
|
|
780
|
+
try {
|
|
781
|
+
fn();
|
|
782
|
+
} catch {
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
652
786
|
// src/qualifyGroups.ts
|
|
653
787
|
function newQualifyGroupState() {
|
|
654
788
|
return { preview: false, previewClosed: false, projected: false, notRecommended: false, rankedSeen: false };
|
|
@@ -934,6 +1068,14 @@ function cleanFormat(raw, dialect) {
|
|
|
934
1068
|
if (!s2.trim() || /^general$/i.test(s2.trim())) return null;
|
|
935
1069
|
return hasDateToken(s2, dialect) ? s2 : null;
|
|
936
1070
|
}
|
|
1071
|
+
function isExcelDateFormat(raw) {
|
|
1072
|
+
if (!raw) return false;
|
|
1073
|
+
const bare = stripLiterals(firstSection(String(raw), "excel"), "excel");
|
|
1074
|
+
if (/\[(h+|m+|s+)\]/i.test(bare)) return false;
|
|
1075
|
+
const tokens = bare.replace(/\[[^\]]*\]/g, "").trim();
|
|
1076
|
+
if (!tokens || /^general$/i.test(tokens)) return false;
|
|
1077
|
+
return /[ymdhs]/i.test(tokens);
|
|
1078
|
+
}
|
|
937
1079
|
function firstSection(s2, dialect) {
|
|
938
1080
|
let out = "";
|
|
939
1081
|
let quote = "";
|
|
@@ -971,6 +1113,10 @@ function stripLiterals(s2, dialect) {
|
|
|
971
1113
|
i2++;
|
|
972
1114
|
continue;
|
|
973
1115
|
}
|
|
1116
|
+
if (dialect === "excel" && (ch === "_" || ch === "*")) {
|
|
1117
|
+
i2++;
|
|
1118
|
+
continue;
|
|
1119
|
+
}
|
|
974
1120
|
if (ch === '"' || dialect === "dotnet" && ch === "'") {
|
|
975
1121
|
const end = s2.indexOf(ch, i2 + 1);
|
|
976
1122
|
i2 = end < 0 ? s2.length : end;
|
|
@@ -2270,6 +2416,8 @@ export {
|
|
|
2270
2416
|
PILL_MIN_ALPHA,
|
|
2271
2417
|
PILL_MIN_COVERAGE,
|
|
2272
2418
|
PILL_OPAQUE_ALPHA,
|
|
2419
|
+
PRODUCT_FEEDBACK_MAX_CHARS,
|
|
2420
|
+
PRODUCT_FEEDBACK_MIN_CHARS,
|
|
2273
2421
|
QUALIFY_REFUSAL_UNSPECIFIED,
|
|
2274
2422
|
ROW_IDX_ATTR,
|
|
2275
2423
|
SAME_SHADE_DELTA_E,
|
|
@@ -2291,6 +2439,7 @@ export {
|
|
|
2291
2439
|
blankRenderFlag,
|
|
2292
2440
|
buildPalette,
|
|
2293
2441
|
buildPaletteFromSeed,
|
|
2442
|
+
buildProductFeedbackPayload,
|
|
2294
2443
|
buildRenderPayload,
|
|
2295
2444
|
buildReviewWire,
|
|
2296
2445
|
canConfirmLaunch,
|
|
@@ -2337,6 +2486,7 @@ export {
|
|
|
2337
2486
|
inlineFilterGate,
|
|
2338
2487
|
isBlankRender,
|
|
2339
2488
|
isBlindMarker,
|
|
2489
|
+
isExcelDateFormat,
|
|
2340
2490
|
isHorizontalLabelRow,
|
|
2341
2491
|
isPhantomBox,
|
|
2342
2492
|
isPillBackdropAlpha,
|
|
@@ -2349,11 +2499,13 @@ export {
|
|
|
2349
2499
|
loadGeo,
|
|
2350
2500
|
markerArmedBlind,
|
|
2351
2501
|
measureContainerBoxes,
|
|
2502
|
+
mountProductFeedbackBox,
|
|
2352
2503
|
needsScroll,
|
|
2353
2504
|
newQualifyGroupState,
|
|
2354
2505
|
newQualifyRefusalGroupState,
|
|
2355
2506
|
noopViewStateProvider,
|
|
2356
2507
|
normaliseAggregation,
|
|
2508
|
+
normaliseProductFeedbackText,
|
|
2357
2509
|
normalizeFilterTerm,
|
|
2358
2510
|
orderMostDistinct,
|
|
2359
2511
|
orderRefusalsForDisplay,
|
|
@@ -2368,6 +2520,7 @@ export {
|
|
|
2368
2520
|
planFrameGrow,
|
|
2369
2521
|
planTrivialChart,
|
|
2370
2522
|
pollGiveUpKeepsMarker,
|
|
2523
|
+
productFeedbackSendable,
|
|
2371
2524
|
qualifyAuto,
|
|
2372
2525
|
qualifyCancel,
|
|
2373
2526
|
qualifyFailureFallsOpen,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -12,11 +12,12 @@ 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";
|
|
18
19
|
export { computeSelectionCard, normaliseAggregation, type SelectionCardModel, type SelectionCardLine, type SelectionCardOptions, } from "./selectionCard";
|
|
19
|
-
export { formatSourceDate, formatSourceDateFor, type SourceFormats, type SourceFormatDialect, type SourceDateOptions, } from "./sourceDateFormat";
|
|
20
|
+
export { formatSourceDate, formatSourceDateFor, isExcelDateFormat, type SourceFormats, type SourceFormatDialect, type SourceDateOptions, } from "./sourceDateFormat";
|
|
20
21
|
export { composeSummaryText } from "./summaryText";
|
|
21
22
|
export { ensureCrossfilterHitTargets, type HitTargetReport } from "./hitTargets";
|
|
22
23
|
export { applyLabelContrast, LABEL_CONTRAST_DONE_ATTR, LABEL_CONTRAST_CAP, type LabelContrastOptions, type LabelContrastReport, } from "./labelContrastDom";
|
|
@@ -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;
|
|
@@ -28,3 +28,22 @@ export interface SourceDateOptions {
|
|
|
28
28
|
export declare function formatSourceDate(raw: any, opts?: SourceDateOptions): string | null;
|
|
29
29
|
/** Convenience for a caller holding a `SourceFormats` map and a column name. */
|
|
30
30
|
export declare function formatSourceDateFor(raw: any, columnName: string, formats: SourceFormats | null | undefined, culture?: string): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Does an EXCEL number format make the cell a date? The question a host asks before it turns a
|
|
33
|
+
* serial number into a Date (2026-09-16).
|
|
34
|
+
*
|
|
35
|
+
* Excel stores 2026-03-01 as 46082 and only the format says which one it is, so reading a format
|
|
36
|
+
* wrongly in EITHER direction corrupts a column without an error anywhere. A bare letter test over
|
|
37
|
+
* the raw string gets it wrong in the direction that hurts: `0.00;[Red]0.00` - Excel's own built-in
|
|
38
|
+
* "Number, red negatives" - has a `d` in its colour, `[$USD] #,##0.00` an `s` in its currency tag,
|
|
39
|
+
* and a revenue of 1,234.50 read through either became a date in May 1903.
|
|
40
|
+
*
|
|
41
|
+
* So the format is reduced the way `cleanFormat` reduces it before rendering: the FIRST section (the
|
|
42
|
+
* one a positive serial takes), literals removed, bracket decorations removed. Only then does a
|
|
43
|
+
* remaining `y m d h s` make it a date.
|
|
44
|
+
*
|
|
45
|
+
* ELAPSED TIME IS A DURATION, NOT A DATE. `[h]:mm:ss` counts hours past 24: its value is a length of
|
|
46
|
+
* time, and turning it into an instant in January 1900 is the same trap as `0.00" days"`. A section
|
|
47
|
+
* carrying an elapsed bracket answers false, and the column stays a number.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isExcelDateFormat(raw: string | null | undefined): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.107",
|
|
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",
|