@campfire-interactive/volume-intelligence-ui 0.9.0 → 0.10.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/dist/index.d.ts CHANGED
@@ -272,7 +272,18 @@ interface DetectSegmentsResult {
272
272
  interface ClearSourceDataResult {
273
273
  uploads: number;
274
274
  criteria: number;
275
- cleared: true;
275
+ /** Whether the source is now EMPTY. False when the call hit its time budget
276
+ * with rows still to delete — call again to continue.
277
+ *
278
+ * BREAKING in 2026-09: this was the literal `true`, returned regardless of
279
+ * whether anything remained. Batched clearing introduced a third outcome
280
+ * (partial), and a consumer branching on `cleared` would have read it as an
281
+ * empty source. */
282
+ cleared: boolean;
283
+ /** False when the call hit its time budget with rows still to delete. */
284
+ done?: boolean;
285
+ /** Criteria still to delete when `done` is false. */
286
+ remainingCriteria?: number;
276
287
  }
277
288
  /** Whether a source satisfies every required identity field. The dual-
278
289
  * satisfaction rule (explicit automotive_field mapping OR the covering
package/dist/index.js CHANGED
@@ -1769,8 +1769,31 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, readOnl
1769
1769
  setError(null);
1770
1770
  setClearResult(null);
1771
1771
  try {
1772
- const result = await transport.clearSourceData(id, clearConfirm);
1773
- setClearResult(`Cleared ${result.criteria.toLocaleString()} criteria and ${result.uploads.toLocaleString()} uploads. Configuration (segments, mappings) preserved.`);
1772
+ let criteria = 0;
1773
+ let uploads = 0;
1774
+ let passes = 0;
1775
+ const MAX_PASSES = 200;
1776
+ for (; ; ) {
1777
+ const result = await transport.clearSourceData(id, clearConfirm);
1778
+ criteria += result.criteria;
1779
+ uploads += result.uploads;
1780
+ passes += 1;
1781
+ if (result.done !== false || passes >= MAX_PASSES) {
1782
+ if (result.done === false) {
1783
+ setClearResult(
1784
+ `Stopped after ${passes} passes with ${(result.remainingCriteria ?? 0).toLocaleString()} criteria still to delete. ${criteria.toLocaleString()} criteria and ${uploads.toLocaleString()} uploads were removed. Run Clear again to continue.`
1785
+ );
1786
+ } else {
1787
+ setClearResult(
1788
+ `Cleared ${criteria.toLocaleString()} criteria and ${uploads.toLocaleString()} uploads${passes > 1 ? ` over ${passes} passes` : ""}. Configuration (segments, mappings) preserved.`
1789
+ );
1790
+ }
1791
+ break;
1792
+ }
1793
+ setClearResult(
1794
+ `Clearing\u2026 ${criteria.toLocaleString()} criteria removed so far, ${(result.remainingCriteria ?? 0).toLocaleString()} to go.`
1795
+ );
1796
+ }
1774
1797
  setClearConfirm("");
1775
1798
  await load();
1776
1799
  } catch (e) {
@@ -1822,14 +1845,14 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, readOnl
1822
1845
  setSavingLayout(false);
1823
1846
  }
1824
1847
  }
1825
- if (loading) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", children: "Loading\u2026" }) });
1826
- if (!source) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-error", children: "Source not found" }) });
1827
- const keySegment = source.segments.find((s) => s.id === source.uniqueKeySegmentId);
1828
- const isOverlay = source.kind === "overlay";
1829
1848
  const aliasTargets = useMemo6(
1830
1849
  () => mappingRows.filter((m) => m.targetCategory === "hierarchy_level" || m.targetCategory === "automotive_field" || m.targetCategory === "dimension").map((m) => ({ targetCategory: m.targetCategory, targetKey: m.targetKey, label: `${m.segmentLabel} \xB7 ${m.targetKey}` })),
1831
1850
  [mappingRows]
1832
1851
  );
1852
+ if (loading) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", children: "Loading\u2026" }) });
1853
+ if (!source) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-error", children: "Source not found" }) });
1854
+ const keySegment = source.segments.find((s) => s.id === source.uniqueKeySegmentId);
1855
+ const isOverlay = source.kind === "overlay";
1833
1856
  const TABS = [
1834
1857
  { id: "structure", label: "Structure", Icon: SlidersHorizontal },
1835
1858
  { id: "mapping", label: "Mapping", Icon: Layers },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/volume-intelligence-ui",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Shared Volume Intelligence UI components (volume import) for the Campfire Suite — embedded by the VI webapp and by consuming apps (OMSF) so there is one import surface, not two that drift.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",