@metron-labs/quote-react 0.1.36 → 0.1.40

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.
@@ -157,9 +157,15 @@ function QuickQuoteInner({ fullPage = false, hideHeader = false, internal = fals
157
157
  const original = event.state;
158
158
  const href = window.location.href;
159
159
  setTimeout(() => {
160
- if (original?.turbo || window.location.href !== href)
160
+ if (window.location.href !== href)
161
161
  return;
162
- if (window.history.state?.turbo)
162
+ // Our own steps always get our state back, even if a stamp slipped through earlier -
163
+ // otherwise it sticks and every later visit to that step is a Turbo page visit.
164
+ if (hash === "#quote-request" || hash === "#matched-products") {
165
+ window.history.replaceState({ boqQuoteStage: hash === "#quote-request" ? "basket" : "results" }, "", href);
166
+ return;
167
+ }
168
+ if (!original?.turbo && window.history.state?.turbo)
163
169
  window.history.replaceState(original, "", href);
164
170
  });
165
171
  };
@@ -249,11 +255,10 @@ function QuickQuoteInner({ fullPage = false, hideHeader = false, internal = fals
249
255
  // wrap the pasted text as a .txt — verbatim, so the copy archived in blob storage reads
250
256
  // exactly as pasted — and feed it straight into the same match pipeline.
251
257
  const handlePasteSchedule = useCallback(async (text, providedLines, archiveSource = true) => {
252
- const trimmed = text.trim();
253
- if (!trimmed)
258
+ if (!text.trim())
254
259
  return;
255
260
  setEntryMode("schedule");
256
- const file = new File([trimmed], "pasted-schedule.txt", { type: "text/plain" });
261
+ const file = new File([text], "pasted-schedule.txt", { type: "text/plain" });
257
262
  await runScheduleMatch(file, providedLines, archiveSource);
258
263
  }, [runScheduleMatch]);
259
264
  // Entry-page "upload file" tab: same fast path as handlePasteSchedule, but
@@ -4,7 +4,7 @@ import BackArrow from "../../components/BackArrow";
4
4
  import RefreshIcon from "../../components/RefreshIcon";
5
5
  import ForwardArrow from "../../components/ForwardArrow";
6
6
  import CloseIcon from "../../components/CloseIcon";
7
- import { apiUrl } from "../../lib/config";
7
+ import { apiUrl, getQuoteConfig } from "../../lib/config";
8
8
  import { useTrack } from "../../lib/analytics";
9
9
  import { renderDisplayUnit, formatPriceBasis } from "../components/UnitDisplay";
10
10
  import { fmtCurrency, fmtQty } from "../../lib/formatters";
@@ -297,7 +297,7 @@ function DetailedDecision({ item, decision, result, showRetrievalDebug, reviewOn
297
297
  function CandidateBreakdown({ item, candidates, result, decision, unmatchable, selectedProductId, detailMode, onPick, onClear, showAll = false, internal = false, debugEnabled = false, forceReviewNote = false, linkedGroupMeta, }) {
298
298
  // Business-relevant reasoning (why review is needed, missing info, requested
299
299
  // spec) is useful to merchant staff. Raw match scores/retrieval debug are
300
- // Metron Labs' own tooling — only surfaced under the real ?debug=1 detail mode.
300
+ // Metron Labs' own tooling — only surfaced under the `debug` config's detail mode.
301
301
  const showBusinessDetail = internal || detailMode === "detailed";
302
302
  const showScoreColumns = debugEnabled && detailMode === "detailed";
303
303
  const detailBlock = showBusinessDetail || forceReviewNote ? (_jsx(DetailedDecision, { item: item, decision: decision, result: result, showRetrievalDebug: showScoreColumns, reviewOnly: forceReviewNote && !showBusinessDetail, linkedGroupMeta: linkedGroupMeta })) : null;
@@ -334,13 +334,8 @@ export default function ScheduleResultsStage({ scheduleResult, onStartOver, cart
334
334
  const [sortConfig, setSortConfig] = useState(null);
335
335
  const [page, setPage] = useState(1);
336
336
  // Raw ML/pipeline debug (scores, retrieval queries, timings) is Metron Labs'
337
- // own engineering tooling — gated on ?debug=1 only, never on `internal`.
338
- // Read after mount rather than during render: the host page may server-render the
339
- // widget, and reading the URL during render would differ between server and client.
340
- const [debugEnabled, setDebugEnabled] = useState(false);
341
- useEffect(() => {
342
- setDebugEnabled(new URLSearchParams(window.location.search).get("debug") === "1");
343
- }, []);
337
+ // own engineering tooling — gated on the host's `debug` config only, never on `internal`.
338
+ const debugEnabled = getQuoteConfig().debug === true;
344
339
  const [detailMode, setDetailMode] = useState("simple");
345
340
  const [viewMode, setViewMode] = useState(internal ? "list" : "tile");
346
341
  const [showTimings, setShowTimings] = useState(false);