@elaraai/e3-ui-components 1.0.21 → 1.0.23

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.js CHANGED
@@ -27,7 +27,7 @@ import { jsx as jsx$1, Fragment, jsxs } from "react/jsx-runtime";
27
27
  import * as React from "react";
28
28
  import React__default, { useId, useMemo, useContext, createContext, useRef, useEffect, useState, useCallback, useSyncExternalStore, memo, forwardRef, useLayoutEffect, Fragment as Fragment$1, Component } from "react";
29
29
  import { Box, Flex, Text, HStack, Input, useSlotRecipe, useRecipe, VStack, useToken, Drawer, Portal, Field, NativeSelect, Textarea, chakra, Tooltip, SegmentGroup, Menu, HoverCard, useChakraContext, Spinner, Code, Clipboard, IconButton, Badge, Button, Tabs, useTabs } from "@chakra-ui/react";
30
- import { implementUIComponent, getSomeorUndefined, SliceEditPopover, SlicePredicateBuilder, formatPredicate, StateRuntime, buildSliceHandle, DEFAULT_SLICE_STATE, registerPlatformImplementation as registerPlatformImplementation$1, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, OverlayImpl, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
30
+ import { implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, StateRuntime, buildSliceHandle, DEFAULT_SLICE_STATE, registerPlatformImplementation as registerPlatformImplementation$1, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, OverlayImpl, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
31
31
  import { createPortal } from "react-dom";
32
32
  import "@elaraai/e3-ui";
33
33
  import { sliceMatches } from "@elaraai/east-ui/internal";
@@ -60709,9 +60709,28 @@ function DeckSkeleton({ tab }) {
60709
60709
  ] })
60710
60710
  ] });
60711
60711
  }
60712
+ function LoadingSkeleton() {
60713
+ const sk = useRecipe({ key: "skeleton" });
60714
+ const line2 = (w2, h2) => /* @__PURE__ */ jsx$1(Box, { css: sk({ variant: "line" }), width: w2, height: h2 });
60715
+ const block = (h2) => /* @__PURE__ */ jsx$1(Box, { css: sk({ variant: "block" }), width: "100%", minHeight: h2 });
60716
+ return /* @__PURE__ */ jsxs(Box, { layerStyle: "frame", overflow: "visible", children: [
60717
+ /* @__PURE__ */ jsxs(Box, { layerStyle: "header.bar", display: "flex", alignItems: "center", gap: "3.5", children: [
60718
+ line2("260px", "20px"),
60719
+ /* @__PURE__ */ jsx$1(Box, { flex: "1" }),
60720
+ line2("72px", "16px")
60721
+ ] }),
60722
+ /* @__PURE__ */ jsxs(Box, { display: "grid", gridTemplateColumns: "304px minmax(0,1fr)", alignItems: "start", children: [
60723
+ /* @__PURE__ */ jsx$1(Box, { borderRightWidth: "1px", borderColor: "border.subtle", p: "4.5", display: "flex", flexDirection: "column", gap: "5", children: [0, 1, 2, 3].map((n2) => /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", gap: "2", children: [
60724
+ line2("150px", "12px"),
60725
+ block("40px")
60726
+ ] }, n2)) }),
60727
+ /* @__PURE__ */ jsx$1(DeckSkeleton, { tab: "answer" })
60728
+ ] })
60729
+ ] });
60730
+ }
60712
60731
  const experimentValueEqual = equalFor(Experiment.Component.schema);
60713
60732
  const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60714
- var _a2, _b2, _c2, _d2;
60733
+ var _a2, _b2, _c2;
60715
60734
  const v3 = value;
60716
60735
  const button = useRecipe({ key: "button" });
60717
60736
  const chip = useRecipe({ key: "chip" });
@@ -60721,27 +60740,48 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60721
60740
  const es = useSlotRecipe({ key: "eyebrowRow" })({});
60722
60741
  const workspace = getReactiveDatasetCache().getConfig().workspace ?? "";
60723
60742
  const data4 = useBindingValue(v3.data);
60724
- const configBind = useBindingValue(v3.config);
60725
60743
  const journalBind = useBindingValue(v3.journal.type === "some" ? v3.journal.value : null);
60726
- const populationBind = useBindingValue(v3.population.type === "some" ? v3.population.value : null);
60727
60744
  const meta3 = getSomeorUndefined(v3.columnMeta);
60728
60745
  const readonly = getSomeorUndefined(v3.readonly) ?? false;
