@elaraai/e3-ui-components 1.0.18 → 1.0.20

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.cjs CHANGED
@@ -30,6 +30,7 @@ const React = require("react");
30
30
  const react = require("@chakra-ui/react");
31
31
  const eastUiComponents = require("@elaraai/east-ui-components");
32
32
  const reactDom = require("react-dom");
33
+ require("@elaraai/e3-ui");
33
34
  const internal$2 = require("@elaraai/east-ui/internal");
34
35
  const reactQuery = require("@tanstack/react-query");
35
36
  const reactVirtual = require("@tanstack/react-virtual");
@@ -8344,7 +8345,7 @@ function parseManualDraft(leafType, draft) {
8344
8345
  }
8345
8346
  }
8346
8347
  const diffValueEqual = east.equalFor(internal.Diff.Component.schema);
8347
- function getOpt$2(opt) {
8348
+ function getOpt$1(opt) {
8348
8349
  return opt.type === "some" ? opt.value : void 0;
8349
8350
  }
8350
8351
  const DENSITY_METRICS = {
@@ -8988,9 +8989,9 @@ const EastChakraDiff = React.memo(function EastChakraDiff2({ value }) {
8988
8989
  () => value.bindings ?? [],
8989
8990
  [value.bindings]
8990
8991
  );
8991
- const interactive = !(getOpt$2(value.readonly) ?? false);
8992
- const onCommittedFn = getOpt$2(value.onCommitted);
8993
- const onDiscardedFn = getOpt$2(value.onDiscarded);
8992
+ const interactive = !(getOpt$1(value.readonly) ?? false);
8993
+ const onCommittedFn = getOpt$1(value.onCommitted);
8994
+ const onDiscardedFn = getOpt$1(value.onDiscarded);
8994
8995
  const density = resolveDensity(value.density);
8995
8996
  const metrics = DENSITY_METRICS[density];
8996
8997
  const eyebrow = react.useSlotRecipe({ key: "eyebrowRow" });
@@ -56736,7 +56737,7 @@ function freshNodeId() {
56736
56737
  }
56737
56738
  const NODE_TYPES = { ontology: OntologyNode };
56738
56739
  const EDGE_TYPES = { ontology: OntologyEdge };
56739
- function getOpt$1(opt) {
56740
+ function getOpt(opt) {
56740
56741
  return opt.type === "some" ? opt.value : void 0;
56741
56742
  }
56742
56743
  function nextLinkId(existing) {
@@ -57051,10 +57052,10 @@ const EastChakraOntology = React.memo(function EastChakraOntology2({ value }) {
57051
57052
  var _a2;
57052
57053
  const binding = value.binding;
57053
57054
  const { ontology, pending, mutate } = useBindingOntology(binding);
57054
- const readonly = getOpt$1(value.readonly) ?? false;
57055
- const hideMiniMap = getOpt$1(value.hideMiniMap) ?? false;
57056
- const hideSearch = getOpt$1(value.hideSearch) ?? false;
57057
- const defaultView2 = ((_a2 = getOpt$1(value.defaultView)) == null ? void 0 : _a2.type) ?? "graph";
57055
+ const readonly = getOpt(value.readonly) ?? false;
57056
+ const hideMiniMap = getOpt(value.hideMiniMap) ?? false;
57057
+ const hideSearch = getOpt(value.hideSearch) ?? false;
57058
+ const defaultView2 = ((_a2 = getOpt(value.defaultView)) == null ? void 0 : _a2.type) ?? "graph";
57058
57059
  const [view, setView] = React.useState(defaultView2);
57059
57060
  const [tableSelectedId, setTableSelectedId] = React.useState(null);
57060
57061
  const handlers = React.useMemo(() => {
@@ -57267,12 +57268,13 @@ function useBindingValue(binding) {
57267
57268
  if (!types) return null;
57268
57269
  return defaultBindRuntime.buildBindHandle(types.sourceType, sourcePath, patchPath, mode);
57269
57270
  }, [binding, workspace, sourcePath, patchPath, mode]);
57270
- const { value, pending } = React.useMemo(() => {
57271
- if (!handle || !handle.has()) return { value: null, pending: false };
57271
+ const { value, pending, error: error3 } = React.useMemo(() => {
57272
+ if (!handle || !handle.has()) return { value: null, pending: false, error: void 0 };
57272
57273
  try {
57273
- return { value: handle.read(), pending: handle.pending() };
57274
- } catch {
57275
- return { value: null, pending: false };
57274
+ return { value: handle.read(), pending: handle.pending(), error: void 0 };
57275
+ } catch (e3) {
57276
+ console.error(`[Experiment] failed to read binding "${String(sourcePath)}":`, e3);
57277
+ return { value: null, pending: false, error: e3 };
57276
57278
  }
57277
57279
  }, [handle, version2]);
57278
57280
  const mutate = React.useCallback((next2) => {
@@ -57285,7 +57287,7 @@ function useBindingValue(binding) {
57285
57287
  const discard = React.useCallback(() => {
57286
57288
  handle == null ? void 0 : handle.discard();
57287
57289
  }, [handle]);
57288
- return { value, mode, pending, mutate, commit, discard };
57290
+ return { value, mode, pending, error: error3, mutate, commit, discard };
57289
57291
  }
57290
57292
  const IDLE = { call: () => {
57291
57293
  }, result: null, status: "idle", pending: false, error: null };
@@ -60130,7 +60132,6 @@ function OverlapHistogram({ treated, control, domain = [0, 1], supportLabel, pos
60130
60132
  }
60131
60133
  const arr = (v3) => v3 ? Array.from(v3, Number) : [];
60132
60134
  const arrI = (v3) => v3 ? Array.from(v3, Number) : [];
60133
- const getOpt = (o2) => o2 && o2.type === "some" ? o2.value : void 0;
60134
60135
  const fmt$1 = (x2) => {
60135
60136
  const r2 = Number.isInteger(x2) ? String(x2) : x2.toFixed(1);
60136
60137
  return r2 === "-0.0" ? "0.0" : r2;
@@ -60148,7 +60149,7 @@ function band(absStd) {
60148
60149
  const colMeta = (meta3, col) => meta3 == null ? void 0 : meta3.get(col);
60149
60150
  const unitOf = (meta3, col) => {
60150
60151
  var _a2;
60151
- return getOpt((_a2 = colMeta(meta3, col)) == null ? void 0 : _a2.unit) ?? "";
60152
+ return eastUiComponents.getSomeorUndefined((_a2 = colMeta(meta3, col)) == null ? void 0 : _a2.unit) ?? "";
60152
60153
  };
60153
60154
  const kindOf = (cols, name) => {
60154
60155
  var _a2;
@@ -60204,9 +60205,9 @@ function deriveSpec(config2, cols, result, meta3, dataLen) {
60204
60205
  const inPlay = /* @__PURE__ */ new Set([config2.treatment, config2.outcome, ...config2.common_causes]);
60205
60206
  const suggest = cols.find((c2) => !inPlay.has(c2.name));
60206
60207
  const suggestion = suggest ? `add ${suggest.name}` : "";
60207
- const methodV = getOpt(config2.method);
60208
+ const methodV = eastUiComponents.getSomeorUndefined(config2.method);
60208
60209
  const method = (methodV == null ? void 0 : methodV.type) === "propensity_score_weighting" ? "reweighting" : "regression";
60209
- const targetV = getOpt(config2.estimand);
60210
+ const targetV = eastUiComponents.getSomeorUndefined(config2.estimand);
60210
60211
  const target = targetV && (targetV.type === "att" || targetV.type === "atc") ? "treated" : "all";
60211
60212
  return {
60212
60213
  treatment: config2.treatment,
@@ -60226,9 +60227,9 @@ function balanceDisplay(b2, categorical) {
60226
60227
  return isProp ? `${Math.round(b2.treated_mean * 100)}% vs ${Math.round(b2.control_mean * 100)}%` : `${b2.treated_mean.toFixed(1)} vs ${b2.control_mean.toFixed(1)}`;
60227
60228
  }
60228
60229
  function deriveAnswer(config2, result, adj, meta3) {
60229
- const ci = getOpt(adj.ci);
60230
- const nci = getOpt(result.naive_ci);
60231
- const categorical = new Set(getOpt(config2.categorical) ?? []);
60230
+ const ci = eastUiComponents.getSomeorUndefined(adj.ci);
60231
+ const nci = eastUiComponents.getSomeorUndefined(result.naive_ci);
60232
+ const categorical = new Set(eastUiComponents.getSomeorUndefined(config2.categorical) ?? []);
60232
60233
  const balance = [...result.balance].sort((a2, b2) => Math.abs(b2.std_diff) - Math.abs(a2.std_diff)).map((b2) => ({
60233
60234
  col: b2.column,
60234
60235
  treated: b2.treated_mean,
@@ -60326,43 +60327,43 @@ function zeroCrossing(xs, ys) {
60326
60327
  function deriveRefute(r2, adj) {
60327
60328
  const checks = [];
60328
60329
  const est = (adj == null ? void 0 : adj.effect) ?? 0;
60329
- const placeboEffect = getOpt(r2.placebo_effect);
60330
- const placeboPasses = getOpt(r2.placebo_passes);
60330
+ const placeboEffect = eastUiComponents.getSomeorUndefined(r2.placebo_effect);
60331
+ const placeboPasses = eastUiComponents.getSomeorUndefined(r2.placebo_passes);
60331
60332
  if (placeboEffect !== void 0 || placeboPasses !== void 0) {
60332
60333
  checks.push({
60333
60334
  name: "Shuffle test",
60334
60335
  desc: "Shuffle which rows were treated; a real effect should collapse to zero.",
60335
60336
  value: placeboEffect !== void 0 ? `→ ${signed(placeboEffect)}` : placeboPasses ? "passed" : "failed",
60336
60337
  passed: placeboPasses ?? (placeboEffect !== void 0 && Math.abs(placeboEffect) < Math.max(0.5, Math.abs(est) * 0.15)),
60337
- tip: { type: "some", value: "Randomly re-label which rows were treated. A genuine effect should vanish." },
60338
+ tip: east.some("Randomly re-label which rows were treated. A genuine effect should vanish."),
60338
60339
  help: "check_shuffle"
60339
60340
  });
60340
60341
  }
60341
- const ds = getOpt(r2.data_subset_effect);
60342
+ const ds = eastUiComponents.getSomeorUndefined(r2.data_subset_effect);
60342
60343
  if (ds !== void 0) {
60343
- const dstd = getOpt(r2.data_subset_std) ?? 0;
60344
+ const dstd = eastUiComponents.getSomeorUndefined(r2.data_subset_std) ?? 0;
60344
60345
  checks.push({
60345
60346
  name: "Drop-some test",
60346
60347
  desc: "Re-estimate on random subsamples; a trustworthy effect stays put.",
60347
60348
  value: `${fmt$1(ds)} ± ${fmt$1(dstd)}`,
60348
60349
  passed: Math.abs(ds - est) < Math.max(0.5, Math.abs(est) * 0.2),
60349
- tip: { type: "none", value: null },
60350
+ tip: east.none,
60350
60351
  help: "check_dropsome"
60351
60352
  });
60352
60353
  }
60353
- const rcc = getOpt(r2.random_cc_within_ci);
60354
+ const rcc = eastUiComponents.getSomeorUndefined(r2.random_cc_within_ci);
60354
60355
  if (rcc !== void 0) {
60355
60356
  checks.push({
60356
60357
  name: "Decoy cause",
60357
60358
  desc: "Add an irrelevant random factor; the answer should not move.",
60358
60359
  value: rcc ? "within range" : "moved",
60359
60360
  passed: rcc,
60360
- tip: { type: "none", value: null },
60361
+ tip: east.none,
60361
60362
  help: "check_decoy"
60362
60363
  });
60363
60364
  }
60364
- const sens = getOpt(r2.sensitivity);
60365
- const evalue = getOpt(r2.robustness_value);
60365
+ const sens = eastUiComponents.getSomeorUndefined(r2.sensitivity);
60366
+ const evalue = eastUiComponents.getSomeorUndefined(r2.robustness_value);
60366
60367
  if (sens !== void 0 || evalue !== void 0) {
60367
60368
  const strengths = sens ? arr(sens.strengths) : [];
60368
60369
  const effects = sens ? arr(sens.effects) : [];
@@ -60373,7 +60374,7 @@ function deriveRefute(r2, adj) {
60373
60374
  desc: "How strong an unrecorded common cause would need to be to overturn the result.",
60374
60375
  value,
60375
60376
  passed: tip === null,
60376
- tip: { type: "some", value: "Something unrecorded could drive both the treatment choice and the outcome." },
60377
+ tip: east.some("Something unrecorded could drive both the treatment choice and the outcome."),
60377
60378
  help: "check_hidden"
60378
60379
  });
60379
60380
  }
@@ -60381,7 +60382,7 @@ function deriveRefute(r2, adj) {
60381
60382
  if (sens !== void 0) {
60382
60383
  const mid = arr(sens.effects);
60383
60384
  if (mid.length) {
60384
- const ci = getOpt(adj == null ? void 0 : adj.ci);
60385
+ const ci = eastUiComponents.getSomeorUndefined(adj == null ? void 0 : adj.ci);
60385
60386
  const half = ci ? Math.abs(ci.upper - ci.lower) / 2 : 0;
60386
60387
  const lo2 = mid.map((m2) => m2 - half);
60387
60388
  const hi = mid.map((m2) => m2 + half);
@@ -60394,8 +60395,8 @@ function deriveRefute(r2, adj) {
60394
60395
  function deriveDose(dose, config2, meta3) {
60395
60396
  const grid = arr(dose.grid);
60396
60397
  const mid = arr(dose.effect);
60397
- const lo2 = getOpt(dose.lower) ? arr(getOpt(dose.lower)) : mid.slice();
60398
- const hi = getOpt(dose.upper) ? arr(getOpt(dose.upper)) : mid.slice();
60398
+ const lo2 = eastUiComponents.getSomeorUndefined(dose.lower) ? arr(eastUiComponents.getSomeorUndefined(dose.lower)) : mid.slice();
60399
+ const hi = eastUiComponents.getSomeorUndefined(dose.upper) ? arr(eastUiComponents.getSomeorUndefined(dose.upper)) : mid.slice();
60399
60400
  const sizes = arrI(dose.size);
60400
60401
  const featureUnit = unitOf(meta3, dose.feature);
60401
60402
  const here = sizes.length ? sizes.indexOf(Math.max(...sizes)) : 0;
@@ -60455,7 +60456,7 @@ const VERDICT_WORD = {
60455
60456
  not_estimable: "n/a"
60456
60457
  };
60457
60458
  function deriveJournalRow(row, now2) {
60458
- const adj = getOpt(row.adjusted);
60459
+ const adj = eastUiComponents.getSomeorUndefined(row.adjusted);
60459
60460
  return {
60460
60461
  treatment: row.config.treatment,
60461
60462
  outcome: row.config.outcome,
@@ -60464,13 +60465,16 @@ function deriveJournalRow(row, now2) {
60464
60465
  verdict: VERDICT_WORD[row.verdict.type],
60465
60466
  verdictTone: VERDICT_TONE[row.verdict.type],
60466
60467
  who: row.committed_by,
60467
- when: relTime(row.committed_at, now2)
60468
+ when: relTime(row.committed_at, now2),
60469
+ // The originating preset id (resolved to a label by the surface); `none` for a
60470
+ // free-form / pre-presets row.
60471
+ preset: row.preset
60468
60472
  };
60469
60473
  }
60470
60474
  function deriveView(config2, ranConfig, cols, result, journal, meta3, dataLen, now2) {
60471
- const adj = result ? getOpt(result.adjusted) : void 0;
60472
- const refutation = result ? getOpt(result.refutation) : void 0;
60473
- const doseR = result ? getOpt(result.dose_response) : void 0;
60475
+ const adj = result ? eastUiComponents.getSomeorUndefined(result.adjusted) : void 0;
60476
+ const refutation = result ? eastUiComponents.getSomeorUndefined(result.refutation) : void 0;
60477
+ const doseR = result ? eastUiComponents.getSomeorUndefined(result.dose_response) : void 0;
60474
60478
  return {
60475
60479
  // The set-up rail reflects the LIVE config (the editor); the result deck
60476
60480
  // reflects RANCONFIG — the config that produced `result` — so the result
@@ -60517,7 +60521,7 @@ function deriveDesign(d2, result, ranConfig, meta3) {
60517
60521
  const b2 = balByCol.get(col);
60518
60522
  const absStd = b2 ? Math.abs(b2.std_diff) : 0;
60519
60523
  const { tone } = band(absStd);
60520
- return { col, frac: clamp01(absStd), tone, display: getOpt((_a2 = colMeta(meta3, col)) == null ? void 0 : _a2.label) ?? col };
60524
+ return { col, frac: clamp01(absStd), tone, display: eastUiComponents.getSomeorUndefined((_a2 = colMeta(meta3, col)) == null ? void 0 : _a2.label) ?? col };
60521
60525
  });
60522
60526
  const ns = arrI(d2.power_curve.n);
60523
60527
  const powers = arr(d2.power_curve.power);
@@ -60536,7 +60540,7 @@ function deriveDesign(d2, result, ranConfig, meta3) {
60536
60540
  const xTicks = len ? [String(ns[0]), String(ns[Math.floor((len - 1) / 2)]), String(ns[len - 1])] : [];
60537
60541
  const marks = [];
60538
60542
  if (len) marks.push({ at: nearest(primary.nTotal), label: `target ${(d2.target_power * 100).toFixed(0)}%`, tone: "pos", help: "validate_power" });
60539
- const cp = getOpt(d2.current_power);
60543
+ const cp = eastUiComponents.getSomeorUndefined(d2.current_power);
60540
60544
  if (cp !== void 0 && len) {
60541
60545
  const curN = result ? Number(result.n_total) : 0;
60542
60546
  if (curN > 0) {
@@ -60738,8 +60742,20 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60738
60742
  const configBind = useBindingValue(v3.config);
60739
60743
  const journalBind = useBindingValue(v3.journal.type === "some" ? v3.journal.value : null);
60740
60744
  const populationBind = useBindingValue(v3.population.type === "some" ? v3.population.value : null);
60741
- const meta3 = getOpt(v3.columnMeta);
60742
- const readonly = getOpt(v3.readonly) ?? false;
60745
+ const meta3 = eastUiComponents.getSomeorUndefined(v3.columnMeta);
60746
+ const readonly = eastUiComponents.getSomeorUndefined(v3.readonly) ?? false;
60747
+ const presets = React.useMemo(() => eastUiComponents.getSomeorUndefined(v3.presets) ?? [], [v3.presets]);
60748
+ const [currentPreset, setCurrentPreset] = React.useState(void 0);
60749
+ const presetGroups = React.useMemo(() => {
60750
+ const buckets = /* @__PURE__ */ new Map();
60751
+ for (const p2 of presets) {
60752
+ const label = eastUiComponents.getSomeorUndefined(p2.group) ?? "Saved questions";
60753
+ const bucket = buckets.get(label);
60754
+ if (bucket) bucket.push(p2);
60755
+ else buckets.set(label, [p2]);
60756
+ }
60757
+ return [...buckets].map(([label, items]) => ({ label, items }));
60758
+ }, [presets]);
60743
60759
  const { columns, rowArrayType } = useColumns(workspace, v3.data.source);
60744
60760
  const config2 = configBind.value;
60745
60761
  const [localPop, setLocalPop] = React.useState([]);
@@ -60753,7 +60769,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60753
60769
  var _a3;
60754
60770
  return {
60755
60771
  fieldId: c2.name,
60756
- label: getOpt((_a3 = meta3 == null ? void 0 : meta3.get(c2.name)) == null ? void 0 : _a3.label) ?? c2.name,
60772
+ label: eastUiComponents.getSomeorUndefined((_a3 = meta3 == null ? void 0 : meta3.get(c2.name)) == null ? void 0 : _a3.label) ?? c2.name,
60757
60773
  kind: c2.kind
60758
60774
  };
60759
60775
  }),
@@ -60791,17 +60807,24 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60791
60807
  if (experiment.result !== null) setRanConfig(pendingConfigRef.current);
60792
60808
  }, [experiment.result]);
60793
60809
  const [stale, setStale] = React.useState(false);
60794
- const editConfig = React.useCallback((next2) => {
60810
+ const editConfig = React.useCallback((next2, fromPreset) => {
60795
60811
  if (readonly) return;
60796
60812
  setStale(true);
60813
+ setCurrentPreset(fromPreset);
60797
60814
  queueMicrotask(() => configBind.mutate(next2));
60798
60815
  }, [readonly, configBind]);
60799
- const editPopulation = React.useCallback((next2) => {
60816
+ const editPopulation = React.useCallback((next2, fromPreset) => {
60800
60817
  if (readonly) return;
60801
60818
  setStale(true);
60819
+ setCurrentPreset(fromPreset);
60802
60820
  if (v3.population.type === "some") queueMicrotask(() => populationBind.mutate(next2));
60803
60821
  else setLocalPop(next2);
60804
60822
  }, [readonly, v3.population.type, populationBind]);
60823
+ const selectPreset = React.useCallback((p2) => {
60824
+ if (readonly) return;
60825
+ editConfig(p2.config, p2.id);
60826
+ editPopulation(eastUiComponents.getSomeorUndefined(p2.population) ?? [], p2.id);
60827
+ }, [readonly, editConfig, editPopulation]);
60805
60828
  const onRun = React.useCallback(() => {
60806
60829
  runAll();
60807
60830
  setStale(false);
@@ -60815,7 +60838,9 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60815
60838
  naive: r2.naive,
60816
60839
  adjusted: r2.adjusted.type === "some" ? east.some(r2.adjusted.value.effect) : east.none,
60817
60840
  committed_at: /* @__PURE__ */ new Date(),
60818
- committed_by: "you"
60841
+ committed_by: "you",
60842
+ // Record which preset framed this experiment (none for a free-form run).
60843
+ preset: currentPreset !== void 0 ? east.some(currentPreset) : east.none
60819
60844
  };
60820
60845
  journalBind.mutate([row, ...journalBind.value ?? []]);
60821
60846
  try {
@@ -60825,8 +60850,8 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60825
60850
  setStale(false);
60826
60851
  } catch {
60827
60852
  }
60828
- }, [config2, experiment.result, journalBind, configBind, populationBind, v3.population.type]);
60829
- const [tab, setTab] = React.useState(((_a2 = getOpt(v3.defaultTab)) == null ? void 0 : _a2.type) ?? "answer");
60853
+ }, [config2, experiment.result, journalBind, configBind, populationBind, v3.population.type, currentPreset]);
60854
+ const [tab, setTab] = React.useState(((_a2 = eastUiComponents.getSomeorUndefined(v3.defaultTab)) == null ? void 0 : _a2.type) ?? "answer");
60830
60855
  const [guidance, setGuidance] = React.useState(true);
60831
60856
  const now2 = React.useMemo(() => /* @__PURE__ */ new Date(), []);
60832
60857
  const nRows = (filteredRows == null ? void 0 : filteredRows.length) ?? 0;
@@ -60834,7 +60859,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60834
60859
  const rc = ranConfig ?? config2;
60835
60860
  const labelOf = (col) => {
60836
60861
  var _a3;
60837
- return col ? getOpt((_a3 = meta3 == null ? void 0 : meta3.get(col)) == null ? void 0 : _a3.label) ?? col : "";
60862
+ return col ? eastUiComponents.getSomeorUndefined((_a3 = meta3 == null ? void 0 : meta3.get(col)) == null ? void 0 : _a3.label) ?? col : "";
60838
60863
  };
60839
60864
  return { treatment: labelOf(rc == null ? void 0 : rc.treatment), outcome: labelOf(rc == null ? void 0 : rc.outcome), subject: SUBJECT_ONE, subjects: SUBJECT_MANY };
60840
60865
  }, [ranConfig, config2, meta3]);
@@ -60864,10 +60889,18 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60864
60889
  const designFresh = design.result !== null && ((_b2 = designSnapRef.current) == null ? void 0 : _b2.result) === experiment.result && !design.pending;
60865
60890
  if (!config2 || !view) {
60866
60891
  const failed2 = experiment.status === "failed";
60867
- return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { layerStyle: "frame", p: "6", children: failed2 && experiment.error ? /* @__PURE__ */ jsxRuntime.jsx(RunError, { error: experiment.error }) : /* @__PURE__ */ jsxRuntime.jsx(react.Text, { className: failed2 ? void 0 : "elara-skeleton", textStyle: "body.sm", color: "fg.muted", children: failed2 ? "Could not run the experiment." : "Loading experiment…" }) });
60892
+ const which = data4.error ? "dataset" : configBind.error ? "config" : journalBind.error ? "journal" : populationBind.error ? "population filter" : null;
60893
+ const bindError = data4.error ?? configBind.error ?? journalBind.error ?? populationBind.error;
60894
+ const bindMsg = bindError instanceof Error ? bindError.message : bindError != null ? String(bindError) : null;
60895
+ return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { layerStyle: "frame", p: "6", children: bindMsg ? /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { textStyle: "body.sm", color: "fg.danger", children: [
60896
+ "Couldn’t load the experiment ",
60897
+ which,
60898
+ ": ",
60899
+ bindMsg
60900
+ ] }) : failed2 && experiment.error ? /* @__PURE__ */ jsxRuntime.jsx(RunError, { error: experiment.error }) : /* @__PURE__ */ jsxRuntime.jsx(react.Text, { className: failed2 ? void 0 : "elara-skeleton", textStyle: "body.sm", color: "fg.muted", children: failed2 ? "Could not run the experiment." : "Loading experiment…" }) });
60868
60901
  }
60869
60902
  const { spec: vs, answer: a2, refusal: ref, overlap: ov, refute: vr, dose: vd, journal, verdict } = view;
60870
- const higherBetter = getOpt((_c2 = meta3 == null ? void 0 : meta3.get(vs.outcome)) == null ? void 0 : _c2.higherIsBetter);
60903
+ const higherBetter = eastUiComponents.getSomeorUndefined((_c2 = meta3 == null ? void 0 : meta3.get(vs.outcome)) == null ? void 0 : _c2.higherIsBetter);
60871
60904
  const dataStatus = statusR({ status: "success", size: "sm" });
60872
60905
  const barList = (rows) => /* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: bs.root, children: rows.map((r2, i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: bs.row, children: [
60873
60906
  /* @__PURE__ */ jsxRuntime.jsx(react.Text, { css: bs.label, textStyle: "mono.sm", color: "fg.default", truncate: true, children: r2.label }),
@@ -60885,7 +60918,25 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
60885
60918
  const tabKeys = [...["answer", "trust", "dose"], ...hasDesign ? ["validate"] : []];
60886
60919
  return /* @__PURE__ */ jsxRuntime.jsx(GuidanceProvider, { on: guidance, vars: helpVars, children: /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { layerStyle: "frame", overflow: "visible", children: [
60887
60920
  /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { layerStyle: "header.bar", display: "flex", alignItems: "center", gap: "3.5", children: [
60888
- /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "title.card", color: "fg.muted", children: /* @__PURE__ */ jsxRuntime.jsxs(Help, { id: "header", children: [
60921
+ presets.length > 0 && !readonly ? /* @__PURE__ */ jsxRuntime.jsxs(react.Menu.Root, { children: [
60922
+ /* @__PURE__ */ jsxRuntime.jsx(react.Menu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "button", bg: "transparent", border: "0", p: "0", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: "2", textAlign: "start", children: [
60923
+ /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { textStyle: "title.card", color: "fg.muted", children: [
60924
+ "Does ",
60925
+ /* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "brand.solid", fontWeight: "bold", children: vs.treatment }),
60926
+ " change ",
60927
+ /* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "brand.solid", fontWeight: "bold", children: vs.outcome }),
60928
+ "?"
60929
+ ] }),
60930
+ /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", color: "fg.subtle", fontSize: "11px", lineHeight: "1", children: /* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faChevronDown }) })
60931
+ ] }) }),
60932
+ /* @__PURE__ */ jsxRuntime.jsx(react.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Menu.Positioner, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Menu.Content, { minW: "280px", children: presetGroups.map((g2) => /* @__PURE__ */ jsxRuntime.jsxs(react.Menu.ItemGroup, { children: [
60933
+ g2.label !== "Saved questions" && /* @__PURE__ */ jsxRuntime.jsx(react.Menu.ItemGroupLabel, { textStyle: "caption.eyebrow", fontSize: "9px", children: g2.label }),
60934
+ g2.items.map((p2) => /* @__PURE__ */ jsxRuntime.jsxs(react.Menu.Item, { value: p2.id, onClick: () => selectPreset(p2), gap: "2", children: [
60935
+ /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", width: "14px", flexShrink: "0", color: "brand.fg", children: p2.id === currentPreset && /* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faCheck, style: { fontSize: "10px" } }) }),
60936
+ p2.label
60937
+ ] }, p2.id))
60938
+ ] }, g2.label)) }) }) })
60939
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "title.card", color: "fg.muted", children: /* @__PURE__ */ jsxRuntime.jsxs(Help, { id: "header", children: [
60889
60940
  "Does ",
60890
60941
  /* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "brand.solid", fontWeight: "bold", children: vs.treatment }),
60891
60942
  " change ",
@@ -61133,7 +61184,20 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
61133
61184
  /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", color: "fg.muted", children: [
61134
61185
  "· vs ",
61135
61186
  r2.confounders
61136
- ] })
61187
+ ] }),
61188
+ (() => {
61189
+ var _a3;
61190
+ const id3 = eastUiComponents.getSomeorUndefined(r2.preset);
61191
+ if (id3 === void 0) return null;
61192
+ const label = ((_a3 = presets.find((p2) => p2.id === id3)) == null ? void 0 : _a3.label) ?? id3;
61193
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
61194
+ " ",
61195
+ /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: chip({ tone: "brand", size: "sm" }), children: [
61196
+ "from ",
61197
+ label
61198
+ ] })
61199
+ ] });
61200
+ })()
61137
61201
  ] }),
61138
61202
  /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono.sm", fontWeight: "semibold", textAlign: "right", fontVariantNumeric: "tabular-nums", color: r2.verdictTone === "pos" ? "fg.success" : "fg.default", children: r2.effect }),
61139
61203
  /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "caption.eyebrow", textAlign: "right", color: toneToken(r2.verdictTone), children: r2.verdict }),