@bicharts/chart-host 0.5.104 → 0.5.106

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.
@@ -3226,6 +3226,7 @@ function createChartHost(container, config) {
3226
3226
  let current = null;
3227
3227
  let activeTickEl = null;
3228
3228
  let selectionIsPeriod = false;
3229
+ let selectionFromChart = false;
3229
3230
  const subs = /* @__PURE__ */ new Set();
3230
3231
  const ensureAffordanceStyles = () => {
3231
3232
  try {
@@ -3305,8 +3306,9 @@ function createChartHost(container, config) {
3305
3306
  } catch {
3306
3307
  }
3307
3308
  };
3308
- const notify = (rowIdxs, source, tick) => {
3309
+ const notify = (rowIdxs, source, tick, fromChart = false) => {
3309
3310
  current = rowIdxs;
3311
+ selectionFromChart = rowIdxs.length > 0 && fromChart;
3310
3312
  activeTickEl = rowIdxs.length ? tick ?? null : null;
3311
3313
  selectionIsPeriod = rowIdxs.length > 0 && periodTickSuppressesFeedback(!!tick, chartOwnsTimeline(container));
3312
3314
  paintSelection();
@@ -3323,7 +3325,7 @@ function createChartHost(container, config) {
3323
3325
  const d2 = e?.detail || {};
3324
3326
  xfAt = Date.now();
3325
3327
  if (d2.clear) notify([], d2.source || "chart");
3326
- else if (d2.mark) notify(parseRowIdxs(d2.mark.getAttribute?.(ROW_IDX_ATTR)), d2.source || "chart", d2.mark);
3328
+ else if (d2.mark) notify(parseRowIdxs(d2.mark.getAttribute?.(ROW_IDX_ATTR)), d2.source || "chart", d2.mark, true);
3327
3329
  };
3328
3330
  const resolver = createMarkResolver({
3329
3331
  root: container,
@@ -3340,7 +3342,7 @@ function createChartHost(container, config) {
3340
3342
  if (!el) {
3341
3343
  if (current && current.length) {
3342
3344
  const slot = container[CONTAINER_SLOT_XF_CLEAR];
3343
- if (typeof slot === "function") {
3345
+ if (selectionFromChart && typeof slot === "function") {
3344
3346
  try {
3345
3347
  slot();
3346
3348
  } catch {
package/dist/index.mjs CHANGED
@@ -128,7 +128,7 @@ import {
128
128
  u,
129
129
  unpinScrolledAxis,
130
130
  valuePlacementFlag
131
- } from "./chunk-VPCD6LVR.mjs";
131
+ } from "./chunk-HLNXXQA5.mjs";
132
132
  import "./chunk-A2GMXZP7.mjs";
133
133
  import "./chunk-GHODWOAL.mjs";
134
134
 
@@ -934,6 +934,14 @@ function cleanFormat(raw, dialect) {
934
934
  if (!s2.trim() || /^general$/i.test(s2.trim())) return null;
935
935
  return hasDateToken(s2, dialect) ? s2 : null;
936
936
  }
937
+ function isExcelDateFormat(raw) {
938
+ if (!raw) return false;
939
+ const bare = stripLiterals(firstSection(String(raw), "excel"), "excel");
940
+ if (/\[(h+|m+|s+)\]/i.test(bare)) return false;
941
+ const tokens = bare.replace(/\[[^\]]*\]/g, "").trim();
942
+ if (!tokens || /^general$/i.test(tokens)) return false;
943
+ return /[ymdhs]/i.test(tokens);
944
+ }
937
945
  function firstSection(s2, dialect) {
938
946
  let out = "";
939
947
  let quote = "";
@@ -971,6 +979,10 @@ function stripLiterals(s2, dialect) {
971
979
  i2++;
972
980
  continue;
973
981
  }
982
+ if (dialect === "excel" && (ch === "_" || ch === "*")) {
983
+ i2++;
984
+ continue;
985
+ }
974
986
  if (ch === '"' || dialect === "dotnet" && ch === "'") {
975
987
  const end = s2.indexOf(ch, i2 + 1);
976
988
  i2 = end < 0 ? s2.length : end;
@@ -2337,6 +2349,7 @@ export {
2337
2349
  inlineFilterGate,
2338
2350
  isBlankRender,
2339
2351
  isBlindMarker,
2352
+ isExcelDateFormat,
2340
2353
  isHorizontalLabelRow,
2341
2354
  isPhantomBox,
2342
2355
  isPillBackdropAlpha,
package/dist/react.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createChartHost,
5
5
  geoFromCache,
6
6
  loadGeo
7
- } from "./chunk-VPCD6LVR.mjs";
7
+ } from "./chunk-HLNXXQA5.mjs";
8
8
  import "./chunk-A2GMXZP7.mjs";
9
9
  import "./chunk-GHODWOAL.mjs";
10
10
 
@@ -16,7 +16,7 @@ export { qualifyGroupHeadingFor, newQualifyGroupState, type QualifyGroupRow, typ
16
16
  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
17
  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
18
  export { computeSelectionCard, normaliseAggregation, type SelectionCardModel, type SelectionCardLine, type SelectionCardOptions, } from "./selectionCard";
19
- export { formatSourceDate, formatSourceDateFor, type SourceFormats, type SourceFormatDialect, type SourceDateOptions, } from "./sourceDateFormat";
19
+ export { formatSourceDate, formatSourceDateFor, isExcelDateFormat, type SourceFormats, type SourceFormatDialect, type SourceDateOptions, } from "./sourceDateFormat";
20
20
  export { composeSummaryText } from "./summaryText";
21
21
  export { ensureCrossfilterHitTargets, type HitTargetReport } from "./hitTargets";
22
22
  export { applyLabelContrast, LABEL_CONTRAST_DONE_ATTR, LABEL_CONTRAST_CAP, type LabelContrastOptions, type LabelContrastReport, } from "./labelContrastDom";
@@ -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.104",
3
+ "version": "0.5.106",
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",