60729
- const presets = useMemo(() => getSomeorUndefined(v3.presets) ?? [], [v3.presets]);
60730
- const [currentPreset, setCurrentPreset] = useState(void 0);
60731
- const presetGroups = useMemo(() => {
60746
+ const configsBind = useBindingValue(v3.configs);
60747
+ const configs = useMemo(() => configsBind.value ?? [], [configsBind.value]);
60748
+ const [currentConfigId, setCurrentConfigId] = useState(void 0);
60749
+ const selectedEntry = useMemo(
60750
+ () => configs.find((c2) => c2.id === currentConfigId) ?? configs[0],
60751
+ [configs, currentConfigId]
60752
+ );
60753
+ useEffect(() => {
60754
+ const first2 = configs[0];
60755
+ if (currentConfigId === void 0 && first2 !== void 0) setCurrentConfigId(first2.id);
60756
+ }, [configs, currentConfigId]);
60757
+ const configGroups = useMemo(() => {
60732
60758
  const buckets = /* @__PURE__ */ new Map();
60733
- for (const p2 of presets) {
60734
- const label = getSomeorUndefined(p2.group) ?? "Saved questions";
60759
+ for (const c2 of configs) {
60760
+ const label = getSomeorUndefined(c2.group) ?? "Questions";
60735
60761
  const bucket = buckets.get(label);
60736
- if (bucket) bucket.push(p2);
60737
- else buckets.set(label, [p2]);
60762
+ if (bucket) bucket.push(c2);
60763
+ else buckets.set(label, [c2]);
60738
60764
  }
60739
60765
  return [...buckets].map(([label, items]) => ({ label, items }));
60740
- }, [presets]);
60766
+ }, [configs]);
60741
60767
  const { columns, rowArrayType } = useColumns(workspace, v3.data.source);
60742
- const config2 = configBind.value;
60768
+ const [workingConfig, setWorkingConfig] = useState(void 0);
60743
60769
  const [localPop, setLocalPop] = useState([]);
60744
- const population = populationBind.value ?? localPop;
60770
+ const [stale, setStale] = useState(false);
60771
+ const seededIdRef = useRef(void 0);
60772
+ useEffect(() => {
60773
+ const id3 = selectedEntry == null ? void 0 : selectedEntry.id;
60774
+ if (id3 === seededIdRef.current) return;
60775
+ const switching = seededIdRef.current !== void 0;
60776
+ seededIdRef.current = id3;
60777
+ setWorkingConfig(selectedEntry == null ? void 0 : selectedEntry.spec);
60778
+ setLocalPop(getSomeorUndefined(selectedEntry == null ? void 0 : selectedEntry.population) ?? []);
60779
+ const precomputed = (selectedEntry == null ? void 0 : selectedEntry.result.type) === "some";
60780
+ const hasEstimator = v3.experiment.type === "some";
60781
+ setStale(switching && hasEstimator && !precomputed);
60782
+ }, [selectedEntry, v3.experiment.type]);
60783
+ const config2 = workingConfig;
60784
+ const population = localPop;
60745
60785
  const filteredRows = useMemo(() => {
60746
60786
  if (!data4.value) return null;
60747
60787
  return population.length ? data4.value.filter((r2) => rowMatchesAll(r2, population)) : data4.value;
@@ -60758,7 +60798,9 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60758
60798
  [columns, meta3]
60759
60799
  );
60760
60800
  const estInputs = useMemo(() => rowArrayType ? [rowArrayType, Experiment.Types.Config] : null, [rowArrayType]);
60761
- const experiment = useFuncCall(v3.experiment.name, estInputs, Experiment.Types.Result);
60801
+ const experiment = useFuncCall(v3.experiment.type === "some" ? v3.experiment.value.name : null, estInputs, Experiment.Types.Result);
60802
+ const hasExperiment = v3.experiment.type === "some";
60803
+ const shownResult = experiment.result ?? getSomeorUndefined(selectedEntry == null ? void 0 : selectedEntry.result) ?? null;
60762
60804
  const hasDesign = v3.design.type === "some";
60763
60805
  const designInputs = useMemo(
60764
60806
  () => rowArrayType ? [rowArrayType, Experiment.Types.Config, Experiment.Types.Result, Experiment.Types.DesignConfig] : null,
@@ -60773,8 +60815,13 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60773
60815
  experiment.call(filteredRows, config2);
60774
60816
  }, [filteredRows, config2, experiment]);
60775
60817
  const autoRan = useRef(false);
60818
+ const hasPrecomputed = selectedEntry !== void 0 && selectedEntry.result.type === "some";
60776
60819
  useEffect(() => {
60777
60820
  if (autoRan.current) return;
60821
+ if (hasPrecomputed || !hasExperiment) {
60822
+ autoRan.current = true;
60823
+ return;
60824
+ }
60778
60825
  if (!filteredRows || !config2 || !rowArrayType) return;
60779
60826
  if (experiment.result !== null || experiment.status === "running") {
60780
60827
  autoRan.current = true;
@@ -60784,29 +60831,23 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60784
60831
  autoRan.current = true;
60785
60832
  if (filteredRows.length > AUTORUN_MAX_ROWS) return;
60786
60833
  runAll();
60787
- }, [filteredRows, config2, rowArrayType, experiment.result, experiment.status, runAll]);
60834
+ }, [hasPrecomputed, hasExperiment, filteredRows, config2, rowArrayType, experiment.result, experiment.status, runAll]);
60788
60835
  useEffect(() => {
60789
60836
  if (experiment.result !== null) setRanConfig(pendingConfigRef.current);
60790
60837
  }, [experiment.result]);
60791
- const [stale, setStale] = useState(false);
60792
- const editConfig = useCallback((next2, fromPreset) => {
60793
- if (readonly) return;
60794
- setStale(true);
60795
- setCurrentPreset(fromPreset);
60796
- queueMicrotask(() => configBind.mutate(next2));
60797
- }, [readonly, configBind]);
60798
- const editPopulation = useCallback((next2, fromPreset) => {
60838
+ const editConfig = useCallback((next2) => {
60799
60839
  if (readonly) return;
60800
- setStale(true);
60801
- setCurrentPreset(fromPreset);
60802
- if (v3.population.type === "some") queueMicrotask(() => populationBind.mutate(next2));
60803
- else setLocalPop(next2);
60804
- }, [readonly, v3.population.type, populationBind]);
60805
- const selectPreset = useCallback((p2) => {
60840
+ if (v3.experiment.type === "some") setStale(true);
60841
+ setWorkingConfig(next2);
60842
+ }, [readonly, v3.experiment.type]);
60843
+ const editPopulation = useCallback((next2) => {
60806
60844
  if (readonly) return;
60807
- editConfig(p2.config, p2.id);
60808
- editPopulation(getSomeorUndefined(p2.population) ?? [], p2.id);
60809
- }, [readonly, editConfig, editPopulation]);
60845
+ if (v3.experiment.type === "some") setStale(true);
60846
+ setLocalPop(next2);
60847
+ }, [readonly, v3.experiment.type]);
60848
+ const selectEntry = useCallback((c2) => {
60849
+ setCurrentConfigId(c2.id);
60850
+ }, []);
60810
60851
  const onRun = useCallback(() => {
60811
60852
  runAll();
60812
60853
  setStale(false);
@@ -60821,18 +60862,16 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60821
60862
  adjusted: r2.adjusted.type === "some" ? some(r2.adjusted.value.effect) : none$1,
60822
60863
  committed_at: /* @__PURE__ */ new Date(),
60823
60864
  committed_by: "you",
60824
- // Record which preset framed this experiment (none for a free-form run).
60825
- preset: currentPreset !== void 0 ? some(currentPreset) : none$1
60865
+ // Record which question framed this experiment.
60866
+ preset: currentConfigId !== void 0 ? some(currentConfigId) : none$1
60826
60867
  };
60827
60868
  journalBind.mutate([row, ...journalBind.value ?? []]);
60828
60869
  try {
60829
60870
  await journalBind.commit();
60830
- await configBind.commit();
60831
- if (v3.population.type === "some") await populationBind.commit();
60832
60871
  setStale(false);
60833
60872
  } catch {
60834
60873
  }
60835
- }, [config2, experiment.result, journalBind, configBind, populationBind, v3.population.type, currentPreset]);
60874
+ }, [config2, experiment.result, journalBind, currentConfigId]);
60836
60875
  const [tab, setTab] = useState(((_a2 = getSomeorUndefined(v3.defaultTab)) == null ? void 0 : _a2.type) ?? "answer");
60837
60876
  const [guidance, setGuidance] = useState(true);
60838
60877
  const now2 = useMemo(() => /* @__PURE__ */ new Date(), []);
@@ -60847,39 +60886,44 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60847
60886
  }, [ranConfig, config2, meta3]);
60848
60887
  const view = useMemo(() => {
60849
60888
  if (!config2) return null;
60850
- return deriveView(config2, ranConfig ?? config2, columns, experiment.result, journalBind.value, meta3, nRows, now2);
60851
- }, [config2, ranConfig, columns, experiment.result, journalBind.value, meta3, nRows, now2]);
60889
+ return deriveView(config2, ranConfig ?? config2, columns, shownResult, journalBind.value, meta3, nRows, now2);
60890
+ }, [config2, ranConfig, columns, shownResult, journalBind.value, meta3, nRows, now2]);
60852
60891
  const designConfigValue = useMemo(() => ({
60853
60892
  alpha: none$1,
60854
60893
  target_power: none$1,
60855
60894
  materiality: none$1,
60856
60895
  treated_shares: some([0.5, 0.3])
60857
60896
  }), []);
60897
+ const precomputedDesign = getSomeorUndefined(selectedEntry == null ? void 0 : selectedEntry.design) ?? null;
60858
60898
  const designSnapRef = useRef(null);
60859
60899
  useEffect(() => {
60860
60900
  var _a3;
60861
- if (tab !== "validate" || !hasDesign || design.pending) return;
60862
- if (!filteredRows || !config2 || !experiment.result) return;
60863
- if (((_a3 = designSnapRef.current) == null ? void 0 : _a3.result) === experiment.result) return;
60864
- designSnapRef.current = { result: experiment.result, config: ranConfig ?? config2 };
60865
- design.call(filteredRows, ranConfig ?? config2, experiment.result, designConfigValue);
60866
- }, [tab, hasDesign, filteredRows, config2, ranConfig, experiment.result, design, designConfigValue]);
60867
- const vmDesign = useMemo(
60868
- () => design.result && designSnapRef.current ? deriveDesign(design.result, designSnapRef.current.result, designSnapRef.current.config, meta3) : null,
60869
- [design.result, meta3]
60870
- );
60871
- const designFresh = design.result !== null && ((_b2 = designSnapRef.current) == null ? void 0 : _b2.result) === experiment.result && !design.pending;
60901
+ if (tab !== "validate" || !hasDesign || design.pending || precomputedDesign !== null) return;
60902
+ if (!filteredRows || !config2 || !shownResult) return;
60903
+ if (((_a3 = designSnapRef.current) == null ? void 0 : _a3.result) === shownResult) return;
60904
+ designSnapRef.current = { result: shownResult, config: ranConfig ?? config2 };
60905
+ design.call(filteredRows, ranConfig ?? config2, shownResult, designConfigValue);
60906
+ }, [tab, hasDesign, precomputedDesign, filteredRows, config2, ranConfig, shownResult, design, designConfigValue]);
60907
+ const vmDesign = useMemo(() => {
60908
+ if (precomputedDesign !== null && shownResult !== null && config2) return deriveDesign(precomputedDesign, shownResult, ranConfig ?? config2, meta3);
60909
+ return design.result && designSnapRef.current ? deriveDesign(design.result, designSnapRef.current.result, designSnapRef.current.config, meta3) : null;
60910
+ }, [precomputedDesign, shownResult, config2, ranConfig, design.result, meta3]);
60911
+ const designFresh = precomputedDesign !== null && shownResult !== null || design.result !== null && ((_b2 = designSnapRef.current) == null ? void 0 : _b2.result) === shownResult && !design.pending;
60872
60912
  if (!config2 || !view) {
60873
60913
  const failed2 = experiment.status === "failed";
60874
- const which = data4.error ? "dataset" : configBind.error ? "config" : journalBind.error ? "journal" : populationBind.error ? "population filter" : null;
60875
- const bindError = data4.error ?? configBind.error ?? journalBind.error ?? populationBind.error;
60914
+ const noConfigs = !configsBind.error && configs.length === 0;
60915
+ const which = data4.error ? "dataset" : configsBind.error ? "configs" : journalBind.error ? "journal" : null;
60916
+ const bindError = data4.error ?? configsBind.error ?? journalBind.error;
60876
60917
  const bindMsg = bindError instanceof Error ? bindError.message : bindError != null ? String(bindError) : null;
60877
- return /* @__PURE__ */ jsx$1(Box, { layerStyle: "frame", p: "6", children: bindMsg ? /* @__PURE__ */ jsxs(Text, { textStyle: "body.sm", color: "fg.danger", children: [
60918
+ if (bindMsg) return /* @__PURE__ */ jsx$1(Box, { layerStyle: "frame", p: "6", children: /* @__PURE__ */ jsxs(Text, { textStyle: "body.sm", color: "fg.danger", children: [
60878
60919
  "Couldn’t load the experiment ",
60879
60920
  which,
60880
60921
  ": ",
60881
60922
  bindMsg
60882
- ] }) : failed2 && experiment.error ? /* @__PURE__ */ jsx$1(RunError, { error: experiment.error }) : /* @__PURE__ */ jsx$1(Text, { className: failed2 ? void 0 : "elara-skeleton", textStyle: "body.sm", color: "fg.muted", children: failed2 ? "Could not run the experiment." : "Loading experiment…" }) });
60923
+ ] }) });
60924
+ if (noConfigs) return /* @__PURE__ */ jsx$1(Box, { layerStyle: "frame", p: "6", children: /* @__PURE__ */ jsx$1(Text, { textStyle: "body.sm", color: "fg.muted", children: "No questions to show — bind a non-empty configs list." }) });
60925
+ if (failed2 && experiment.error) return /* @__PURE__ */ jsx$1(Box, { layerStyle: "frame", p: "6", children: /* @__PURE__ */ jsx$1(RunError, { error: experiment.error }) });
60926
+ return /* @__PURE__ */ jsx$1(LoadingSkeleton, {});
60883
60927
  }
60884
60928
  const { spec: vs, answer: a2, refusal: ref, overlap: ov, refute: vr, dose: vd, journal, verdict } = view;
60885
60929
  const higherBetter = getSomeorUndefined((_c2 = meta3 == null ? void 0 : meta3.get(vs.outcome)) == null ? void 0 : _c2.higherIsBetter);
@@ -60889,18 +60933,19 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60889
60933
  /* @__PURE__ */ jsx$1(Box, { css: bs.track, children: /* @__PURE__ */ jsx$1(Box, { css: bs.fill, width: `${Math.round(r2.frac * 100)}%`, bg: toneToken(r2.tone) }) }),
60890
60934
  /* @__PURE__ */ jsx$1(Text, { css: bs.value, children: r2.value })
60891
60935
  ] }, i)) });
60892
- const specStaged = configBind.mode === "staged";
60893
60936
  const hasJournal = v3.journal.type === "some";
60894
- const canRun = !readonly;
60895
- const canCommit = !readonly && specStaged && hasJournal;
60937
+ const canRun = !readonly && hasExperiment;
60938
+ const canCommit = !readonly && hasExperiment && hasJournal;
60896
60939
  const runDisabled = !data4.value || experiment.pending;
60897
60940
  const commitDisabled = experiment.status !== "succeeded" || experiment.pending || stale;
60898
60941
  const failed = experiment.status === "failed" && experiment.error;
60899
- const showResult = experiment.result !== null && !experiment.pending && !failed;
60900
- const tabKeys = [...["answer", "trust", "dose"], ...hasDesign ? ["validate"] : []];
60942
+ const showResult = shownResult !== null && !experiment.pending && !failed;
60943
+ const anyPrecomputedDesign = configs.some((c2) => c2.design.type === "some");
60944
+ const showValidate = hasDesign || anyPrecomputedDesign;
60945
+ const tabKeys = [...["answer", "trust", "dose"], ...showValidate ? ["validate"] : []];
60901
60946
  return /* @__PURE__ */ jsx$1(GuidanceProvider, { on: guidance, vars: helpVars, children: /* @__PURE__ */ jsxs(Box, { layerStyle: "frame", overflow: "visible", children: [
60902
60947
  /* @__PURE__ */ jsxs(Box, { layerStyle: "header.bar", display: "flex", alignItems: "center", gap: "3.5", children: [
60903
- presets.length > 0 && !readonly ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
60948
+ configs.length > 1 ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
60904
60949
  /* @__PURE__ */ jsx$1(Menu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(Box, { as: "button", bg: "transparent", border: "0", p: "0", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: "2", textAlign: "start", children: [
60905
60950
  /* @__PURE__ */ jsxs(Text, { textStyle: "title.card", color: "fg.muted", children: [
60906
60951
  "Does ",
@@ -60911,12 +60956,12 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60911
60956
  ] }),
60912
60957
  /* @__PURE__ */ jsx$1(Box, { as: "span", color: "fg.subtle", fontSize: "11px", lineHeight: "1", children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faChevronDown }) })
60913
60958
  ] }) }),
60914
- /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Menu.Positioner, { children: /* @__PURE__ */ jsx$1(Menu.Content, { minW: "280px", children: presetGroups.map((g2) => /* @__PURE__ */ jsxs(Menu.ItemGroup, { children: [
60915
- g2.label !== "Saved questions" && /* @__PURE__ */ jsx$1(Menu.ItemGroupLabel, { textStyle: "caption.eyebrow", fontSize: "9px", children: g2.label }),
60916
- g2.items.map((p2) => /* @__PURE__ */ jsxs(Menu.Item, { value: p2.id, onClick: () => selectPreset(p2), gap: "2", children: [
60917
- /* @__PURE__ */ jsx$1(Box, { as: "span", width: "14px", flexShrink: "0", color: "brand.fg", children: p2.id === currentPreset && /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faCheck, style: { fontSize: "10px" } }) }),
60918
- p2.label
60919
- ] }, p2.id))
60959
+ /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Menu.Positioner, { children: /* @__PURE__ */ jsx$1(Menu.Content, { minW: "280px", children: configGroups.map((g2) => /* @__PURE__ */ jsxs(Menu.ItemGroup, { children: [
60960
+ g2.label !== "Questions" && /* @__PURE__ */ jsx$1(Menu.ItemGroupLabel, { textStyle: "caption.eyebrow", fontSize: "9px", children: g2.label }),
60961
+ g2.items.map((c2) => /* @__PURE__ */ jsxs(Menu.Item, { value: c2.id, onClick: () => selectEntry(c2), gap: "2", children: [
60962
+ /* @__PURE__ */ jsx$1(Box, { as: "span", width: "14px", flexShrink: "0", color: "brand.fg", children: c2.id === (selectedEntry == null ? void 0 : selectedEntry.id) && /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faCheck, style: { fontSize: "10px" } }) }),
60963
+ c2.label
60964
+ ] }, c2.id))
60920
60965
  ] }, g2.label)) }) }) })
60921
60966
  ] }) : /* @__PURE__ */ jsx$1(Text, { textStyle: "title.card", color: "fg.muted", children: /* @__PURE__ */ jsxs(Help, { id: "header", children: [
60922
60967
  "Does ",
@@ -60926,6 +60971,7 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60926
60971
  "?"
60927
60972
  ] }) }),
60928
60973
  /* @__PURE__ */ jsx$1(Box, { flex: "1" }),
60974
+ readonly && /* @__PURE__ */ jsx$1(Box, { as: "span", css: badge({ variant: "plain", size: "sm" }), textTransform: "none", letterSpacing: "normal", children: "View only" }),
60929
60975
  /* @__PURE__ */ jsxs(Box, { as: "span", css: dataStatus.root, children: [
60930
60976
  /* @__PURE__ */ jsx$1(Box, { as: "span", css: dataStatus.indicator }),
60931
60977
  /* @__PURE__ */ jsx$1(Box, { as: "span", css: dataStatus.label, children: stale ? `${nRows} rows` : vs.dataLabel })
@@ -60937,15 +60983,15 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60937
60983
  /* @__PURE__ */ jsxs(Box, { display: "grid", gridTemplateColumns: "304px minmax(0,1fr)", alignItems: "start", children: [
60938
60984
  /* @__PURE__ */ jsxs(Box, { borderRightWidth: "1px", borderColor: "border.subtle", children: [
60939
60985
  /* @__PURE__ */ jsxs(Step, { n: 1, title: "What did you change?", help: "step_treatment", children: [
60940
- /* @__PURE__ */ jsx$1(ColumnPick, { column: vs.treatment, kind: vs.treatmentKind, badge, button, choices: columns.filter((c2) => c2.kind === "boolean" || c2.kind === "integer").map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, treatment: c2 }) }),
60986
+ /* @__PURE__ */ jsx$1(ColumnPick, { column: vs.treatment, kind: vs.treatmentKind, badge, button, readonly, choices: columns.filter((c2) => c2.kind === "boolean" || c2.kind === "integer").map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, treatment: c2 }) }),
60941
60987
  /* @__PURE__ */ jsxs(Text, { textStyle: "caption", mt: "1.5", children: [
60942
60988
  "Treated = ",
60943
60989
  /* @__PURE__ */ jsx$1(Text, { as: "span", color: "fg.default", fontWeight: "semibold", children: vs.comparison })
60944
60990
  ] })
60945
60991
  ] }),
60946
- /* @__PURE__ */ jsx$1(Step, { n: 2, title: "What did you want it to improve?", help: "step_outcome", children: /* @__PURE__ */ jsx$1(ColumnPick, { column: vs.outcome, kind: vs.outcomeKind, badge, button, choices: columns.filter((c2) => c2.kind === "float" || c2.kind === "integer").map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, outcome: c2 }) }) }),
60992
+ /* @__PURE__ */ jsx$1(Step, { n: 2, title: "What did you want it to improve?", help: "step_outcome", children: /* @__PURE__ */ jsx$1(ColumnPick, { column: vs.outcome, kind: vs.outcomeKind, badge, button, readonly, choices: columns.filter((c2) => c2.kind === "float" || c2.kind === "integer").map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, outcome: c2 }) }) }),
60947
60993
  /* @__PURE__ */ jsx$1(Step, { n: 3, title: "What else was different?", help: "step_confounders", children: /* @__PURE__ */ jsxs(Box, { layerStyle: "frame.flat", children: [
60948
- /* @__PURE__ */ jsx$1(Box, { maxH: "216px", overflowY: "auto", children: vs.confounders.map((c2, i) => /* @__PURE__ */ jsxs(Box, { display: "grid", gridTemplateColumns: "1fr 78px 16px", gap: "2.5", alignItems: "center", px: "2.5", py: "2.5", borderTopWidth: i ? "1px" : "0", borderColor: "border.subtle", children: [
60994
+ /* @__PURE__ */ jsx$1(Box, { maxH: "216px", overflowY: "auto", children: vs.confounders.map((c2, i) => /* @__PURE__ */ jsxs(Box, { display: "grid", gridTemplateColumns: readonly ? "1fr 78px" : "1fr 78px 16px", gap: "2.5", alignItems: "center", px: "2.5", py: "2.5", borderTopWidth: i ? "1px" : "0", borderColor: "border.subtle", children: [
60949
60995
  /* @__PURE__ */ jsxs(Box, { children: [
60950
60996
  /* @__PURE__ */ jsx$1(Text, { textStyle: "mono.sm", fontWeight: "semibold", color: "fg.default", children: c2.col }),
60951
60997
  /* @__PURE__ */ jsx$1(Text, { textStyle: "caption", lineHeight: "1.35", mt: "px", children: c2.reason })
@@ -60954,14 +61000,14 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60954
61000
  /* @__PURE__ */ jsx$1(Box, { css: bs.track, children: /* @__PURE__ */ jsx$1(Box, { css: bs.fill, width: `${Math.round(c2.imbalance * 100)}%`, bg: toneToken(c2.tone) }) }),
60955
61001
  /* @__PURE__ */ jsx$1(Text, { textStyle: "caption.eyebrow", fontSize: "9px", textAlign: "center", mt: "1.5", children: /* @__PURE__ */ jsx$1(Help, { id: "confounder_imbalance", children: c2.level }) })
60956
61002
  ] }),
60957
- /* @__PURE__ */ jsx$1(Box, { as: "button", css: button({ variant: "ghost", size: "xs" }), px: "0", minW: "16px", display: "inline-flex", alignItems: "center", justifyContent: "center", "aria-label": `Remove ${c2.col}`, onClick: () => editConfig({ ...config2, common_causes: config2.common_causes.filter((x2) => x2 !== c2.col), categorical: config2.categorical.type === "some" ? some(config2.categorical.value.filter((x2) => x2 !== c2.col)) : none$1 }), children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faXmark, style: { fontSize: "11px" } }) })
61003
+ !readonly && /* @__PURE__ */ jsx$1(Box, { as: "button", css: button({ variant: "ghost", size: "xs" }), px: "0", minW: "16px", display: "inline-flex", alignItems: "center", justifyContent: "center", "aria-label": `Remove ${c2.col}`, onClick: () => editConfig({ ...config2, common_causes: config2.common_causes.filter((x2) => x2 !== c2.col), categorical: config2.categorical.type === "some" ? some(config2.categorical.value.filter((x2) => x2 !== c2.col)) : none$1 }), children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faXmark, style: { fontSize: "11px" } }) })
60958
61004
  ] }, i)) }),
60959
- vs.suggestion && /* @__PURE__ */ jsx$1(ColumnMenu, { choices: columns.filter((c2) => !(/* @__PURE__ */ new Set([config2.treatment, config2.outcome, ...config2.common_causes])).has(c2.name)).map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, common_causes: [...config2.common_causes, c2] }), children: /* @__PURE__ */ jsxs(Box, { as: "button", css: button({ variant: "ghost", size: "sm" }), justifyContent: "flex-start", width: "100%", color: "brand.fg", fontFamily: "mono", display: "inline-flex", alignItems: "center", gap: "2", children: [
61005
+ !readonly && vs.suggestion && /* @__PURE__ */ jsx$1(ColumnMenu, { choices: columns.filter((c2) => !(/* @__PURE__ */ new Set([config2.treatment, config2.outcome, ...config2.common_causes])).has(c2.name)).map((c2) => c2.name), onPick: (c2) => editConfig({ ...config2, common_causes: [...config2.common_causes, c2] }), children: /* @__PURE__ */ jsxs(Box, { as: "button", css: button({ variant: "ghost", size: "sm" }), justifyContent: "flex-start", width: "100%", color: "brand.fg", fontFamily: "mono", display: "inline-flex", alignItems: "center", gap: "2", children: [
60960
61006
  /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faPlus, style: { fontSize: "9px" } }),
60961
61007
  "add another"
60962
61008
  ] }) })
60963
61009
  ] }) }),
60964
- /* @__PURE__ */ jsx$1(Step, { n: 4, title: `Which ${SUBJECT_MANY}?`, help: "step_population", children: /* @__PURE__ */ jsx$1(FilterRail, { fields, population, onChange: editPopulation, chip, button }) }),
61010
+ /* @__PURE__ */ jsx$1(Step, { n: 4, title: `Which ${SUBJECT_MANY}?`, help: "step_population", children: /* @__PURE__ */ jsx$1(FilterRail, { fields, population, onChange: editPopulation, chip, button, readonly }) }),
60965
61011
  /* @__PURE__ */ jsxs(Box, { as: "details", borderTopWidth: "1px", borderColor: "border.subtle", children: [
60966
61012
  /* @__PURE__ */ jsxs(
60967
61013
  Box,
@@ -60994,8 +61040,8 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
60994
61040
  }
60995
61041
  ),
60996
61042
  /* @__PURE__ */ jsxs(Box, { px: "4.5", pb: "3.5", pt: "0.5", children: [
60997
- /* @__PURE__ */ jsx$1(Segmented, { label: "How to compare", help: "adv_method", left: "regression", right: "reweighting", active: vs.method === "reweighting" ? "right" : "left", onPick: (s2) => editConfig({ ...config2, method: some(s2 === "right" ? variant("propensity_score_weighting", { weighting_scheme: none$1 }) : variant("linear_regression", null)) }) }),
60998
- /* @__PURE__ */ jsx$1(Segmented, { label: "Answer for", help: "adv_estimand", left: "all", right: "only treated", active: vs.target === "treated" ? "right" : "left", onPick: (s2) => editConfig({ ...config2, estimand: some(variant(s2 === "right" ? "att" : "ate", null)) }), last: true })
61043
+ /* @__PURE__ */ jsx$1(Segmented, { label: "How to compare", help: "adv_method", left: "regression", right: "reweighting", active: vs.method === "reweighting" ? "right" : "left", readonly, onPick: (s2) => editConfig({ ...config2, method: some(s2 === "right" ? variant("propensity_score_weighting", { weighting_scheme: none$1 }) : variant("linear_regression", null)) }) }),
61044
+ /* @__PURE__ */ jsx$1(Segmented, { label: "Answer for", help: "adv_estimand", left: "all", right: "only treated", active: vs.target === "treated" ? "right" : "left", readonly, onPick: (s2) => editConfig({ ...config2, estimand: some(variant(s2 === "right" ? "att" : "ate", null)) }), last: true })
60999
61045
  ] })
61000
61046
  ] })
61001
61047
  ] }),
@@ -61069,7 +61115,7 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
61069
61115
  ] })
61070
61116
  ] }),
61071
61117
  tab === "answer" && a2 && /* @__PURE__ */ jsx$1(AnswerNumeric, { a: a2, verdict, higherBetter, badge, barList }),
61072
- tab === "answer" && !a2 && ref && /* @__PURE__ */ jsx$1(RefusalZone, { refusal: ref, overlap: ov, naiveValue: ((_d2 = experiment.result) == null ? void 0 : _d2.naive) ?? 0, outcome: vs.outcome }),
61118
+ tab === "answer" && !a2 && ref && /* @__PURE__ */ jsx$1(RefusalZone, { refusal: ref, overlap: ov, naiveValue: (shownResult == null ? void 0 : shownResult.naive) ?? 0, outcome: vs.outcome }),
61073
61119
  tab === "trust" && vr && /* @__PURE__ */ jsxs(Box, { p: "4.5", children: [
61074
61120
  /* @__PURE__ */ jsx$1(Text, { textStyle: "body.sm", color: "fg.muted", mb: "3.5", children: /* @__PURE__ */ jsx$1(Help, { id: "trust_intro", children: "Before trusting the answer we tried to break it — colour shows pass / caution." }) }),
61075
61121
  /* @__PURE__ */ jsx$1(Box, { layerStyle: "frame.flat", children: vr.checks.map((c2, i) => {
@@ -61171,7 +61217,7 @@ const EastChakraExperiment = memo(function EastChakraExperiment2({ value }) {
61171
61217
  var _a3;
61172
61218
  const id3 = getSomeorUndefined(r2.preset);
61173
61219
  if (id3 === void 0) return null;
61174
- const label = ((_a3 = presets.find((p2) => p2.id === id3)) == null ? void 0 : _a3.label) ?? id3;
61220
+ const label = ((_a3 = configs.find((c2) => c2.id === id3)) == null ? void 0 : _a3.label) ?? id3;
61175
61221
  return /* @__PURE__ */ jsxs(Fragment, { children: [
61176
61222
  " ",
61177
61223
  /* @__PURE__ */ jsxs(Box, { as: "span", css: chip({ tone: "brand", size: "sm" }), children: [
@@ -61371,11 +61417,17 @@ function ValidatePanel({ vm, barList }) {
61371
61417
  ] }, i)) })
61372
61418
  ] });
61373
61419
  }
61374
- function FilterRail({ fields, population, onChange: onChange2, chip, button }) {
61420
+ function FilterRail({ fields, population, onChange: onChange2, chip, button, readonly }) {
61375
61421
  const [open, setOpen] = useState(null);
61376
61422
  const replaceAt = (i, p2) => onChange2(population.map((f2, j2) => j2 === i ? p2 : f2));
61377
61423
  const removeAt = (i) => onChange2(population.filter((_2, j2) => j2 !== i));
61378
61424
  const done = /* @__PURE__ */ jsx$1(Box, { as: "button", css: button({ variant: "outline", size: "xs" }), onClick: () => setOpen(null), children: "Done" });
61425
+ if (readonly) {
61426
+ return /* @__PURE__ */ jsx$1(Box, { display: "flex", flexWrap: "wrap", gap: "1.5", alignItems: "center", children: population.length === 0 ? /* @__PURE__ */ jsxs(Box, { css: chip({ tone: "plain", numeric: true, shape: "rounded" }), children: [
61427
+ "all ",
61428
+ SUBJECT_MANY
61429
+ ] }) : population.map((pred, i) => /* @__PURE__ */ jsx$1(Box, { css: chip({ tone: "brand", numeric: true, shape: "rounded" }), flexShrink: 0, children: /* @__PURE__ */ jsx$1(Box, { as: "span", whiteSpace: "nowrap", children: formatPredicate(pred) }) }, i)) });
61430
+ }
61379
61431
  return /* @__PURE__ */ jsxs(Box, { display: "flex", flexWrap: "wrap", gap: "1.5", alignItems: "center", children: [
61380
61432
  population.map((pred, i) => /* @__PURE__ */ jsx$1(
61381
61433
  SliceEditPopover,
@@ -61436,7 +61488,13 @@ function ColumnMenu({ choices, onPick, children: children2 }) {
61436
61488
  /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Menu.Positioner, { children: /* @__PURE__ */ jsx$1(Menu.Content, { children: choices.map((c2) => /* @__PURE__ */ jsx$1(Menu.Item, { value: c2, onClick: () => onPick(c2), children: c2 }, c2)) }) }) })
61437
61489
  ] });
61438
61490
  }
61439
- function ColumnPick({ column: column2, kind, choices, onPick, badge, button }) {
61491
+ function ColumnPick({ column: column2, kind, choices, onPick, badge, button, readonly }) {
61492
+ if (readonly) {
61493
+ return /* @__PURE__ */ jsxs(Box, { css: button({ variant: "outline", size: "sm" }), gap: "1.5", cursor: "default", children: [
61494
+ /* @__PURE__ */ jsx$1(Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", children: column2 }),
61495
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: badge({ variant: "plain", size: "sm" }), textTransform: "none", letterSpacing: "normal", children: kind })
61496
+ ] });
61497
+ }
61440
61498
  return /* @__PURE__ */ jsx$1(ColumnMenu, { choices, onPick, children: /* @__PURE__ */ jsxs(Box, { as: "button", css: button({ variant: "outline", size: "sm" }), gap: "1.5", children: [
61441
61499
  /* @__PURE__ */ jsx$1(Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", children: column2 }),
61442
61500
  /* @__PURE__ */ jsx$1(Box, { as: "span", css: badge({ variant: "plain", size: "sm" }), textTransform: "none", letterSpacing: "normal", children: kind }),
@@ -61479,10 +61537,14 @@ function SegmentSelect({ options: options2, active, onPick, fill, size: size3 =
61479
61537
  }
61480
61538
  );
61481
61539
  }
61482
- function Segmented({ label, left, right, active, onPick, last: last2, help }) {
61540
+ function SegmentStatic({ value, size: size3 = "xs" }) {
61541
+ const s2 = useSlotRecipe({ key: "segmentGroup" })({ size: size3 });
61542
+ return /* @__PURE__ */ jsx$1(Box, { css: s2.root, alignSelf: "flex-start", children: /* @__PURE__ */ jsx$1(Box, { css: s2.item, "data-state": "checked", children: /* @__PURE__ */ jsx$1(Box, { as: "span", css: s2.itemText, children: value }) }) });
61543
+ }
61544
+ function Segmented({ label, left, right, active, onPick, last: last2, help, readonly }) {
61483
61545
  return /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", alignItems: "stretch", gap: "1.5", py: "2", borderBottomWidth: last2 ? "0" : "1px", borderColor: "border.subtle", children: [
61484
61546
  /* @__PURE__ */ jsx$1(Text, { textStyle: "caption.eyebrow", textTransform: "none", letterSpacing: "normal", color: "fg.default", children: help ? /* @__PURE__ */ jsx$1(Help, { id: help, children: label }) : label }),
61485
- /* @__PURE__ */ jsx$1(SegmentSelect, { options: [left, right], active: active === "left" ? 0 : 1, onPick: (i) => onPick(i === 0 ? "left" : "right"), fill: true, size: "xs" })
61547
+ readonly ? /* @__PURE__ */ jsx$1(SegmentStatic, { value: active === "left" ? left : right }) : /* @__PURE__ */ jsx$1(SegmentSelect, { options: [left, right], active: active === "left" ? 0 : 1, onPick: (i) => onPick(i === 0 ? "left" : "right"), fill: true, size: "xs" })
61486
61548
  ] });
61487
61549
  }
61488
61550
  implementUIComponent(Experiment.Component, EastChakraExperiment);