@railtownai/railtracks-visualizer 0.0.54 → 0.0.55

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/esm/index.js CHANGED
@@ -8,7 +8,7 @@ import RcDrawer from '@rc-component/drawer';
8
8
  import useId$2 from '@rc-component/util/es/hooks/useId';
9
9
  import { composeRef, supportRef, getNodeRef, supportNodeRef, useComposeRef as useComposeRef$1 } from '@rc-component/util/es/ref';
10
10
  import '@rc-component/form';
11
- import { warning as warning$1, merge, useEvent, toArray as toArray$1, omit, useComposeRef, useControlledState } from '@rc-component/util';
11
+ import { warning as warning$2, merge, useEvent, toArray as toArray$1, omit, useComposeRef, useControlledState } from '@rc-component/util';
12
12
  import CloseOutlined from '@ant-design/icons/es/icons/CloseOutlined';
13
13
  import pickAttrs from '@rc-component/util/es/pickAttrs';
14
14
  import Pagination$1 from '@rc-component/pagination/es/locale/en_US';
@@ -8051,7 +8051,7 @@ function fixedForwardRef(render) {
8051
8051
  return forwardRef(render);
8052
8052
  }
8053
8053
  // we need this hook to prevent a warning when using react-flow in SSR
8054
- const useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
8054
+ const useIsomorphicLayoutEffect$3 = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
8055
8055
  /**
8056
8056
  * This hook returns a queue that can be used to batch updates.
8057
8057
  *
@@ -8076,7 +8076,7 @@ const useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? useLayoutEff
8076
8076
  * Layout effects are guaranteed to run before the next render which means we
8077
8077
  * shouldn't run into any issues with stale state or weird issues that come from
8078
8078
  * rendering things one frame later than expected (we used to use `setTimeout`).
8079
- */ useIsomorphicLayoutEffect$2(()=>{
8079
+ */ useIsomorphicLayoutEffect$3(()=>{
8080
8080
  const queueItems = queue.get();
8081
8081
  if (queueItems.length) {
8082
8082
  runQueue(queueItems);
@@ -15204,7 +15204,7 @@ function requireHoistNonReactStatics_cjs() {
15204
15204
 
15205
15205
  requireHoistNonReactStatics_cjs();
15206
15206
 
15207
- var isBrowser = true;
15207
+ var isBrowser$1 = true;
15208
15208
  function getRegisteredStyles(registered, registeredStyles, classNames) {
15209
15209
  var rawClassName = '';
15210
15210
  classNames.split(' ').forEach(function(className) {
@@ -15226,7 +15226,7 @@ var registerStyles = function registerStyles(cache, serialized, isStringTag) {
15226
15226
  // in node since emotion-server relies on whether a style is in
15227
15227
  // the registered cache to know whether a style is global or not
15228
15228
  // also, note that this check will be dead code eliminated in the browser
15229
- isBrowser === false) && cache.registered[className] === undefined) {
15229
+ isBrowser$1 === false) && cache.registered[className] === undefined) {
15230
15230
  cache.registered[className] = serialized.styles;
15231
15231
  }
15232
15232
  };
@@ -15874,6 +15874,21 @@ const ThemeProvider = ({ children, theme: propTheme })=>{
15874
15874
  }, [
15875
15875
  propTheme
15876
15876
  ]);
15877
+ // Sync html.dark class for GlobalStyles and other CSS that uses html.dark
15878
+ useEffect(()=>{
15879
+ const isDark = currentTheme === darkTheme;
15880
+ try {
15881
+ if (isDark) {
15882
+ document.documentElement.classList.add("dark");
15883
+ } else {
15884
+ document.documentElement.classList.remove("dark");
15885
+ }
15886
+ } catch (e) {
15887
+ // document might not be available (e.g. SSR)
15888
+ }
15889
+ }, [
15890
+ currentTheme
15891
+ ]);
15877
15892
  // Only listen for storage events if no theme prop is provided
15878
15893
  useEffect(()=>{
15879
15894
  if (propTheme) {
@@ -20981,7 +20996,7 @@ function cn(...inputs) {
20981
20996
  /**
20982
20997
  * Formats a metric value for display based on evaluator metric definitions.
20983
20998
  * Handles Categorical (index → option label), Continuous (decimal), and fallback.
20984
- */ function formatMetricValue(evaluator, metricName, value) {
20999
+ */ function formatMetricValue$1(evaluator, metricName, value) {
20985
21000
  if (value === undefined || value === null) return "-";
20986
21001
  const numericValue = typeof value === "number" ? value : Number(value);
20987
21002
  if (isNaN(numericValue)) return "-";
@@ -21608,7 +21623,7 @@ const Badge = ({ variant = "default", children, title, placement = "top" })=>{
21608
21623
  };
21609
21624
 
21610
21625
  function noop$2() {}
21611
- const { resetWarned: rcResetWarned } = warning$1;
21626
+ const { resetWarned: rcResetWarned } = warning$2;
21612
21627
  let deprecatedWarnList = null;
21613
21628
  function resetWarned() {
21614
21629
  deprecatedWarnList = null;
@@ -21617,14 +21632,14 @@ function resetWarned() {
21617
21632
  let _warning = noop$2;
21618
21633
  if (process.env.NODE_ENV !== 'production') {
21619
21634
  _warning = (valid, component, message)=>{
21620
- warning$1(valid, `[antd: ${component}] ${message}`);
21635
+ warning$2(valid, `[antd: ${component}] ${message}`);
21621
21636
  // StrictMode will inject console which will not throw warning in React 17.
21622
21637
  if (process.env.NODE_ENV === 'test') {
21623
21638
  resetWarned();
21624
21639
  }
21625
21640
  };
21626
21641
  }
21627
- const warning = _warning;
21642
+ const warning$1 = _warning;
21628
21643
  const WarningContext = /*#__PURE__*/ React.createContext({});
21629
21644
  /**
21630
21645
  * This is a hook but we not named as `useWarning`
@@ -21648,7 +21663,7 @@ const WarningContext = /*#__PURE__*/ React.createContext({});
21648
21663
  console.warn('[antd] There exists deprecated usage in your code:', deprecatedWarnList);
21649
21664
  }
21650
21665
  } else {
21651
- process.env.NODE_ENV !== "production" ? warning(valid, component, message) : void 0;
21666
+ process.env.NODE_ENV !== "production" ? warning$1(valid, component, message) : void 0;
21652
21667
  }
21653
21668
  }
21654
21669
  };
@@ -23499,6 +23514,367 @@ const useZIndex = (componentType, customZIndex)=>{
23499
23514
  return result;
23500
23515
  };
23501
23516
 
23517
+ const genAlertTypeStyle = (bgColor, borderColor, iconColor, token, alertCls)=>({
23518
+ background: bgColor,
23519
+ border: `${unit(token.lineWidth)} ${token.lineType} ${borderColor}`,
23520
+ [`${alertCls}-icon`]: {
23521
+ color: iconColor
23522
+ }
23523
+ });
23524
+ const genBaseStyle$6 = (token)=>{
23525
+ const { componentCls, motionDurationSlow: duration, marginXS, marginSM, fontSize, fontSizeLG, lineHeight, borderRadiusLG: borderRadius, motionEaseInOutCirc, withDescriptionIconSize, colorText, colorTextHeading, withDescriptionPadding, defaultPadding } = token;
23526
+ return {
23527
+ [componentCls]: {
23528
+ ...resetComponent(token),
23529
+ position: 'relative',
23530
+ display: 'flex',
23531
+ alignItems: 'center',
23532
+ padding: defaultPadding,
23533
+ wordWrap: 'break-word',
23534
+ borderRadius,
23535
+ [`&${componentCls}-rtl`]: {
23536
+ direction: 'rtl'
23537
+ },
23538
+ [`${componentCls}-section`]: {
23539
+ flex: 1,
23540
+ minWidth: 0
23541
+ },
23542
+ [`${componentCls}-icon`]: {
23543
+ marginInlineEnd: marginXS,
23544
+ lineHeight: 0
23545
+ },
23546
+ '&-description': {
23547
+ display: 'none',
23548
+ fontSize,
23549
+ lineHeight
23550
+ },
23551
+ '&-title': {
23552
+ color: colorTextHeading
23553
+ },
23554
+ [`&${componentCls}-motion-leave`]: {
23555
+ overflow: 'hidden',
23556
+ opacity: 1,
23557
+ transition: [
23558
+ `max-height`,
23559
+ `opacity`,
23560
+ `padding-top`,
23561
+ `padding-bottom`,
23562
+ `margin-bottom`
23563
+ ].map((prop)=>`${prop} ${duration} ${motionEaseInOutCirc}`).join(', ')
23564
+ },
23565
+ [`&${componentCls}-motion-leave-active`]: {
23566
+ maxHeight: 0,
23567
+ marginBottom: '0 !important',
23568
+ paddingTop: 0,
23569
+ paddingBottom: 0,
23570
+ opacity: 0
23571
+ }
23572
+ },
23573
+ [`${componentCls}-with-description`]: {
23574
+ alignItems: 'flex-start',
23575
+ padding: withDescriptionPadding,
23576
+ [`${componentCls}-icon`]: {
23577
+ marginInlineEnd: marginSM,
23578
+ fontSize: withDescriptionIconSize,
23579
+ lineHeight: 0
23580
+ },
23581
+ [`${componentCls}-title`]: {
23582
+ display: 'block',
23583
+ marginBottom: marginXS,
23584
+ color: colorTextHeading,
23585
+ fontSize: fontSizeLG
23586
+ },
23587
+ [`${componentCls}-description`]: {
23588
+ display: 'block',
23589
+ color: colorText
23590
+ }
23591
+ },
23592
+ [`${componentCls}-banner`]: {
23593
+ marginBottom: 0,
23594
+ border: '0 !important',
23595
+ borderRadius: 0
23596
+ }
23597
+ };
23598
+ };
23599
+ const genTypeStyle = (token)=>{
23600
+ const { componentCls, colorSuccess, colorSuccessBorder, colorSuccessBg, colorWarning, colorWarningBorder, colorWarningBg, colorError, colorErrorBorder, colorErrorBg, colorInfo, colorInfoBorder, colorInfoBg } = token;
23601
+ return {
23602
+ [componentCls]: {
23603
+ '&-success': genAlertTypeStyle(colorSuccessBg, colorSuccessBorder, colorSuccess, token, componentCls),
23604
+ '&-info': genAlertTypeStyle(colorInfoBg, colorInfoBorder, colorInfo, token, componentCls),
23605
+ '&-warning': genAlertTypeStyle(colorWarningBg, colorWarningBorder, colorWarning, token, componentCls),
23606
+ '&-error': {
23607
+ ...genAlertTypeStyle(colorErrorBg, colorErrorBorder, colorError, token, componentCls),
23608
+ [`${componentCls}-description > pre`]: {
23609
+ margin: 0,
23610
+ padding: 0
23611
+ }
23612
+ }
23613
+ }
23614
+ };
23615
+ };
23616
+ const genActionStyle = (token)=>{
23617
+ const { componentCls, iconCls, motionDurationMid, marginXS, fontSizeIcon, colorIcon, colorIconHover } = token;
23618
+ return {
23619
+ [componentCls]: {
23620
+ '&-actions': {
23621
+ marginInlineStart: marginXS
23622
+ },
23623
+ [`${componentCls}-close-icon`]: {
23624
+ marginInlineStart: marginXS,
23625
+ padding: 0,
23626
+ overflow: 'hidden',
23627
+ fontSize: fontSizeIcon,
23628
+ lineHeight: unit(fontSizeIcon),
23629
+ backgroundColor: 'transparent',
23630
+ border: 'none',
23631
+ outline: 'none',
23632
+ cursor: 'pointer',
23633
+ [`${iconCls}-close`]: {
23634
+ color: colorIcon,
23635
+ transition: `color ${motionDurationMid}`,
23636
+ '&:hover': {
23637
+ color: colorIconHover
23638
+ }
23639
+ }
23640
+ },
23641
+ '&-close-text': {
23642
+ color: colorIcon,
23643
+ transition: `color ${motionDurationMid}`,
23644
+ '&:hover': {
23645
+ color: colorIconHover
23646
+ }
23647
+ }
23648
+ }
23649
+ };
23650
+ };
23651
+ const prepareComponentToken$n = (token)=>{
23652
+ const paddingHorizontal = 12; // Fixed value here.
23653
+ return {
23654
+ withDescriptionIconSize: token.fontSizeHeading3,
23655
+ defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
23656
+ withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`
23657
+ };
23658
+ };
23659
+ var useStyle$u = genStyleHooks('Alert', (token)=>[
23660
+ genBaseStyle$6(token),
23661
+ genTypeStyle(token),
23662
+ genActionStyle(token)
23663
+ ], prepareComponentToken$n);
23664
+
23665
+ const IconNode = (props)=>{
23666
+ const { icon, type, className, style, successIcon, infoIcon, warningIcon, errorIcon } = props;
23667
+ const iconMapFilled = {
23668
+ success: successIcon ?? /*#__PURE__*/ React.createElement(CheckCircleFilled, null),
23669
+ info: infoIcon ?? /*#__PURE__*/ React.createElement(InfoCircleFilled, null),
23670
+ error: errorIcon ?? /*#__PURE__*/ React.createElement(CloseCircleFilled, null),
23671
+ warning: warningIcon ?? /*#__PURE__*/ React.createElement(ExclamationCircleFilled, null)
23672
+ };
23673
+ return /*#__PURE__*/ React.createElement("span", {
23674
+ className: className,
23675
+ style: style
23676
+ }, icon ?? iconMapFilled[type]);
23677
+ };
23678
+ const CloseIconNode = (props)=>{
23679
+ const { isClosable, prefixCls, closeIcon, handleClose, ariaProps, className, style } = props;
23680
+ const mergedCloseIcon = closeIcon === true || closeIcon === undefined ? /*#__PURE__*/ React.createElement(CloseOutlined, null) : closeIcon;
23681
+ return isClosable ? /*#__PURE__*/ React.createElement("button", {
23682
+ type: "button",
23683
+ onClick: handleClose,
23684
+ className: clsx(`${prefixCls}-close-icon`, className),
23685
+ tabIndex: 0,
23686
+ style: style,
23687
+ ...ariaProps
23688
+ }, mergedCloseIcon) : null;
23689
+ };
23690
+ const Alert$1 = /*#__PURE__*/ React.forwardRef((props, ref)=>{
23691
+ const { description, prefixCls: customizePrefixCls, message, title, banner, className, rootClassName, style, onMouseEnter, onMouseLeave, onClick, afterClose, showIcon, closable, closeText, closeIcon, action, id, styles, classNames, ...otherProps } = props;
23692
+ const mergedTitle = title ?? message;
23693
+ const [closed, setClosed] = React.useState(false);
23694
+ if (process.env.NODE_ENV !== 'production') {
23695
+ const warning = devUseWarning('Alert');
23696
+ [
23697
+ [
23698
+ 'closeText',
23699
+ 'closable.closeIcon'
23700
+ ],
23701
+ [
23702
+ 'message',
23703
+ 'title'
23704
+ ]
23705
+ ].forEach(([deprecatedName, newName])=>{
23706
+ warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
23707
+ });
23708
+ }
23709
+ const internalRef = React.useRef(null);
23710
+ React.useImperativeHandle(ref, ()=>({
23711
+ nativeElement: internalRef.current
23712
+ }));
23713
+ const { getPrefixCls, direction, closable: contextClosable, closeIcon: contextCloseIcon, className: contextClassName, style: contextStyle, classNames: contextClassNames, styles: contextStyles, successIcon, infoIcon, warningIcon, errorIcon } = useComponentConfig('alert');
23714
+ const prefixCls = getPrefixCls('alert', customizePrefixCls);
23715
+ const [hashId, cssVarCls] = useStyle$u(prefixCls);
23716
+ const { onClose: closableOnClose, afterClose: closableAfterClose } = closable && typeof closable === 'object' ? closable : {};
23717
+ const handleClose = (e)=>{
23718
+ setClosed(true);
23719
+ (closableOnClose ?? props.onClose)?.(e);
23720
+ };
23721
+ const type = React.useMemo(()=>{
23722
+ if (props.type !== undefined) {
23723
+ return props.type;
23724
+ }
23725
+ // banner mode defaults to 'warning'
23726
+ return banner ? 'warning' : 'info';
23727
+ }, [
23728
+ props.type,
23729
+ banner
23730
+ ]);
23731
+ // closeable when closeText or closeIcon is assigned
23732
+ const isClosable = React.useMemo(()=>{
23733
+ if (typeof closable === 'object' && closable.closeIcon) {
23734
+ return true;
23735
+ }
23736
+ if (closeText) {
23737
+ return true;
23738
+ }
23739
+ if (typeof closable === 'boolean') {
23740
+ return closable;
23741
+ }
23742
+ // should be true when closeIcon is 0 or ''
23743
+ if (closeIcon !== false && isNonNullable(closeIcon)) {
23744
+ return true;
23745
+ }
23746
+ return !!contextClosable;
23747
+ }, [
23748
+ closeText,
23749
+ closeIcon,
23750
+ closable,
23751
+ contextClosable
23752
+ ]);
23753
+ // banner mode defaults to Icon
23754
+ const isShowIcon = banner && showIcon === undefined ? true : showIcon;
23755
+ // =========== Merged Props for Semantic ==========
23756
+ const mergedProps = {
23757
+ ...props,
23758
+ prefixCls,
23759
+ type,
23760
+ showIcon: isShowIcon,
23761
+ closable: isClosable
23762
+ };
23763
+ const [mergedClassNames, mergedStyles] = useMergeSemantic([
23764
+ contextClassNames,
23765
+ classNames
23766
+ ], [
23767
+ contextStyles,
23768
+ styles
23769
+ ], {
23770
+ props: mergedProps
23771
+ });
23772
+ const alertCls = clsx(prefixCls, `${prefixCls}-${type}`, {
23773
+ [`${prefixCls}-with-description`]: !!description,
23774
+ [`${prefixCls}-no-icon`]: !isShowIcon,
23775
+ [`${prefixCls}-banner`]: !!banner,
23776
+ [`${prefixCls}-rtl`]: direction === 'rtl'
23777
+ }, contextClassName, className, rootClassName, mergedClassNames.root, cssVarCls, hashId);
23778
+ const restProps = pickAttrs(otherProps, {
23779
+ aria: true,
23780
+ data: true
23781
+ });
23782
+ const mergedCloseIcon = React.useMemo(()=>{
23783
+ if (typeof closable === 'object' && closable.closeIcon) {
23784
+ return closable.closeIcon;
23785
+ }
23786
+ if (closeText) {
23787
+ return closeText;
23788
+ }
23789
+ if (closeIcon !== undefined) {
23790
+ return closeIcon;
23791
+ }
23792
+ if (typeof contextClosable === 'object' && contextClosable.closeIcon) {
23793
+ return contextClosable.closeIcon;
23794
+ }
23795
+ return contextCloseIcon;
23796
+ }, [
23797
+ closeIcon,
23798
+ closable,
23799
+ contextClosable,
23800
+ closeText,
23801
+ contextCloseIcon
23802
+ ]);
23803
+ const mergedAriaProps = React.useMemo(()=>{
23804
+ const merged = closable ?? contextClosable;
23805
+ if (typeof merged === 'object') {
23806
+ return pickAttrs(merged, {
23807
+ data: true,
23808
+ aria: true
23809
+ });
23810
+ }
23811
+ return {};
23812
+ }, [
23813
+ closable,
23814
+ contextClosable
23815
+ ]);
23816
+ return /*#__PURE__*/ React.createElement(CSSMotion, {
23817
+ visible: !closed,
23818
+ motionName: `${prefixCls}-motion`,
23819
+ motionAppear: false,
23820
+ motionEnter: false,
23821
+ onLeaveStart: (node)=>({
23822
+ maxHeight: node.offsetHeight
23823
+ }),
23824
+ onLeaveEnd: closableAfterClose ?? afterClose
23825
+ }, ({ className: motionClassName, style: motionStyle }, setRef)=>/*#__PURE__*/ React.createElement("div", {
23826
+ id: id,
23827
+ ref: composeRef(internalRef, setRef),
23828
+ "data-show": !closed,
23829
+ className: clsx(alertCls, motionClassName),
23830
+ style: {
23831
+ ...mergedStyles.root,
23832
+ ...contextStyle,
23833
+ ...style,
23834
+ ...motionStyle
23835
+ },
23836
+ onMouseEnter: onMouseEnter,
23837
+ onMouseLeave: onMouseLeave,
23838
+ onClick: onClick,
23839
+ role: "alert",
23840
+ ...restProps
23841
+ }, isShowIcon ? /*#__PURE__*/ React.createElement(IconNode, {
23842
+ className: clsx(`${prefixCls}-icon`, mergedClassNames.icon),
23843
+ style: mergedStyles.icon,
23844
+ description: description,
23845
+ icon: props.icon,
23846
+ prefixCls: prefixCls,
23847
+ type: type,
23848
+ successIcon: successIcon,
23849
+ infoIcon: infoIcon,
23850
+ warningIcon: warningIcon,
23851
+ errorIcon: errorIcon
23852
+ }) : null, /*#__PURE__*/ React.createElement("div", {
23853
+ className: clsx(`${prefixCls}-section`, mergedClassNames.section),
23854
+ style: mergedStyles.section
23855
+ }, mergedTitle ? /*#__PURE__*/ React.createElement("div", {
23856
+ className: clsx(`${prefixCls}-title`, mergedClassNames.title),
23857
+ style: mergedStyles.title
23858
+ }, mergedTitle) : null, description ? /*#__PURE__*/ React.createElement("div", {
23859
+ className: clsx(`${prefixCls}-description`, mergedClassNames.description),
23860
+ style: mergedStyles.description
23861
+ }, description) : null), action ? /*#__PURE__*/ React.createElement("div", {
23862
+ className: clsx(`${prefixCls}-actions`, mergedClassNames.actions),
23863
+ style: mergedStyles.actions
23864
+ }, action) : null, /*#__PURE__*/ React.createElement(CloseIconNode, {
23865
+ className: mergedClassNames.close,
23866
+ style: mergedStyles.close,
23867
+ isClosable: isClosable,
23868
+ prefixCls: prefixCls,
23869
+ closeIcon: mergedCloseIcon,
23870
+ handleClose: handleClose,
23871
+ ariaProps: mergedAriaProps
23872
+ })));
23873
+ });
23874
+ if (process.env.NODE_ENV !== 'production') {
23875
+ Alert$1.displayName = 'Alert';
23876
+ }
23877
+
23502
23878
  function _classCallCheck(a, n) {
23503
23879
  if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
23504
23880
  }
@@ -23540,6 +23916,110 @@ function _createClass(e, r, t) {
23540
23916
  }), e;
23541
23917
  }
23542
23918
 
23919
+ function _getPrototypeOf(t) {
23920
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function(t) {
23921
+ return t.__proto__ || Object.getPrototypeOf(t);
23922
+ }, _getPrototypeOf(t);
23923
+ }
23924
+
23925
+ function _isNativeReflectConstruct() {
23926
+ try {
23927
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
23928
+ } catch (t) {}
23929
+ return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
23930
+ return !!t;
23931
+ })();
23932
+ }
23933
+
23934
+ function _assertThisInitialized(e) {
23935
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
23936
+ return e;
23937
+ }
23938
+
23939
+ function _possibleConstructorReturn(t, e) {
23940
+ if (e && ("object" == _typeof(e) || "function" == typeof e)) return e;
23941
+ if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
23942
+ return _assertThisInitialized(t);
23943
+ }
23944
+
23945
+ function _callSuper(t, o, e) {
23946
+ return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
23947
+ }
23948
+
23949
+ function _setPrototypeOf(t, e) {
23950
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(t, e) {
23951
+ return t.__proto__ = e, t;
23952
+ }, _setPrototypeOf(t, e);
23953
+ }
23954
+
23955
+ function _inherits(t, e) {
23956
+ if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
23957
+ t.prototype = Object.create(e && e.prototype, {
23958
+ constructor: {
23959
+ value: t,
23960
+ writable: true,
23961
+ configurable: true
23962
+ }
23963
+ }), Object.defineProperty(t, "prototype", {
23964
+ writable: false
23965
+ }), e && _setPrototypeOf(t, e);
23966
+ }
23967
+
23968
+ let ErrorBoundary$1 = /*#__PURE__*/ function(_React$Component) {
23969
+ function ErrorBoundary() {
23970
+ var _this;
23971
+ _classCallCheck(this, ErrorBoundary);
23972
+ _this = _callSuper(this, ErrorBoundary, arguments);
23973
+ _this.state = {
23974
+ error: undefined,
23975
+ info: {
23976
+ componentStack: ''
23977
+ }
23978
+ };
23979
+ return _this;
23980
+ }
23981
+ _inherits(ErrorBoundary, _React$Component);
23982
+ return _createClass(ErrorBoundary, [
23983
+ {
23984
+ key: "componentDidCatch",
23985
+ value: function componentDidCatch(error, info) {
23986
+ this.setState({
23987
+ error,
23988
+ info
23989
+ });
23990
+ }
23991
+ },
23992
+ {
23993
+ key: "render",
23994
+ value: function render() {
23995
+ const { message, title, description, id, children } = this.props;
23996
+ const { error, info } = this.state;
23997
+ const mergedTitle = title ?? message;
23998
+ const componentStack = info?.componentStack || null;
23999
+ const errorMessage = typeof mergedTitle === 'undefined' ? (error || '').toString() : mergedTitle;
24000
+ const errorDescription = typeof description === 'undefined' ? componentStack : description;
24001
+ if (error) {
24002
+ return /*#__PURE__*/ React.createElement(Alert$1, {
24003
+ id: id,
24004
+ type: "error",
24005
+ title: errorMessage,
24006
+ description: /*#__PURE__*/ React.createElement("pre", {
24007
+ style: {
24008
+ fontSize: '0.9em',
24009
+ overflowX: 'auto'
24010
+ }
24011
+ }, errorDescription)
24012
+ });
24013
+ }
24014
+ return children;
24015
+ }
24016
+ }
24017
+ ]);
24018
+ }(React.Component);
24019
+
24020
+ const Alert = Alert$1;
24021
+ Alert.ErrorBoundary = ErrorBoundary$1;
24022
+
23543
24023
  function isWindow(obj) {
23544
24024
  return isNonNullable(obj) && obj === obj.window;
23545
24025
  }
@@ -23822,7 +24302,7 @@ var PropWarning$1 = process.env.NODE_ENV !== 'production' ? PropWarning : ()=>nu
23822
24302
  * theme register info here to help developer get warning info.
23823
24303
  */ let existThemeConfig = false;
23824
24304
  const warnContext = process.env.NODE_ENV !== 'production' ? (componentName)=>{
23825
- process.env.NODE_ENV !== "production" ? warning(!existThemeConfig, componentName, `Static function can not consume context like dynamic theme. Please use 'App' component instead.`) : void 0;
24305
+ process.env.NODE_ENV !== "production" ? warning$1(!existThemeConfig, componentName, `Static function can not consume context like dynamic theme. Please use 'App' component instead.`) : void 0;
23826
24306
  } : /* istanbul ignore next */ null;
23827
24307
  // These props is used by `useContext` directly in sub component
23828
24308
  const PASSED_PROPS = [
@@ -24138,7 +24618,7 @@ ConfigProvider.config = setGlobalConfig;
24138
24618
  ConfigProvider.useConfig = useConfig;
24139
24619
  Object.defineProperty(ConfigProvider, 'SizeContext', {
24140
24620
  get: ()=>{
24141
- process.env.NODE_ENV !== "production" ? warning(false, 'ConfigProvider', 'ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.') : void 0;
24621
+ process.env.NODE_ENV !== "production" ? warning$1(false, 'ConfigProvider', 'ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.') : void 0;
24142
24622
  return SizeContext;
24143
24623
  }
24144
24624
  });
@@ -46790,7 +47270,7 @@ const asyncCopy = async (text, isHtmlFormat)=>{
46790
47270
  };
46791
47271
  async function copy(text, config) {
46792
47272
  if (typeof text !== 'string') {
46793
- process.env.NODE_ENV !== "production" ? warning(false, 'The clipboard content must be of string type', '') : void 0;
47273
+ process.env.NODE_ENV !== "production" ? warning$1(false, 'The clipboard content must be of string type', '') : void 0;
46794
47274
  return false;
46795
47275
  }
46796
47276
  const isHtmlFormat = config?.format === 'text/html';
@@ -47579,7 +48059,7 @@ const Base = /*#__PURE__*/ React.forwardRef((props, ref)=>{
47579
48059
  }, node) : node, renderEllipsis(canEllipsis)))))));
47580
48060
  });
47581
48061
 
47582
- const Link = /*#__PURE__*/ React.forwardRef((props, ref)=>{
48062
+ const Link$1 = /*#__PURE__*/ React.forwardRef((props, ref)=>{
47583
48063
  const { ellipsis, rel, children, // @ts-expect-error: https://github.com/ant-design/ant-design/issues/26622
47584
48064
  navigate: _navigate, ...restProps } = props;
47585
48065
  if (process.env.NODE_ENV !== 'production') {
@@ -47655,7 +48135,7 @@ const Title$1 = /*#__PURE__*/ React.forwardRef((props, ref)=>{
47655
48135
 
47656
48136
  const Typography = Typography$1;
47657
48137
  Typography.Text = Text$1;
47658
- Typography.Link = Link;
48138
+ Typography.Link = Link$1;
47659
48139
  Typography.Title = Title$1;
47660
48140
  Typography.Paragraph = Paragraph;
47661
48141
 
@@ -49639,7 +50119,7 @@ const Timeline = ({ stamps, currentStep, onStepChange, onToggle })=>{
49639
50119
  };
49640
50120
 
49641
50121
  // src/primitive.tsx
49642
- function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
50122
+ function composeEventHandlers$1(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
49643
50123
  return function handleEvent(event) {
49644
50124
  originalEventHandler?.(event);
49645
50125
  if (checkForDefaultPrevented === false || !event.defaultPrevented) {
@@ -50152,9 +50632,9 @@ var DismissableLayer = React.forwardRef((props, forwardedRef)=>{
50152
50632
  pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
50153
50633
  ...props.style
50154
50634
  },
50155
- onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
50156
- onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
50157
- onPointerDownCapture: composeEventHandlers(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture)
50635
+ onFocusCapture: composeEventHandlers$1(props.onFocusCapture, focusOutside.onFocusCapture),
50636
+ onBlurCapture: composeEventHandlers$1(props.onBlurCapture, focusOutside.onBlurCapture),
50637
+ onPointerDownCapture: composeEventHandlers$1(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture)
50158
50638
  });
50159
50639
  });
50160
50640
  DismissableLayer.displayName = DISMISSABLE_LAYER_NAME;
@@ -50788,7 +51268,7 @@ var noScrollbarsClassName = 'with-scroll-bars-hidden';
50788
51268
  return ref.facade;
50789
51269
  }
50790
51270
 
50791
- var useIsomorphicLayoutEffect$1 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
51271
+ var useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
50792
51272
  var currentValues = new WeakMap();
50793
51273
  /**
50794
51274
  * Merges two or more refs together providing a single interface to set their value
@@ -50810,7 +51290,7 @@ var currentValues = new WeakMap();
50810
51290
  });
50811
51291
  });
50812
51292
  // handle refs changes - added or removed
50813
- useIsomorphicLayoutEffect$1(function() {
51293
+ useIsomorphicLayoutEffect$2(function() {
50814
51294
  var oldValue = currentValues.get(callbackRef);
50815
51295
  if (oldValue) {
50816
51296
  var prevRefs_1 = new Set(oldValue);
@@ -51699,7 +52179,7 @@ var DialogTrigger = React.forwardRef((props, forwardedRef)=>{
51699
52179
  "data-state": getState(context.open),
51700
52180
  ...triggerProps,
51701
52181
  ref: composedTriggerRef,
51702
- onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
52182
+ onClick: composeEventHandlers$1(props.onClick, context.onOpenToggle)
51703
52183
  });
51704
52184
  });
51705
52185
  DialogTrigger.displayName = TRIGGER_NAME;
@@ -51791,17 +52271,17 @@ var DialogContentModal = React.forwardRef((props, forwardedRef)=>{
51791
52271
  ref: composedRefs,
51792
52272
  trapFocus: context.open,
51793
52273
  disableOutsidePointerEvents: true,
51794
- onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event)=>{
52274
+ onCloseAutoFocus: composeEventHandlers$1(props.onCloseAutoFocus, (event)=>{
51795
52275
  event.preventDefault();
51796
52276
  context.triggerRef.current?.focus();
51797
52277
  }),
51798
- onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event)=>{
52278
+ onPointerDownOutside: composeEventHandlers$1(props.onPointerDownOutside, (event)=>{
51799
52279
  const originalEvent = event.detail.originalEvent;
51800
52280
  const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
51801
52281
  const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
51802
52282
  if (isRightClick) event.preventDefault();
51803
52283
  }),
51804
- onFocusOutside: composeEventHandlers(props.onFocusOutside, (event)=>event.preventDefault())
52284
+ onFocusOutside: composeEventHandlers$1(props.onFocusOutside, (event)=>event.preventDefault())
51805
52285
  });
51806
52286
  });
51807
52287
  var DialogContentNonModal = React.forwardRef((props, forwardedRef)=>{
@@ -51908,7 +52388,7 @@ var DialogClose = React.forwardRef((props, forwardedRef)=>{
51908
52388
  type: "button",
51909
52389
  ...closeProps,
51910
52390
  ref: forwardedRef,
51911
- onClick: composeEventHandlers(props.onClick, ()=>context.onOpenChange(false))
52391
+ onClick: composeEventHandlers$1(props.onClick, ()=>context.onOpenChange(false))
51912
52392
  });
51913
52393
  });
51914
52394
  DialogClose.displayName = CLOSE_NAME;
@@ -113501,6 +113981,12 @@ function dtoMetricToMetric(def) {
113501
113981
  if (idx !== undefined && idx >= 0) {
113502
113982
  aggregatedResults[evaluatorId][item.metric.name] = idx;
113503
113983
  }
113984
+ } else if ((isLLMResult(item) || isToolResult(item)) && "result_name" in item && typeof item.value === "number") {
113985
+ // Raw LLM/Tool results: aggregate by result_name (metric name) for comparison view
113986
+ const name = item.result_name;
113987
+ const arr = valuesByMetric.get(name) ?? [];
113988
+ arr.push(item.value);
113989
+ valuesByMetric.set(name, arr);
113504
113990
  }
113505
113991
  }
113506
113992
  // Compute mean across all values for each metric
@@ -113552,117 +114038,114 @@ function dtoMetricToMetric(def) {
113552
114038
  return "evaluator_results" in x && Array.isArray(x.evaluator_results);
113553
114039
  }
113554
114040
 
113555
- const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluationId, evaluations, onSourceChange, onTargetChange })=>{
113556
- const { isDarkMode } = useTheme$1();
114041
+ /** Returns set of "evaluatorId:metricName" for all metrics in the evaluation. */ function getMetricKeys(evaluation) {
114042
+ const keys = new Set();
114043
+ for (const evaluator of evaluation.evaluators){
114044
+ for (const metric of evaluator.metrics){
114045
+ keys.add(`${evaluator.evaluator_id}:${metric.name}`);
114046
+ }
114047
+ }
114048
+ return keys;
114049
+ }
114050
+ /**
114051
+ * Returns true if both evaluations have the same set of metrics
114052
+ * (evaluator_id + metric name) across all evaluators.
114053
+ */ function evaluationsHaveSameMetrics(a, b) {
114054
+ if (a == null || b == null) return false;
114055
+ const evalA = isEvaluationDto(a) ? transformEvaluation(a) : a;
114056
+ const evalB = isEvaluationDto(b) ? transformEvaluation(b) : b;
114057
+ const keysA = getMetricKeys(evalA);
114058
+ const keysB = getMetricKeys(evalB);
114059
+ if (keysA.size !== keysB.size) return false;
114060
+ for (const key of keysA){
114061
+ if (!keysB.has(key)) return false;
114062
+ }
114063
+ return true;
114064
+ }
114065
+
114066
+ function formatMetricValue(evaluation, evaluatorId, metricName, metricType, options) {
114067
+ const evaluatorResults = evaluation.results[evaluatorId];
114068
+ const value = evaluatorResults?.[metricName];
114069
+ if (value === undefined) return "-";
114070
+ if (metricType === "Categorical" && options?.length) {
114071
+ const index = Math.round(value);
114072
+ return options[index] || value.toString();
114073
+ }
114074
+ if (metricType === "Continuous") {
114075
+ return value.toFixed(1);
114076
+ }
114077
+ return value.toString();
114078
+ }
114079
+ function getMetricValue(evaluation, evaluatorId, metricName) {
114080
+ const evaluatorResults = evaluation.results[evaluatorId];
114081
+ return evaluatorResults?.[metricName];
114082
+ }
114083
+ const EvaluationsCompareView = ({ evaluations, evaluationId1, evaluationId2, onEvaluationId1Change, onEvaluationId2Change, loading = false, showEvaluationComparisonDropdowns = false, backHref })=>{
114084
+ const { theme } = useTheme$1();
113557
114085
  const normalizedEvaluations = React__default.useMemo(()=>evaluations.map((e)=>isEvaluationDto(e) ? transformEvaluation(e) : e), [
113558
114086
  evaluations
113559
114087
  ]);
113560
- // Handler for copying evaluation IDs to clipboard
113561
- const handleCopyIds = async ()=>{
113562
- if (!sourceEvaluationId || !targetEvaluationId) {
113563
- staticMethods.error("No evaluation IDs available");
113564
- return;
113565
- }
113566
- try {
113567
- const idsText = `Source: ${sourceEvaluationId}\nTarget: ${targetEvaluationId}`;
113568
- await navigator.clipboard.writeText(idsText);
113569
- staticMethods.success("Evaluation IDs copied to clipboard");
113570
- } catch (err) {
113571
- staticMethods.error("Failed to copy evaluation IDs");
113572
- }
113573
- };
113574
- // Handler for sharing evaluation comparison
113575
- const handleShare = async ()=>{
113576
- if (!sourceEvaluationId || !targetEvaluationId) {
113577
- staticMethods.error("No evaluations available to share");
113578
- return;
113579
- }
113580
- const shareUrl = `${window.location.origin}${window.location.pathname}#/evaluations/compare?source=${sourceEvaluationId}&target=${targetEvaluationId}`;
113581
- // Try Web Share API if available
113582
- if (navigator.share) {
113583
- try {
113584
- await navigator.share({
113585
- title: "Evaluation Comparison",
113586
- text: `Compare evaluations: ${sourceEvaluationId} vs ${targetEvaluationId}`,
113587
- url: shareUrl
114088
+ const evaluation1 = normalizedEvaluations.find((e)=>e.evaluation_id === evaluationId1);
114089
+ const evaluation2 = normalizedEvaluations.find((e)=>e.evaluation_id === evaluationId2);
114090
+ const metricsMismatch = React__default.useMemo(()=>!evaluationsHaveSameMetrics(evaluation1, evaluation2), [
114091
+ evaluation1,
114092
+ evaluation2
114093
+ ]);
114094
+ const comparisonData = React__default.useMemo(()=>{
114095
+ if (!evaluation1 || !evaluation2) return [];
114096
+ const rows = [];
114097
+ // Build evaluator lookup by id for evaluation2 (to match evaluators between evaluations)
114098
+ const eval2EvaluatorsById = new Map(evaluation2.evaluators.map((e)=>[
114099
+ e.evaluator_id,
114100
+ e
114101
+ ]));
114102
+ // Iterate over ALL evaluators in evaluation1 (LLM, Tool, Judge, etc.)
114103
+ for (const evaluator1 of evaluation1.evaluators){
114104
+ const evaluator2 = eval2EvaluatorsById.get(evaluator1.evaluator_id);
114105
+ if (!evaluator2) continue;
114106
+ const allMetricNames = new Set();
114107
+ evaluator1.metrics.forEach((m)=>allMetricNames.add(m.name));
114108
+ evaluator2.metrics.forEach((m)=>allMetricNames.add(m.name));
114109
+ for (const metricName of allMetricNames){
114110
+ const metric1 = evaluator1.metrics.find((m)=>m.name === metricName);
114111
+ const metric2 = evaluator2.metrics.find((m)=>m.name === metricName);
114112
+ const metricType = metric1?.type || metric2?.type || "Continuous";
114113
+ const options = metric1?.type === "Categorical" ? metric1.options : metric2?.type === "Categorical" ? metric2.options : undefined;
114114
+ const value1 = getMetricValue(evaluation1, evaluator1.evaluator_id, metricName);
114115
+ const value2 = getMetricValue(evaluation2, evaluator2.evaluator_id, metricName);
114116
+ const formatted1 = formatMetricValue(evaluation1, evaluator1.evaluator_id, metricName, metricType, options);
114117
+ const formatted2 = formatMetricValue(evaluation2, evaluator2.evaluator_id, metricName, metricType, options);
114118
+ let difference;
114119
+ if (metricType === "Continuous" && value1 !== undefined && value2 !== undefined) {
114120
+ difference = value2 - value1;
114121
+ }
114122
+ rows.push({
114123
+ metricName,
114124
+ evaluatorName: evaluator1.name,
114125
+ metricType,
114126
+ value1,
114127
+ value2,
114128
+ formatted1,
114129
+ formatted2,
114130
+ difference,
114131
+ rowKey: `${evaluator1.evaluator_id}:${metricName}`
113588
114132
  });
113589
- return;
113590
- } catch (err) {
113591
- // User cancelled or error occurred, fall back to clipboard
113592
114133
  }
113593
114134
  }
113594
- // Fall back to copying URL to clipboard
113595
- try {
113596
- await navigator.clipboard.writeText(shareUrl);
113597
- staticMethods.success("Share link copied to clipboard");
113598
- } catch (err) {
113599
- staticMethods.error("Failed to copy share link");
113600
- }
113601
- };
113602
- // Find the evaluations
113603
- const sourceEvaluation = normalizedEvaluations.find((e)=>e.evaluation_id === sourceEvaluationId);
113604
- const targetEvaluation = normalizedEvaluations.find((e)=>e.evaluation_id === targetEvaluationId);
113605
- // Helper to format metric value (same logic as evaluations.tsx)
113606
- const formatMetricValue = (evaluation, metricName)=>{
113607
- const evaluator = evaluation.evaluators[0];
113608
- const metric = evaluator?.metrics.find((m)=>m.name === metricName);
113609
- const evaluatorId = evaluator?.evaluator_id || "";
113610
- const evaluatorResults = evaluation.results[evaluatorId];
113611
- const value = evaluatorResults?.[metricName];
113612
- if (value === undefined) return "-";
113613
- if (metric?.type === "Categorical" && metric.options) {
113614
- const index = Math.round(value);
113615
- return metric.options[index] || value.toString();
113616
- }
113617
- if (metric?.type === "Continuous") {
113618
- return value.toFixed(1);
113619
- }
113620
- return value.toString();
113621
- };
113622
- // Get metric value as number for comparison
113623
- const getMetricValue = (evaluation, metricName)=>{
113624
- const evaluator = evaluation.evaluators[0];
113625
- const evaluatorId = evaluator?.evaluator_id || "";
113626
- const evaluatorResults = evaluation.results[evaluatorId];
113627
- return evaluatorResults?.[metricName];
113628
- };
113629
- // Build comparison data
113630
- const comparisonData = React__default.useMemo(()=>{
113631
- if (!sourceEvaluation || !targetEvaluation) return [];
113632
- const sourceEvaluator = sourceEvaluation.evaluators[0];
113633
- const targetEvaluator = targetEvaluation.evaluators[0];
113634
- if (!sourceEvaluator || !targetEvaluator) return [];
113635
- // Get all unique metric names
113636
- const allMetricNames = new Set();
113637
- sourceEvaluator.metrics.forEach((m)=>allMetricNames.add(m.name));
113638
- targetEvaluator.metrics.forEach((m)=>allMetricNames.add(m.name));
113639
- return Array.from(allMetricNames).map((metricName)=>{
113640
- const sourceMetric = sourceEvaluator.metrics.find((m)=>m.name === metricName);
113641
- const targetMetric = targetEvaluator.metrics.find((m)=>m.name === metricName);
113642
- const metricType = sourceMetric?.type || targetMetric?.type || "Continuous";
113643
- const sourceValue = getMetricValue(sourceEvaluation, metricName);
113644
- const targetValue = getMetricValue(targetEvaluation, metricName);
113645
- const sourceFormatted = formatMetricValue(sourceEvaluation, metricName);
113646
- const targetFormatted = formatMetricValue(targetEvaluation, metricName);
113647
- let difference;
113648
- if (metricType === "Continuous" && sourceValue !== undefined && targetValue !== undefined) {
113649
- difference = targetValue - sourceValue;
113650
- }
113651
- return {
113652
- metricName,
113653
- metricType,
113654
- sourceValue,
113655
- targetValue,
113656
- sourceFormatted,
113657
- targetFormatted,
113658
- difference
113659
- };
114135
+ return rows;
114136
+ }, [
114137
+ evaluation1,
114138
+ evaluation2
114139
+ ]);
114140
+ const allValuesIdentical = React__default.useMemo(()=>{
114141
+ if (comparisonData.length === 0) return false;
114142
+ return comparisonData.every((r)=>{
114143
+ if (r.metricType === "Continuous" && r.difference !== undefined) return r.difference === 0;
114144
+ return r.formatted1 === r.formatted2;
113660
114145
  });
113661
114146
  }, [
113662
- sourceEvaluation,
113663
- targetEvaluation
114147
+ comparisonData
113664
114148
  ]);
113665
- // Prepare options for dropdowns
113666
114149
  const evaluationOptions = React__default.useMemo(()=>{
113667
114150
  return normalizedEvaluations.map((evaluation)=>({
113668
114151
  label: `${evaluation.name || "Unnamed Evaluation"} (${evaluation.agent_name})`,
@@ -113679,54 +114162,261 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113679
114162
  width: 200,
113680
114163
  render: (name, record)=>/*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("div", {
113681
114164
  style: {
113682
- fontWeight: 500
114165
+ fontWeight: theme.fontWeight.medium
113683
114166
  }
113684
114167
  }, name), /*#__PURE__*/ React__default.createElement("div", {
113685
114168
  style: {
113686
- fontSize: "12px",
113687
- color: isDarkMode ? "#8c8c8c" : "#595959"
114169
+ fontSize: theme.fontSize.xs,
114170
+ color: theme.colors.mutedForeground
113688
114171
  }
113689
- }, record.metricType))
114172
+ }, record.evaluatorName, " • ", record.metricType))
113690
114173
  },
113691
114174
  {
113692
- title: sourceEvaluation?.name || "Source",
113693
- key: "source",
114175
+ title: evaluation1?.name || "Evaluation 1",
114176
+ key: "evaluation1",
113694
114177
  width: 150,
113695
114178
  render: (_, record)=>/*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement(Tag, {
113696
114179
  color: "blue"
113697
- }, record.sourceFormatted))
114180
+ }, record.formatted1))
113698
114181
  },
113699
114182
  {
113700
- title: targetEvaluation?.name || "Target",
113701
- key: "target",
114183
+ title: evaluation2?.name || "Evaluation 2",
114184
+ key: "evaluation2",
113702
114185
  width: 150,
113703
114186
  render: (_, record)=>/*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement(Tag, {
113704
114187
  color: "green"
113705
- }, record.targetFormatted))
114188
+ }, record.formatted2))
113706
114189
  },
113707
114190
  {
113708
114191
  title: "Difference",
113709
114192
  key: "difference",
113710
114193
  width: 120,
113711
114194
  render: (_, record)=>{
113712
- if (record.difference === undefined) return "-";
113713
- const isPositive = record.difference > 0;
113714
- const isNegative = record.difference < 0;
113715
- return /*#__PURE__*/ React__default.createElement(Tag, {
113716
- color: isPositive ? "green" : isNegative ? "red" : "default"
113717
- }, isPositive ? "+" : "", record.difference.toFixed(1));
114195
+ if (record.difference !== undefined) {
114196
+ const isPositive = record.difference > 0;
114197
+ const isNegative = record.difference < 0;
114198
+ return /*#__PURE__*/ React__default.createElement(Tag, {
114199
+ color: isPositive ? "green" : isNegative ? "red" : "default"
114200
+ }, isPositive ? "+" : "", record.difference.toFixed(1));
114201
+ }
114202
+ // Categorical: show "Different" when values differ
114203
+ if (record.formatted1 !== record.formatted2) {
114204
+ return /*#__PURE__*/ React__default.createElement(Tag, {
114205
+ color: "orange"
114206
+ }, "Different");
114207
+ }
114208
+ return "-";
113718
114209
  }
113719
114210
  }
113720
114211
  ];
113721
- const extraButtonsIconSize = 24;
114212
+ const evaluation1Label = evaluation1 ? `${evaluation1.name || "Unnamed Evaluation"} (${evaluation1.agent_name})` : "Select evaluation 1";
114213
+ const evaluation2Label = evaluation2 ? `${evaluation2.name || "Unnamed Evaluation"} (${evaluation2.agent_name})` : "Select evaluation 2";
114214
+ return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, backHref && /*#__PURE__*/ React__default.createElement("a", {
114215
+ href: backHref,
114216
+ style: {
114217
+ display: "inline-flex",
114218
+ alignItems: "center",
114219
+ gap: 6,
114220
+ marginBottom: 24,
114221
+ color: theme.colors.mutedForeground,
114222
+ textDecoration: "none",
114223
+ fontSize: 14
114224
+ }
114225
+ }, /*#__PURE__*/ React__default.createElement(ArrowLeft, {
114226
+ size: 16
114227
+ }), "Back to Evaluations"), /*#__PURE__*/ React__default.createElement("div", {
114228
+ style: {
114229
+ marginBottom: theme.spacing.md,
114230
+ color: theme.colors.mutedForeground
114231
+ }
114232
+ }, showEvaluationComparisonDropdowns ? "Select two evaluations to compare their metrics" : /*#__PURE__*/ React__default.createElement("div", {
114233
+ style: {
114234
+ display: "flex",
114235
+ alignItems: "center",
114236
+ gap: theme.spacing.sm,
114237
+ flexWrap: "wrap"
114238
+ }
114239
+ }, /*#__PURE__*/ React__default.createElement("span", null, /*#__PURE__*/ React__default.createElement("strong", null, "Evaluation 1:"), " ", evaluation1Label), /*#__PURE__*/ React__default.createElement("span", {
114240
+ style: {
114241
+ color: theme.colors.border
114242
+ }
114243
+ }, "•"), /*#__PURE__*/ React__default.createElement("span", null, /*#__PURE__*/ React__default.createElement("strong", null, "Evaluation 2:"), " ", evaluation2Label))), showEvaluationComparisonDropdowns && /*#__PURE__*/ React__default.createElement("div", {
114244
+ style: {
114245
+ marginBottom: theme.spacing.lg
114246
+ }
114247
+ }, /*#__PURE__*/ React__default.createElement(Space, {
114248
+ size: "middle",
114249
+ style: {
114250
+ width: "100%"
114251
+ }
114252
+ }, /*#__PURE__*/ React__default.createElement("div", {
114253
+ style: {
114254
+ flex: 1
114255
+ }
114256
+ }, /*#__PURE__*/ React__default.createElement("label", {
114257
+ style: {
114258
+ display: "block",
114259
+ marginBottom: theme.spacing.sm,
114260
+ fontWeight: theme.fontWeight.medium,
114261
+ color: theme.colors.foreground
114262
+ }
114263
+ }, "Evaluation 1"), /*#__PURE__*/ React__default.createElement(Select, {
114264
+ style: {
114265
+ width: "100%"
114266
+ },
114267
+ placeholder: "Select evaluation 1",
114268
+ value: evaluationId1,
114269
+ onChange: (value)=>onEvaluationId1Change(value),
114270
+ options: evaluationOptions,
114271
+ showSearch: true,
114272
+ loading: loading,
114273
+ filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
114274
+ })), /*#__PURE__*/ React__default.createElement("div", {
114275
+ style: {
114276
+ flex: 1
114277
+ }
114278
+ }, /*#__PURE__*/ React__default.createElement("label", {
114279
+ style: {
114280
+ display: "block",
114281
+ marginBottom: theme.spacing.sm,
114282
+ fontWeight: theme.fontWeight.medium,
114283
+ color: theme.colors.foreground
114284
+ }
114285
+ }, "Evaluation 2"), /*#__PURE__*/ React__default.createElement(Select, {
114286
+ style: {
114287
+ width: "100%"
114288
+ },
114289
+ placeholder: "Select evaluation 2",
114290
+ value: evaluationId2,
114291
+ onChange: (value)=>onEvaluationId2Change(value),
114292
+ options: evaluationOptions,
114293
+ showSearch: true,
114294
+ loading: loading,
114295
+ filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
114296
+ })))), !evaluation1 || !evaluation2 ? /*#__PURE__*/ React__default.createElement("div", {
114297
+ style: {
114298
+ textAlign: "center",
114299
+ padding: theme.spacing["2xl"],
114300
+ color: theme.colors.mutedForeground
114301
+ }
114302
+ }, /*#__PURE__*/ React__default.createElement("p", null, "Please select both evaluations to compare")) : metricsMismatch ? /*#__PURE__*/ React__default.createElement(Alert, {
114303
+ type: "error",
114304
+ showIcon: true,
114305
+ message: "Cannot compare evaluations",
114306
+ description: "The two evaluations must have the same metrics in order to be diffed. Please select evaluations that share the same metric set."
114307
+ }) : /*#__PURE__*/ React__default.createElement("div", null, allValuesIdentical && /*#__PURE__*/ React__default.createElement(Alert, {
114308
+ type: "info",
114309
+ showIcon: true,
114310
+ message: "Evaluations are identical",
114311
+ description: "All metric values match between the two evaluations.",
114312
+ style: {
114313
+ marginBottom: theme.spacing.lg
114314
+ }
114315
+ }), /*#__PURE__*/ React__default.createElement("div", {
114316
+ style: {
114317
+ display: "grid",
114318
+ gridTemplateColumns: "1fr 1fr",
114319
+ gap: theme.spacing.lg,
114320
+ marginBottom: theme.spacing.lg,
114321
+ padding: theme.spacing.md,
114322
+ borderRadius: theme.borderRadius.lg,
114323
+ border: `1px solid ${theme.colors.border}`,
114324
+ backgroundColor: theme.colors.muted
114325
+ }
114326
+ }, /*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("h3", {
114327
+ style: {
114328
+ margin: `0 0 ${theme.spacing.sm} 0`,
114329
+ fontSize: theme.fontSize.base,
114330
+ fontWeight: theme.fontWeight.semibold
114331
+ }
114332
+ }, "Evaluation 1: ", evaluation1.name || "Unnamed Evaluation"), /*#__PURE__*/ React__default.createElement("div", {
114333
+ style: {
114334
+ fontSize: theme.fontSize.sm,
114335
+ color: theme.colors.mutedForeground
114336
+ }
114337
+ }, /*#__PURE__*/ React__default.createElement("div", null, "Agent: ", evaluation1.agent_name), /*#__PURE__*/ React__default.createElement("div", null, "Runs: ", evaluation1.runs.length), /*#__PURE__*/ React__default.createElement("div", null, "Created: ", moment(evaluation1.created_at).format("YYYY-MM-DD HH:mm:ss")))), /*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("h3", {
114338
+ style: {
114339
+ margin: `0 0 ${theme.spacing.sm} 0`,
114340
+ fontSize: theme.fontSize.base,
114341
+ fontWeight: theme.fontWeight.semibold
114342
+ }
114343
+ }, "Evaluation 2: ", evaluation2.name || "Unnamed Evaluation"), /*#__PURE__*/ React__default.createElement("div", {
114344
+ style: {
114345
+ fontSize: theme.fontSize.sm,
114346
+ color: theme.colors.mutedForeground
114347
+ }
114348
+ }, /*#__PURE__*/ React__default.createElement("div", null, "Agent: ", evaluation2.agent_name), /*#__PURE__*/ React__default.createElement("div", null, "Runs: ", evaluation2.runs.length), /*#__PURE__*/ React__default.createElement("div", null, "Created: ", moment(evaluation2.created_at).format("YYYY-MM-DD HH:mm:ss"))))), /*#__PURE__*/ React__default.createElement("h3", {
114349
+ style: {
114350
+ margin: `0 0 ${theme.spacing.md} 0`,
114351
+ fontSize: theme.fontSize.lg,
114352
+ fontWeight: theme.fontWeight.semibold
114353
+ }
114354
+ }, "Metrics Comparison"), /*#__PURE__*/ React__default.createElement(ForwardTable, {
114355
+ columns: comparisonColumns,
114356
+ dataSource: comparisonData,
114357
+ rowKey: "rowKey",
114358
+ pagination: false,
114359
+ style: {
114360
+ background: theme.colors.card
114361
+ },
114362
+ rowClassName: (record)=>{
114363
+ const hasDiff = record.metricType === "Continuous" ? record.difference !== undefined && record.difference !== 0 : record.formatted1 !== record.formatted2;
114364
+ return hasDiff ? "evaluations-compare-diff-row" : "";
114365
+ }
114366
+ })));
114367
+ };
114368
+
114369
+ const extraButtonsIconSize = 24;
114370
+ const EvaluationsCompareDrawer = ({ open, onClose, evaluationId1, evaluationId2, evaluations, onEvaluationId1Change, onEvaluationId2Change })=>{
114371
+ const handleCopyIds = async ()=>{
114372
+ if (!evaluationId1 || !evaluationId2) {
114373
+ staticMethods.error("No evaluation IDs available");
114374
+ return;
114375
+ }
114376
+ try {
114377
+ const idsText = `Evaluation 1: ${evaluationId1}\nEvaluation 2: ${evaluationId2}`;
114378
+ await navigator.clipboard.writeText(idsText);
114379
+ staticMethods.success("Evaluation IDs copied to clipboard");
114380
+ } catch (err) {
114381
+ staticMethods.error("Failed to copy evaluation IDs");
114382
+ }
114383
+ };
114384
+ const handleShare = async ()=>{
114385
+ if (!evaluationId1 || !evaluationId2) {
114386
+ staticMethods.error("No evaluations available to share");
114387
+ return;
114388
+ }
114389
+ const shareUrl = `${window.location.origin}${window.location.pathname}#/evaluations?compare=${evaluationId1},${evaluationId2}`;
114390
+ if (navigator.share) {
114391
+ try {
114392
+ await navigator.share({
114393
+ title: "Evaluation Comparison",
114394
+ text: `Compare evaluations: ${evaluationId1} vs ${evaluationId2}`,
114395
+ url: shareUrl
114396
+ });
114397
+ return;
114398
+ } catch (err) {
114399
+ // User cancelled or error occurred, fall back to clipboard
114400
+ }
114401
+ }
114402
+ try {
114403
+ await navigator.clipboard.writeText(shareUrl);
114404
+ staticMethods.success("Share link copied to clipboard");
114405
+ } catch (err) {
114406
+ staticMethods.error("Failed to copy share link");
114407
+ }
114408
+ };
113722
114409
  return /*#__PURE__*/ React__default.createElement(Drawer$2, {
113723
114410
  title: "Compare Evaluations",
113724
114411
  placement: "right",
113725
114412
  size: "60%",
113726
114413
  open: open,
113727
114414
  onClose: onClose,
113728
- extra: /*#__PURE__*/ React__default.createElement(Space, {
113729
- size: "middle"
114415
+ extra: /*#__PURE__*/ React__default.createElement("div", {
114416
+ style: {
114417
+ display: "flex",
114418
+ gap: 8
114419
+ }
113730
114420
  }, /*#__PURE__*/ React__default.createElement(Tooltip, {
113731
114421
  title: "Copy IDs to Clipboard"
113732
114422
  }, /*#__PURE__*/ React__default.createElement(Button$1, {
@@ -113735,7 +114425,7 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113735
114425
  size: extraButtonsIconSize
113736
114426
  }),
113737
114427
  onClick: handleCopyIds,
113738
- disabled: !sourceEvaluationId || !targetEvaluationId
114428
+ disabled: !evaluationId1 || !evaluationId2
113739
114429
  })), /*#__PURE__*/ React__default.createElement(Tooltip, {
113740
114430
  title: "Share"
113741
114431
  }, /*#__PURE__*/ React__default.createElement(Button$1, {
@@ -113744,123 +114434,21 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113744
114434
  size: extraButtonsIconSize
113745
114435
  }),
113746
114436
  onClick: handleShare,
113747
- disabled: !sourceEvaluationId || !targetEvaluationId
114437
+ disabled: !evaluationId1 || !evaluationId2
113748
114438
  }))),
113749
114439
  styles: {
113750
114440
  body: {
113751
114441
  padding: "24px"
113752
114442
  }
113753
114443
  }
113754
- }, /*#__PURE__*/ React__default.createElement("div", {
113755
- style: {
113756
- marginBottom: "16px",
113757
- color: isDarkMode ? "#8c8c8c" : "#595959"
113758
- }
113759
- }, "Select two evaluations to compare their metrics"), /*#__PURE__*/ React__default.createElement("div", {
113760
- style: {
113761
- marginBottom: "24px"
113762
- }
113763
- }, /*#__PURE__*/ React__default.createElement(Space, {
113764
- size: "middle",
113765
- style: {
113766
- width: "100%"
113767
- }
113768
- }, /*#__PURE__*/ React__default.createElement("div", {
113769
- style: {
113770
- flex: 1
113771
- }
113772
- }, /*#__PURE__*/ React__default.createElement("label", {
113773
- style: {
113774
- display: "block",
113775
- marginBottom: "8px",
113776
- fontWeight: 500,
113777
- color: isDarkMode ? "#e5e7eb" : "#1f2937"
113778
- }
113779
- }, "Source Evaluation"), /*#__PURE__*/ React__default.createElement(Select, {
113780
- style: {
113781
- width: "100%"
113782
- },
113783
- placeholder: "Select source evaluation",
113784
- value: sourceEvaluationId,
113785
- onChange: (value)=>onSourceChange(value),
113786
- options: evaluationOptions,
113787
- showSearch: true,
113788
- filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
113789
- })), /*#__PURE__*/ React__default.createElement("div", {
113790
- style: {
113791
- flex: 1
113792
- }
113793
- }, /*#__PURE__*/ React__default.createElement("label", {
113794
- style: {
113795
- display: "block",
113796
- marginBottom: "8px",
113797
- fontWeight: 500,
113798
- color: isDarkMode ? "#e5e7eb" : "#1f2937"
113799
- }
113800
- }, "Target Evaluation"), /*#__PURE__*/ React__default.createElement(Select, {
113801
- style: {
113802
- width: "100%"
113803
- },
113804
- placeholder: "Select target evaluation",
113805
- value: targetEvaluationId,
113806
- onChange: (value)=>onTargetChange(value),
113807
- options: evaluationOptions,
113808
- showSearch: true,
113809
- filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
113810
- })))), !sourceEvaluation || !targetEvaluation ? /*#__PURE__*/ React__default.createElement("div", {
113811
- style: {
113812
- textAlign: "center",
113813
- padding: "48px",
113814
- color: isDarkMode ? "#8c8c8c" : "#595959"
113815
- }
113816
- }, /*#__PURE__*/ React__default.createElement("p", null, "Please select both source and target evaluations to compare")) : /*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("div", {
113817
- style: {
113818
- display: "grid",
113819
- gridTemplateColumns: "1fr 1fr",
113820
- gap: "24px",
113821
- marginBottom: "24px",
113822
- padding: "16px",
113823
- borderRadius: "8px",
113824
- border: `1px solid ${isDarkMode ? "#2d2d2d" : "#e5e7eb"}`,
113825
- backgroundColor: isDarkMode ? "#1a1a1a" : "#f9fafb"
113826
- }
113827
- }, /*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("h3", {
113828
- style: {
113829
- margin: "0 0 12px 0",
113830
- fontSize: "16px",
113831
- fontWeight: 600
113832
- }
113833
- }, "Source: ", sourceEvaluation.name || "Unnamed Evaluation"), /*#__PURE__*/ React__default.createElement("div", {
113834
- style: {
113835
- fontSize: "14px",
113836
- color: isDarkMode ? "#a3a3a3" : "#6b7280"
113837
- }
113838
- }, /*#__PURE__*/ React__default.createElement("div", null, "Agent: ", sourceEvaluation.agent_name), /*#__PURE__*/ React__default.createElement("div", null, "Runs: ", sourceEvaluation.runs.length), /*#__PURE__*/ React__default.createElement("div", null, "Created: ", moment(sourceEvaluation.created_at).format("YYYY-MM-DD HH:mm:ss")))), /*#__PURE__*/ React__default.createElement("div", null, /*#__PURE__*/ React__default.createElement("h3", {
113839
- style: {
113840
- margin: "0 0 12px 0",
113841
- fontSize: "16px",
113842
- fontWeight: 600
113843
- }
113844
- }, "Target: ", targetEvaluation.name || "Unnamed Evaluation"), /*#__PURE__*/ React__default.createElement("div", {
113845
- style: {
113846
- fontSize: "14px",
113847
- color: isDarkMode ? "#a3a3a3" : "#6b7280"
113848
- }
113849
- }, /*#__PURE__*/ React__default.createElement("div", null, "Agent: ", targetEvaluation.agent_name), /*#__PURE__*/ React__default.createElement("div", null, "Runs: ", targetEvaluation.runs.length), /*#__PURE__*/ React__default.createElement("div", null, "Created: ", moment(targetEvaluation.created_at).format("YYYY-MM-DD HH:mm:ss"))))), /*#__PURE__*/ React__default.createElement("h3", {
113850
- style: {
113851
- margin: "0 0 16px 0",
113852
- fontSize: "18px",
113853
- fontWeight: 600
113854
- }
113855
- }, "Metrics Comparison"), /*#__PURE__*/ React__default.createElement(ForwardTable, {
113856
- columns: comparisonColumns,
113857
- dataSource: comparisonData,
113858
- rowKey: "metricName",
113859
- pagination: false,
113860
- style: {
113861
- background: isDarkMode ? "#141414" : "#fff"
113862
- }
113863
- })));
114444
+ }, /*#__PURE__*/ React__default.createElement(EvaluationsCompareView, {
114445
+ evaluations: evaluations,
114446
+ evaluationId1: evaluationId1,
114447
+ evaluationId2: evaluationId2,
114448
+ onEvaluationId1Change: onEvaluationId1Change,
114449
+ onEvaluationId2Change: onEvaluationId2Change,
114450
+ showEvaluationComparisonDropdowns: false
114451
+ }));
113864
114452
  };
113865
114453
 
113866
114454
  const defaultGetEvaluatorResultsHref = (evaluationId, evaluatorId)=>`#/evaluations/${evaluationId}/results/${evaluatorId}`;
@@ -114094,13 +114682,23 @@ const EvaluationDetailsDrawer = ({ evaluation, open, onClose, getEvaluatorResult
114094
114682
  })))));
114095
114683
  };
114096
114684
 
114097
- const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefresh, onRowClick, onCompare, showFilters = true, showCompare = true, emptyMessage, title })=>{
114685
+ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefresh, onRowClick, onCompare, compareIdsFromUrl, onCompareUrlChange, showFilters = true, showCompare = true, emptyMessage, title })=>{
114098
114686
  const { theme } = useTheme$1();
114099
114687
  const [selectedAgents, setSelectedAgents] = useState([]);
114100
114688
  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
114101
114689
  const [compareDrawerOpen, setCompareDrawerOpen] = useState(false);
114102
- const [sourceEvaluationId, setSourceEvaluationId] = useState(null);
114103
- const [targetEvaluationId, setTargetEvaluationId] = useState(null);
114690
+ const [evaluationId1, setEvaluationId1] = useState(null);
114691
+ const [evaluationId2, setEvaluationId2] = useState(null);
114692
+ // Sync drawer when compare param comes from URL
114693
+ useEffect(()=>{
114694
+ if (compareIdsFromUrl) {
114695
+ setEvaluationId1(compareIdsFromUrl[0]);
114696
+ setEvaluationId2(compareIdsFromUrl[1]);
114697
+ setCompareDrawerOpen(true);
114698
+ }
114699
+ }, [
114700
+ compareIdsFromUrl
114701
+ ]);
114104
114702
  const [selectedEvaluation, setSelectedEvaluation] = useState(null);
114105
114703
  const [detailsDrawerOpen, setDetailsDrawerOpen] = useState(false);
114106
114704
  const [pageSize, setPageSize] = useState(50);
@@ -114164,14 +114762,23 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114164
114762
  if (selectedRowKeys.length === 2 && onCompare) {
114165
114763
  onCompare(selectedRowKeys[0], selectedRowKeys[1]);
114166
114764
  } else if (selectedRowKeys.length === 2 && !onCompare) {
114167
- setSourceEvaluationId(selectedRowKeys[0]);
114168
- setTargetEvaluationId(selectedRowKeys[1]);
114765
+ setEvaluationId1(selectedRowKeys[0]);
114766
+ setEvaluationId2(selectedRowKeys[1]);
114169
114767
  setCompareDrawerOpen(true);
114170
114768
  }
114171
114769
  };
114172
114770
  // Handle drawer close
114173
114771
  const handleDrawerClose = ()=>{
114174
114772
  setCompareDrawerOpen(false);
114773
+ onCompareUrlChange?.(null, null);
114774
+ };
114775
+ const handleEvaluationId1Change = (id)=>{
114776
+ setEvaluationId1(id);
114777
+ onCompareUrlChange?.(id, evaluationId2);
114778
+ };
114779
+ const handleEvaluationId2Change = (id)=>{
114780
+ setEvaluationId2(id);
114781
+ onCompareUrlChange?.(evaluationId1, id);
114175
114782
  };
114176
114783
  // Handle row click to open evaluation details
114177
114784
  const handleRowClick = (record)=>{
@@ -114372,14 +114979,14 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114372
114979
  cursor: "pointer"
114373
114980
  }
114374
114981
  })
114375
- }), !onCompare && /*#__PURE__*/ React__default.createElement(EvaluationsCompare, {
114982
+ }), compareDrawerOpen && /*#__PURE__*/ React__default.createElement(EvaluationsCompareDrawer, {
114376
114983
  open: compareDrawerOpen,
114377
114984
  onClose: handleDrawerClose,
114378
- sourceEvaluationId: sourceEvaluationId,
114379
- targetEvaluationId: targetEvaluationId,
114985
+ evaluationId1: evaluationId1,
114986
+ evaluationId2: evaluationId2,
114380
114987
  evaluations: normalized,
114381
- onSourceChange: setSourceEvaluationId,
114382
- onTargetChange: setTargetEvaluationId
114988
+ onEvaluationId1Change: onCompareUrlChange ? handleEvaluationId1Change : setEvaluationId1,
114989
+ onEvaluationId2Change: onCompareUrlChange ? handleEvaluationId2Change : setEvaluationId2
114383
114990
  }), !onRowClick && /*#__PURE__*/ React__default.createElement(EvaluationDetailsDrawer, {
114384
114991
  evaluation: selectedEvaluation,
114385
114992
  open: detailsDrawerOpen,
@@ -114387,6 +114994,1938 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114387
114994
  }));
114388
114995
  };
114389
114996
 
114997
+ function invariant(value, message) {
114998
+ if (value === false || value === null || typeof value === "undefined") {
114999
+ throw new Error(message);
115000
+ }
115001
+ }
115002
+ function warning(cond, message) {
115003
+ if (!cond) {
115004
+ if (typeof console !== "undefined") console.warn(message);
115005
+ try {
115006
+ throw new Error(message);
115007
+ } catch (e) {}
115008
+ }
115009
+ }
115010
+ function createPath({ pathname = "/", search = "", hash = "" }) {
115011
+ if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
115012
+ if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
115013
+ return pathname;
115014
+ }
115015
+ function parsePath(path) {
115016
+ let parsedPath = {};
115017
+ if (path) {
115018
+ let hashIndex = path.indexOf("#");
115019
+ if (hashIndex >= 0) {
115020
+ parsedPath.hash = path.substring(hashIndex);
115021
+ path = path.substring(0, hashIndex);
115022
+ }
115023
+ let searchIndex = path.indexOf("?");
115024
+ if (searchIndex >= 0) {
115025
+ parsedPath.search = path.substring(searchIndex);
115026
+ path = path.substring(0, searchIndex);
115027
+ }
115028
+ if (path) {
115029
+ parsedPath.pathname = path;
115030
+ }
115031
+ }
115032
+ return parsedPath;
115033
+ }
115034
+ function matchRoutes(routes, locationArg, basename = "/") {
115035
+ return matchRoutesImpl(routes, locationArg, basename, false);
115036
+ }
115037
+ function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
115038
+ let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
115039
+ let pathname = stripBasename(location.pathname || "/", basename);
115040
+ if (pathname == null) {
115041
+ return null;
115042
+ }
115043
+ let branches = flattenRoutes(routes);
115044
+ rankRouteBranches(branches);
115045
+ let matches = null;
115046
+ for(let i = 0; matches == null && i < branches.length; ++i){
115047
+ let decoded = decodePath(pathname);
115048
+ matches = matchRouteBranch(branches[i], decoded, allowPartial);
115049
+ }
115050
+ return matches;
115051
+ }
115052
+ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
115053
+ let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath)=>{
115054
+ let meta = {
115055
+ relativePath: relativePath === void 0 ? route.path || "" : relativePath,
115056
+ caseSensitive: route.caseSensitive === true,
115057
+ childrenIndex: index,
115058
+ route
115059
+ };
115060
+ if (meta.relativePath.startsWith("/")) {
115061
+ if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) {
115062
+ return;
115063
+ }
115064
+ invariant(meta.relativePath.startsWith(parentPath), `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`);
115065
+ meta.relativePath = meta.relativePath.slice(parentPath.length);
115066
+ }
115067
+ let path = joinPaths([
115068
+ parentPath,
115069
+ meta.relativePath
115070
+ ]);
115071
+ let routesMeta = parentsMeta.concat(meta);
115072
+ if (route.children && route.children.length > 0) {
115073
+ invariant(// Our types know better, but runtime JS may not!
115074
+ // @ts-expect-error
115075
+ route.index !== true, `Index routes must not have child routes. Please remove all child routes from route path "${path}".`);
115076
+ flattenRoutes(route.children, branches, routesMeta, path, hasParentOptionalSegments);
115077
+ }
115078
+ if (route.path == null && !route.index) {
115079
+ return;
115080
+ }
115081
+ branches.push({
115082
+ path,
115083
+ score: computeScore(path, route.index),
115084
+ routesMeta
115085
+ });
115086
+ };
115087
+ routes.forEach((route, index)=>{
115088
+ if (route.path === "" || !route.path?.includes("?")) {
115089
+ flattenRoute(route, index);
115090
+ } else {
115091
+ for (let exploded of explodeOptionalSegments(route.path)){
115092
+ flattenRoute(route, index, true, exploded);
115093
+ }
115094
+ }
115095
+ });
115096
+ return branches;
115097
+ }
115098
+ function explodeOptionalSegments(path) {
115099
+ let segments = path.split("/");
115100
+ if (segments.length === 0) return [];
115101
+ let [first, ...rest] = segments;
115102
+ let isOptional = first.endsWith("?");
115103
+ let required = first.replace(/\?$/, "");
115104
+ if (rest.length === 0) {
115105
+ return isOptional ? [
115106
+ required,
115107
+ ""
115108
+ ] : [
115109
+ required
115110
+ ];
115111
+ }
115112
+ let restExploded = explodeOptionalSegments(rest.join("/"));
115113
+ let result = [];
115114
+ result.push(...restExploded.map((subpath)=>subpath === "" ? required : [
115115
+ required,
115116
+ subpath
115117
+ ].join("/")));
115118
+ if (isOptional) {
115119
+ result.push(...restExploded);
115120
+ }
115121
+ return result.map((exploded)=>path.startsWith("/") && exploded === "" ? "/" : exploded);
115122
+ }
115123
+ function rankRouteBranches(branches) {
115124
+ branches.sort((a, b)=>a.score !== b.score ? b.score - a.score : compareIndexes(a.routesMeta.map((meta)=>meta.childrenIndex), b.routesMeta.map((meta)=>meta.childrenIndex)));
115125
+ }
115126
+ var paramRe = /^:[\w-]+$/;
115127
+ var dynamicSegmentValue = 3;
115128
+ var indexRouteValue = 2;
115129
+ var emptySegmentValue = 1;
115130
+ var staticSegmentValue = 10;
115131
+ var splatPenalty = -2;
115132
+ var isSplat = (s)=>s === "*";
115133
+ function computeScore(path, index) {
115134
+ let segments = path.split("/");
115135
+ let initialScore = segments.length;
115136
+ if (segments.some(isSplat)) {
115137
+ initialScore += splatPenalty;
115138
+ }
115139
+ if (index) {
115140
+ initialScore += indexRouteValue;
115141
+ }
115142
+ return segments.filter((s)=>!isSplat(s)).reduce((score, segment)=>score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
115143
+ }
115144
+ function compareIndexes(a, b) {
115145
+ let siblings = a.length === b.length && a.slice(0, -1).every((n, i)=>n === b[i]);
115146
+ return siblings ? // If two routes are siblings, we should try to match the earlier sibling
115147
+ // first. This allows people to have fine-grained control over the matching
115148
+ // behavior by simply putting routes with identical paths in the order they
115149
+ // want them tried.
115150
+ a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
115151
+ // so they sort equally.
115152
+ 0;
115153
+ }
115154
+ function matchRouteBranch(branch, pathname, allowPartial = false) {
115155
+ let { routesMeta } = branch;
115156
+ let matchedParams = {};
115157
+ let matchedPathname = "/";
115158
+ let matches = [];
115159
+ for(let i = 0; i < routesMeta.length; ++i){
115160
+ let meta = routesMeta[i];
115161
+ let end = i === routesMeta.length - 1;
115162
+ let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
115163
+ let match = matchPath({
115164
+ path: meta.relativePath,
115165
+ caseSensitive: meta.caseSensitive,
115166
+ end
115167
+ }, remainingPathname);
115168
+ let route = meta.route;
115169
+ if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
115170
+ match = matchPath({
115171
+ path: meta.relativePath,
115172
+ caseSensitive: meta.caseSensitive,
115173
+ end: false
115174
+ }, remainingPathname);
115175
+ }
115176
+ if (!match) {
115177
+ return null;
115178
+ }
115179
+ Object.assign(matchedParams, match.params);
115180
+ matches.push({
115181
+ // TODO: Can this as be avoided?
115182
+ params: matchedParams,
115183
+ pathname: joinPaths([
115184
+ matchedPathname,
115185
+ match.pathname
115186
+ ]),
115187
+ pathnameBase: normalizePathname(joinPaths([
115188
+ matchedPathname,
115189
+ match.pathnameBase
115190
+ ])),
115191
+ route
115192
+ });
115193
+ if (match.pathnameBase !== "/") {
115194
+ matchedPathname = joinPaths([
115195
+ matchedPathname,
115196
+ match.pathnameBase
115197
+ ]);
115198
+ }
115199
+ }
115200
+ return matches;
115201
+ }
115202
+ function matchPath(pattern, pathname) {
115203
+ if (typeof pattern === "string") {
115204
+ pattern = {
115205
+ path: pattern,
115206
+ caseSensitive: false,
115207
+ end: true
115208
+ };
115209
+ }
115210
+ let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
115211
+ let match = pathname.match(matcher);
115212
+ if (!match) return null;
115213
+ let matchedPathname = match[0];
115214
+ let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
115215
+ let captureGroups = match.slice(1);
115216
+ let params = compiledParams.reduce((memo2, { paramName, isOptional }, index)=>{
115217
+ if (paramName === "*") {
115218
+ let splatValue = captureGroups[index] || "";
115219
+ pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
115220
+ }
115221
+ const value = captureGroups[index];
115222
+ if (isOptional && !value) {
115223
+ memo2[paramName] = void 0;
115224
+ } else {
115225
+ memo2[paramName] = (value || "").replace(/%2F/g, "/");
115226
+ }
115227
+ return memo2;
115228
+ }, {});
115229
+ return {
115230
+ params,
115231
+ pathname: matchedPathname,
115232
+ pathnameBase,
115233
+ pattern
115234
+ };
115235
+ }
115236
+ function compilePath(path, caseSensitive = false, end = true) {
115237
+ warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`);
115238
+ let params = [];
115239
+ let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (match, paramName, isOptional, index, str)=>{
115240
+ params.push({
115241
+ paramName,
115242
+ isOptional: isOptional != null
115243
+ });
115244
+ if (isOptional) {
115245
+ let nextChar = str.charAt(index + match.length);
115246
+ if (nextChar && nextChar !== "/") {
115247
+ return "/([^\\/]*)";
115248
+ }
115249
+ return "(?:/([^\\/]*))?";
115250
+ }
115251
+ return "/([^\\/]+)";
115252
+ }).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2");
115253
+ if (path.endsWith("*")) {
115254
+ params.push({
115255
+ paramName: "*"
115256
+ });
115257
+ regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
115258
+ } else if (end) {
115259
+ regexpSource += "\\/*$";
115260
+ } else if (path !== "" && path !== "/") {
115261
+ regexpSource += "(?:(?=\\/|$))";
115262
+ } else ;
115263
+ let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
115264
+ return [
115265
+ matcher,
115266
+ params
115267
+ ];
115268
+ }
115269
+ function decodePath(value) {
115270
+ try {
115271
+ return value.split("/").map((v)=>decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
115272
+ } catch (error) {
115273
+ warning(false, `The URL path "${value}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${error}).`);
115274
+ return value;
115275
+ }
115276
+ }
115277
+ function stripBasename(pathname, basename) {
115278
+ if (basename === "/") return pathname;
115279
+ if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
115280
+ return null;
115281
+ }
115282
+ let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
115283
+ let nextChar = pathname.charAt(startIndex);
115284
+ if (nextChar && nextChar !== "/") {
115285
+ return null;
115286
+ }
115287
+ return pathname.slice(startIndex) || "/";
115288
+ }
115289
+ var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
115290
+ function resolvePath(to, fromPathname = "/") {
115291
+ let { pathname: toPathname, search = "", hash = "" } = typeof to === "string" ? parsePath(to) : to;
115292
+ let pathname;
115293
+ if (toPathname) {
115294
+ toPathname = toPathname.replace(/\/\/+/g, "/");
115295
+ if (toPathname.startsWith("/")) {
115296
+ pathname = resolvePathname(toPathname.substring(1), "/");
115297
+ } else {
115298
+ pathname = resolvePathname(toPathname, fromPathname);
115299
+ }
115300
+ } else {
115301
+ pathname = fromPathname;
115302
+ }
115303
+ return {
115304
+ pathname,
115305
+ search: normalizeSearch(search),
115306
+ hash: normalizeHash(hash)
115307
+ };
115308
+ }
115309
+ function resolvePathname(relativePath, fromPathname) {
115310
+ let segments = fromPathname.replace(/\/+$/, "").split("/");
115311
+ let relativeSegments = relativePath.split("/");
115312
+ relativeSegments.forEach((segment)=>{
115313
+ if (segment === "..") {
115314
+ if (segments.length > 1) segments.pop();
115315
+ } else if (segment !== ".") {
115316
+ segments.push(segment);
115317
+ }
115318
+ });
115319
+ return segments.length > 1 ? segments.join("/") : "/";
115320
+ }
115321
+ function getInvalidPathError(char, field, dest, path) {
115322
+ return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(path)}]. Please separate it out to the \`to.${dest}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`;
115323
+ }
115324
+ function getPathContributingMatches(matches) {
115325
+ return matches.filter((match, index)=>index === 0 || match.route.path && match.route.path.length > 0);
115326
+ }
115327
+ function getResolveToMatches(matches) {
115328
+ let pathMatches = getPathContributingMatches(matches);
115329
+ return pathMatches.map((match, idx)=>idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);
115330
+ }
115331
+ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
115332
+ let to;
115333
+ if (typeof toArg === "string") {
115334
+ to = parsePath(toArg);
115335
+ } else {
115336
+ to = {
115337
+ ...toArg
115338
+ };
115339
+ invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
115340
+ invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
115341
+ invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
115342
+ }
115343
+ let isEmptyPath = toArg === "" || to.pathname === "";
115344
+ let toPathname = isEmptyPath ? "/" : to.pathname;
115345
+ let from;
115346
+ if (toPathname == null) {
115347
+ from = locationPathname;
115348
+ } else {
115349
+ let routePathnameIndex = routePathnames.length - 1;
115350
+ if (!isPathRelative && toPathname.startsWith("..")) {
115351
+ let toSegments = toPathname.split("/");
115352
+ while(toSegments[0] === ".."){
115353
+ toSegments.shift();
115354
+ routePathnameIndex -= 1;
115355
+ }
115356
+ to.pathname = toSegments.join("/");
115357
+ }
115358
+ from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
115359
+ }
115360
+ let path = resolvePath(to, from);
115361
+ let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
115362
+ let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
115363
+ if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
115364
+ path.pathname += "/";
115365
+ }
115366
+ return path;
115367
+ }
115368
+ var joinPaths = (paths)=>paths.join("/").replace(/\/\/+/g, "/");
115369
+ var normalizePathname = (pathname)=>pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
115370
+ var normalizeSearch = (search)=>!search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
115371
+ var normalizeHash = (hash)=>!hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
115372
+ var ErrorResponseImpl = class {
115373
+ constructor(status, statusText, data2, internal = false){
115374
+ this.status = status;
115375
+ this.statusText = statusText || "";
115376
+ this.internal = internal;
115377
+ if (data2 instanceof Error) {
115378
+ this.data = data2.toString();
115379
+ this.error = data2;
115380
+ } else {
115381
+ this.data = data2;
115382
+ }
115383
+ }
115384
+ };
115385
+ function isRouteErrorResponse(error) {
115386
+ return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
115387
+ }
115388
+ function getRoutePattern(matches) {
115389
+ return matches.map((m)=>m.route.path).filter(Boolean).join("/").replace(/\/\/*/g, "/") || "/";
115390
+ }
115391
+ var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
115392
+ function parseToInfo(_to, basename) {
115393
+ let to = _to;
115394
+ if (typeof to !== "string" || !ABSOLUTE_URL_REGEX.test(to)) {
115395
+ return {
115396
+ absoluteURL: void 0,
115397
+ isExternal: false,
115398
+ to
115399
+ };
115400
+ }
115401
+ let absoluteURL = to;
115402
+ let isExternal = false;
115403
+ if (isBrowser) {
115404
+ try {
115405
+ let currentUrl = new URL(window.location.href);
115406
+ let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
115407
+ let path = stripBasename(targetUrl.pathname, basename);
115408
+ if (targetUrl.origin === currentUrl.origin && path != null) {
115409
+ to = path + targetUrl.search + targetUrl.hash;
115410
+ } else {
115411
+ isExternal = true;
115412
+ }
115413
+ } catch (e) {
115414
+ warning(false, `<Link to="${to}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`);
115415
+ }
115416
+ }
115417
+ return {
115418
+ absoluteURL,
115419
+ isExternal,
115420
+ to
115421
+ };
115422
+ }
115423
+ Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
115424
+ // lib/router/router.ts
115425
+ var validMutationMethodsArr = [
115426
+ "POST",
115427
+ "PUT",
115428
+ "PATCH",
115429
+ "DELETE"
115430
+ ];
115431
+ new Set(validMutationMethodsArr);
115432
+ var validRequestMethodsArr = [
115433
+ "GET",
115434
+ ...validMutationMethodsArr
115435
+ ];
115436
+ new Set(validRequestMethodsArr);
115437
+ var DataRouterContext = React.createContext(null);
115438
+ DataRouterContext.displayName = "DataRouter";
115439
+ var DataRouterStateContext = React.createContext(null);
115440
+ DataRouterStateContext.displayName = "DataRouterState";
115441
+ var RSCRouterContext = React.createContext(false);
115442
+ var ViewTransitionContext = React.createContext({
115443
+ isTransitioning: false
115444
+ });
115445
+ ViewTransitionContext.displayName = "ViewTransition";
115446
+ var FetchersContext = React.createContext(/* @__PURE__ */ new Map());
115447
+ FetchersContext.displayName = "Fetchers";
115448
+ var AwaitContext = React.createContext(null);
115449
+ AwaitContext.displayName = "Await";
115450
+ var NavigationContext = React.createContext(null);
115451
+ NavigationContext.displayName = "Navigation";
115452
+ var LocationContext = React.createContext(null);
115453
+ LocationContext.displayName = "Location";
115454
+ var RouteContext = React.createContext({
115455
+ outlet: null,
115456
+ matches: [],
115457
+ isDataRoute: false
115458
+ });
115459
+ RouteContext.displayName = "Route";
115460
+ var RouteErrorContext = React.createContext(null);
115461
+ RouteErrorContext.displayName = "RouteError";
115462
+ // lib/errors.ts
115463
+ var ERROR_DIGEST_BASE = "REACT_ROUTER_ERROR";
115464
+ var ERROR_DIGEST_REDIRECT = "REDIRECT";
115465
+ var ERROR_DIGEST_ROUTE_ERROR_RESPONSE = "ROUTE_ERROR_RESPONSE";
115466
+ function decodeRedirectErrorDigest(digest) {
115467
+ if (digest.startsWith(`${ERROR_DIGEST_BASE}:${ERROR_DIGEST_REDIRECT}:{`)) {
115468
+ try {
115469
+ let parsed = JSON.parse(digest.slice(28));
115470
+ if (typeof parsed === "object" && parsed && typeof parsed.status === "number" && typeof parsed.statusText === "string" && typeof parsed.location === "string" && typeof parsed.reloadDocument === "boolean" && typeof parsed.replace === "boolean") {
115471
+ return parsed;
115472
+ }
115473
+ } catch {}
115474
+ }
115475
+ }
115476
+ function decodeRouteErrorResponseDigest(digest) {
115477
+ if (digest.startsWith(`${ERROR_DIGEST_BASE}:${ERROR_DIGEST_ROUTE_ERROR_RESPONSE}:{`)) {
115478
+ try {
115479
+ let parsed = JSON.parse(digest.slice(40));
115480
+ if (typeof parsed === "object" && parsed && typeof parsed.status === "number" && typeof parsed.statusText === "string") {
115481
+ return new ErrorResponseImpl(parsed.status, parsed.statusText, parsed.data);
115482
+ }
115483
+ } catch {}
115484
+ }
115485
+ }
115486
+ // lib/hooks.tsx
115487
+ function useHref(to, { relative } = {}) {
115488
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115489
+ // router loaded. We can help them understand how to avoid that.
115490
+ `useHref() may be used only in the context of a <Router> component.`);
115491
+ let { basename, navigator } = React.useContext(NavigationContext);
115492
+ let { hash, pathname, search } = useResolvedPath(to, {
115493
+ relative
115494
+ });
115495
+ let joinedPathname = pathname;
115496
+ if (basename !== "/") {
115497
+ joinedPathname = pathname === "/" ? basename : joinPaths([
115498
+ basename,
115499
+ pathname
115500
+ ]);
115501
+ }
115502
+ return navigator.createHref({
115503
+ pathname: joinedPathname,
115504
+ search,
115505
+ hash
115506
+ });
115507
+ }
115508
+ function useInRouterContext() {
115509
+ return React.useContext(LocationContext) != null;
115510
+ }
115511
+ function useLocation() {
115512
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115513
+ // router loaded. We can help them understand how to avoid that.
115514
+ `useLocation() may be used only in the context of a <Router> component.`);
115515
+ return React.useContext(LocationContext).location;
115516
+ }
115517
+ var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`;
115518
+ function useIsomorphicLayoutEffect$1(cb) {
115519
+ let isStatic = React.useContext(NavigationContext).static;
115520
+ if (!isStatic) {
115521
+ React.useLayoutEffect(cb);
115522
+ }
115523
+ }
115524
+ function useNavigate() {
115525
+ let { isDataRoute } = React.useContext(RouteContext);
115526
+ return isDataRoute ? useNavigateStable() : useNavigateUnstable();
115527
+ }
115528
+ function useNavigateUnstable() {
115529
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115530
+ // router loaded. We can help them understand how to avoid that.
115531
+ `useNavigate() may be used only in the context of a <Router> component.`);
115532
+ let dataRouterContext = React.useContext(DataRouterContext);
115533
+ let { basename, navigator } = React.useContext(NavigationContext);
115534
+ let { matches } = React.useContext(RouteContext);
115535
+ let { pathname: locationPathname } = useLocation();
115536
+ let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
115537
+ let activeRef = React.useRef(false);
115538
+ useIsomorphicLayoutEffect$1(()=>{
115539
+ activeRef.current = true;
115540
+ });
115541
+ let navigate = React.useCallback((to, options = {})=>{
115542
+ warning(activeRef.current, navigateEffectWarning);
115543
+ if (!activeRef.current) return;
115544
+ if (typeof to === "number") {
115545
+ navigator.go(to);
115546
+ return;
115547
+ }
115548
+ let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
115549
+ if (dataRouterContext == null && basename !== "/") {
115550
+ path.pathname = path.pathname === "/" ? basename : joinPaths([
115551
+ basename,
115552
+ path.pathname
115553
+ ]);
115554
+ }
115555
+ (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
115556
+ }, [
115557
+ basename,
115558
+ navigator,
115559
+ routePathnamesJson,
115560
+ locationPathname,
115561
+ dataRouterContext
115562
+ ]);
115563
+ return navigate;
115564
+ }
115565
+ React.createContext(null);
115566
+ function useResolvedPath(to, { relative } = {}) {
115567
+ let { matches } = React.useContext(RouteContext);
115568
+ let { pathname: locationPathname } = useLocation();
115569
+ let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
115570
+ return React.useMemo(()=>resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [
115571
+ to,
115572
+ routePathnamesJson,
115573
+ locationPathname,
115574
+ relative
115575
+ ]);
115576
+ }
115577
+ function useRoutesImpl(routes, locationArg, dataRouterOpts) {
115578
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115579
+ // router loaded. We can help them understand how to avoid that.
115580
+ `useRoutes() may be used only in the context of a <Router> component.`);
115581
+ let { navigator } = React.useContext(NavigationContext);
115582
+ let { matches: parentMatches } = React.useContext(RouteContext);
115583
+ let routeMatch = parentMatches[parentMatches.length - 1];
115584
+ let parentParams = routeMatch ? routeMatch.params : {};
115585
+ let parentPathname = routeMatch ? routeMatch.pathname : "/";
115586
+ let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
115587
+ let parentRoute = routeMatch && routeMatch.route;
115588
+ {
115589
+ let parentPath = parentRoute && parentRoute.path || "";
115590
+ warningOnce(parentPathname, !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"), `You rendered descendant <Routes> (or called \`useRoutes()\`) at "${parentPathname}" (under <Route path="${parentPath}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
115591
+
115592
+ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`);
115593
+ }
115594
+ let locationFromContext = useLocation();
115595
+ let location;
115596
+ {
115597
+ location = locationFromContext;
115598
+ }
115599
+ let pathname = location.pathname || "/";
115600
+ let remainingPathname = pathname;
115601
+ if (parentPathnameBase !== "/") {
115602
+ let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
115603
+ let segments = pathname.replace(/^\//, "").split("/");
115604
+ remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
115605
+ }
115606
+ let matches = matchRoutes(routes, {
115607
+ pathname: remainingPathname
115608
+ });
115609
+ {
115610
+ warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `);
115611
+ warning(matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0, `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`);
115612
+ }
115613
+ let renderedMatches = _renderMatches(matches && matches.map((match)=>Object.assign({}, match, {
115614
+ params: Object.assign({}, parentParams, match.params),
115615
+ pathname: joinPaths([
115616
+ parentPathnameBase,
115617
+ // Re-encode pathnames that were decoded inside matchRoutes.
115618
+ // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses
115619
+ // `new URL()` internally and we need to prevent it from treating
115620
+ // them as separators
115621
+ navigator.encodeLocation ? navigator.encodeLocation(match.pathname.replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathname
115622
+ ]),
115623
+ pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([
115624
+ parentPathnameBase,
115625
+ // Re-encode pathnames that were decoded inside matchRoutes
115626
+ // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses
115627
+ // `new URL()` internally and we need to prevent it from treating
115628
+ // them as separators
115629
+ navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase.replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathnameBase
115630
+ ])
115631
+ })), parentMatches, dataRouterOpts);
115632
+ return renderedMatches;
115633
+ }
115634
+ function DefaultErrorComponent() {
115635
+ let error = useRouteError();
115636
+ let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
115637
+ let stack = error instanceof Error ? error.stack : null;
115638
+ let lightgrey = "rgba(200,200,200, 0.5)";
115639
+ let preStyles = {
115640
+ padding: "0.5rem",
115641
+ backgroundColor: lightgrey
115642
+ };
115643
+ let codeStyles = {
115644
+ padding: "2px 4px",
115645
+ backgroundColor: lightgrey
115646
+ };
115647
+ let devInfo = null;
115648
+ {
115649
+ console.error("Error handled by React Router default ErrorBoundary:", error);
115650
+ devInfo = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", null, "\u{1F4BF} Hey developer \u{1F44B}"), /* @__PURE__ */ React.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /* @__PURE__ */ React.createElement("code", {
115651
+ style: codeStyles
115652
+ }, "ErrorBoundary"), " or", " ", /* @__PURE__ */ React.createElement("code", {
115653
+ style: codeStyles
115654
+ }, "errorElement"), " prop on your route."));
115655
+ }
115656
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h2", null, "Unexpected Application Error!"), /* @__PURE__ */ React.createElement("h3", {
115657
+ style: {
115658
+ fontStyle: "italic"
115659
+ }
115660
+ }, message), stack ? /* @__PURE__ */ React.createElement("pre", {
115661
+ style: preStyles
115662
+ }, stack) : null, devInfo);
115663
+ }
115664
+ var defaultErrorElement = /* @__PURE__ */ React.createElement(DefaultErrorComponent, null);
115665
+ var RenderErrorBoundary = class extends React.Component {
115666
+ static getDerivedStateFromError(error) {
115667
+ return {
115668
+ error
115669
+ };
115670
+ }
115671
+ static getDerivedStateFromProps(props, state) {
115672
+ if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
115673
+ return {
115674
+ error: props.error,
115675
+ location: props.location,
115676
+ revalidation: props.revalidation
115677
+ };
115678
+ }
115679
+ return {
115680
+ error: props.error !== void 0 ? props.error : state.error,
115681
+ location: state.location,
115682
+ revalidation: props.revalidation || state.revalidation
115683
+ };
115684
+ }
115685
+ componentDidCatch(error, errorInfo) {
115686
+ if (this.props.onError) {
115687
+ this.props.onError(error, errorInfo);
115688
+ } else {
115689
+ console.error("React Router caught the following error during render", error);
115690
+ }
115691
+ }
115692
+ render() {
115693
+ let error = this.state.error;
115694
+ if (this.context && typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
115695
+ const decoded = decodeRouteErrorResponseDigest(error.digest);
115696
+ if (decoded) error = decoded;
115697
+ }
115698
+ let result = error !== void 0 ? /* @__PURE__ */ React.createElement(RouteContext.Provider, {
115699
+ value: this.props.routeContext
115700
+ }, /* @__PURE__ */ React.createElement(RouteErrorContext.Provider, {
115701
+ value: error,
115702
+ children: this.props.component
115703
+ })) : this.props.children;
115704
+ if (this.context) {
115705
+ return /* @__PURE__ */ React.createElement(RSCErrorHandler, {
115706
+ error
115707
+ }, result);
115708
+ }
115709
+ return result;
115710
+ }
115711
+ constructor(props){
115712
+ super(props);
115713
+ this.state = {
115714
+ location: props.location,
115715
+ revalidation: props.revalidation,
115716
+ error: props.error
115717
+ };
115718
+ }
115719
+ };
115720
+ RenderErrorBoundary.contextType = RSCRouterContext;
115721
+ var errorRedirectHandledMap = /* @__PURE__ */ new WeakMap();
115722
+ function RSCErrorHandler({ children, error }) {
115723
+ let { basename } = React.useContext(NavigationContext);
115724
+ if (typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
115725
+ let redirect2 = decodeRedirectErrorDigest(error.digest);
115726
+ if (redirect2) {
115727
+ let existingRedirect = errorRedirectHandledMap.get(error);
115728
+ if (existingRedirect) throw existingRedirect;
115729
+ let parsed = parseToInfo(redirect2.location, basename);
115730
+ if (isBrowser && !errorRedirectHandledMap.get(error)) {
115731
+ if (parsed.isExternal || redirect2.reloadDocument) {
115732
+ window.location.href = parsed.absoluteURL || parsed.to;
115733
+ } else {
115734
+ const redirectPromise = Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(parsed.to, {
115735
+ replace: redirect2.replace
115736
+ }));
115737
+ errorRedirectHandledMap.set(error, redirectPromise);
115738
+ throw redirectPromise;
115739
+ }
115740
+ }
115741
+ return /* @__PURE__ */ React.createElement("meta", {
115742
+ httpEquiv: "refresh",
115743
+ content: `0;url=${parsed.absoluteURL || parsed.to}`
115744
+ });
115745
+ }
115746
+ }
115747
+ return children;
115748
+ }
115749
+ function RenderedRoute({ routeContext, match, children }) {
115750
+ let dataRouterContext = React.useContext(DataRouterContext);
115751
+ if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
115752
+ dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
115753
+ }
115754
+ return /* @__PURE__ */ React.createElement(RouteContext.Provider, {
115755
+ value: routeContext
115756
+ }, children);
115757
+ }
115758
+ function _renderMatches(matches, parentMatches = [], dataRouterOpts) {
115759
+ let dataRouterState = dataRouterOpts?.state;
115760
+ if (matches == null) {
115761
+ if (!dataRouterState) {
115762
+ return null;
115763
+ }
115764
+ if (dataRouterState.errors) {
115765
+ matches = dataRouterState.matches;
115766
+ } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) {
115767
+ matches = dataRouterState.matches;
115768
+ } else {
115769
+ return null;
115770
+ }
115771
+ }
115772
+ let renderedMatches = matches;
115773
+ let errors = dataRouterState?.errors;
115774
+ if (errors != null) {
115775
+ let errorIndex = renderedMatches.findIndex((m)=>m.route.id && errors?.[m.route.id] !== void 0);
115776
+ invariant(errorIndex >= 0, `Could not find a matching route for errors on route IDs: ${Object.keys(errors).join(",")}`);
115777
+ renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
115778
+ }
115779
+ let renderFallback = false;
115780
+ let fallbackIndex = -1;
115781
+ if (dataRouterOpts && dataRouterState) {
115782
+ renderFallback = dataRouterState.renderFallback;
115783
+ for(let i = 0; i < renderedMatches.length; i++){
115784
+ let match = renderedMatches[i];
115785
+ if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
115786
+ fallbackIndex = i;
115787
+ }
115788
+ if (match.route.id) {
115789
+ let { loaderData, errors: errors2 } = dataRouterState;
115790
+ let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0);
115791
+ if (match.route.lazy || needsToRunLoader) {
115792
+ if (dataRouterOpts.isStatic) {
115793
+ renderFallback = true;
115794
+ }
115795
+ if (fallbackIndex >= 0) {
115796
+ renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
115797
+ } else {
115798
+ renderedMatches = [
115799
+ renderedMatches[0]
115800
+ ];
115801
+ }
115802
+ break;
115803
+ }
115804
+ }
115805
+ }
115806
+ }
115807
+ let onErrorHandler = dataRouterOpts?.onError;
115808
+ let onError = dataRouterState && onErrorHandler ? (error, errorInfo)=>{
115809
+ onErrorHandler(error, {
115810
+ location: dataRouterState.location,
115811
+ params: dataRouterState.matches?.[0]?.params ?? {},
115812
+ unstable_pattern: getRoutePattern(dataRouterState.matches),
115813
+ errorInfo
115814
+ });
115815
+ } : void 0;
115816
+ return renderedMatches.reduceRight((outlet, match, index)=>{
115817
+ let error;
115818
+ let shouldRenderHydrateFallback = false;
115819
+ let errorElement = null;
115820
+ let hydrateFallbackElement = null;
115821
+ if (dataRouterState) {
115822
+ error = errors && match.route.id ? errors[match.route.id] : void 0;
115823
+ errorElement = match.route.errorElement || defaultErrorElement;
115824
+ if (renderFallback) {
115825
+ if (fallbackIndex < 0 && index === 0) {
115826
+ warningOnce("route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration");
115827
+ shouldRenderHydrateFallback = true;
115828
+ hydrateFallbackElement = null;
115829
+ } else if (fallbackIndex === index) {
115830
+ shouldRenderHydrateFallback = true;
115831
+ hydrateFallbackElement = match.route.hydrateFallbackElement || null;
115832
+ }
115833
+ }
115834
+ }
115835
+ let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1));
115836
+ let getChildren = ()=>{
115837
+ let children;
115838
+ if (error) {
115839
+ children = errorElement;
115840
+ } else if (shouldRenderHydrateFallback) {
115841
+ children = hydrateFallbackElement;
115842
+ } else if (match.route.Component) {
115843
+ children = /* @__PURE__ */ React.createElement(match.route.Component, null);
115844
+ } else if (match.route.element) {
115845
+ children = match.route.element;
115846
+ } else {
115847
+ children = outlet;
115848
+ }
115849
+ return /* @__PURE__ */ React.createElement(RenderedRoute, {
115850
+ match,
115851
+ routeContext: {
115852
+ outlet,
115853
+ matches: matches2,
115854
+ isDataRoute: dataRouterState != null
115855
+ },
115856
+ children
115857
+ });
115858
+ };
115859
+ return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React.createElement(RenderErrorBoundary, {
115860
+ location: dataRouterState.location,
115861
+ revalidation: dataRouterState.revalidation,
115862
+ component: errorElement,
115863
+ error,
115864
+ children: getChildren(),
115865
+ routeContext: {
115866
+ outlet: null,
115867
+ matches: matches2,
115868
+ isDataRoute: true
115869
+ },
115870
+ onError
115871
+ }) : getChildren();
115872
+ }, null);
115873
+ }
115874
+ function getDataRouterConsoleError(hookName) {
115875
+ return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
115876
+ }
115877
+ function useDataRouterContext(hookName) {
115878
+ let ctx = React.useContext(DataRouterContext);
115879
+ invariant(ctx, getDataRouterConsoleError(hookName));
115880
+ return ctx;
115881
+ }
115882
+ function useDataRouterState(hookName) {
115883
+ let state = React.useContext(DataRouterStateContext);
115884
+ invariant(state, getDataRouterConsoleError(hookName));
115885
+ return state;
115886
+ }
115887
+ function useRouteContext(hookName) {
115888
+ let route = React.useContext(RouteContext);
115889
+ invariant(route, getDataRouterConsoleError(hookName));
115890
+ return route;
115891
+ }
115892
+ function useCurrentRouteId(hookName) {
115893
+ let route = useRouteContext(hookName);
115894
+ let thisRoute = route.matches[route.matches.length - 1];
115895
+ invariant(thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"`);
115896
+ return thisRoute.route.id;
115897
+ }
115898
+ function useRouteId() {
115899
+ return useCurrentRouteId("useRouteId" /* UseRouteId */ );
115900
+ }
115901
+ function useRouteError() {
115902
+ let error = React.useContext(RouteErrorContext);
115903
+ let state = useDataRouterState("useRouteError" /* UseRouteError */ );
115904
+ let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */ );
115905
+ if (error !== void 0) {
115906
+ return error;
115907
+ }
115908
+ return state.errors?.[routeId];
115909
+ }
115910
+ function useNavigateStable() {
115911
+ let { router } = useDataRouterContext("useNavigate" /* UseNavigateStable */ );
115912
+ let id = useCurrentRouteId("useNavigate" /* UseNavigateStable */ );
115913
+ let activeRef = React.useRef(false);
115914
+ useIsomorphicLayoutEffect$1(()=>{
115915
+ activeRef.current = true;
115916
+ });
115917
+ let navigate = React.useCallback(async (to, options = {})=>{
115918
+ warning(activeRef.current, navigateEffectWarning);
115919
+ if (!activeRef.current) return;
115920
+ if (typeof to === "number") {
115921
+ await router.navigate(to);
115922
+ } else {
115923
+ await router.navigate(to, {
115924
+ fromRouteId: id,
115925
+ ...options
115926
+ });
115927
+ }
115928
+ }, [
115929
+ router,
115930
+ id
115931
+ ]);
115932
+ return navigate;
115933
+ }
115934
+ var alreadyWarned = {};
115935
+ function warningOnce(key, cond, message) {
115936
+ if (!cond && !alreadyWarned[key]) {
115937
+ alreadyWarned[key] = true;
115938
+ warning(false, message);
115939
+ }
115940
+ }
115941
+ React.memo(DataRoutes);
115942
+ function DataRoutes({ routes, future, state, isStatic, onError }) {
115943
+ return useRoutesImpl(routes, void 0, {
115944
+ state,
115945
+ isStatic,
115946
+ onError});
115947
+ }
115948
+ // lib/dom/dom.ts
115949
+ var defaultMethod = "get";
115950
+ var defaultEncType = "application/x-www-form-urlencoded";
115951
+ function isHtmlElement(object) {
115952
+ return typeof HTMLElement !== "undefined" && object instanceof HTMLElement;
115953
+ }
115954
+ function isButtonElement(object) {
115955
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
115956
+ }
115957
+ function isFormElement(object) {
115958
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
115959
+ }
115960
+ function isInputElement(object) {
115961
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
115962
+ }
115963
+ function isModifiedEvent(event) {
115964
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
115965
+ }
115966
+ function shouldProcessLinkClick(event, target) {
115967
+ return event.button === 0 && // Ignore everything but left clicks
115968
+ (!target || target === "_self") && // Let browser handle "target=_blank" etc.
115969
+ !isModifiedEvent(event);
115970
+ }
115971
+ function createSearchParams(init = "") {
115972
+ return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key)=>{
115973
+ let value = init[key];
115974
+ return memo2.concat(Array.isArray(value) ? value.map((v)=>[
115975
+ key,
115976
+ v
115977
+ ]) : [
115978
+ [
115979
+ key,
115980
+ value
115981
+ ]
115982
+ ]);
115983
+ }, []));
115984
+ }
115985
+ function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
115986
+ let searchParams = createSearchParams(locationSearch);
115987
+ if (defaultSearchParams) {
115988
+ defaultSearchParams.forEach((_, key)=>{
115989
+ if (!searchParams.has(key)) {
115990
+ defaultSearchParams.getAll(key).forEach((value)=>{
115991
+ searchParams.append(key, value);
115992
+ });
115993
+ }
115994
+ });
115995
+ }
115996
+ return searchParams;
115997
+ }
115998
+ var _formDataSupportsSubmitter = null;
115999
+ function isFormDataSubmitterSupported() {
116000
+ if (_formDataSupportsSubmitter === null) {
116001
+ try {
116002
+ new FormData(document.createElement("form"), // @ts-expect-error if FormData supports the submitter parameter, this will throw
116003
+ 0);
116004
+ _formDataSupportsSubmitter = false;
116005
+ } catch (e) {
116006
+ _formDataSupportsSubmitter = true;
116007
+ }
116008
+ }
116009
+ return _formDataSupportsSubmitter;
116010
+ }
116011
+ var supportedFormEncTypes = /* @__PURE__ */ new Set([
116012
+ "application/x-www-form-urlencoded",
116013
+ "multipart/form-data",
116014
+ "text/plain"
116015
+ ]);
116016
+ function getFormEncType(encType) {
116017
+ if (encType != null && !supportedFormEncTypes.has(encType)) {
116018
+ warning(false, `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`);
116019
+ return null;
116020
+ }
116021
+ return encType;
116022
+ }
116023
+ function getFormSubmissionInfo(target, basename) {
116024
+ let method;
116025
+ let action;
116026
+ let encType;
116027
+ let formData;
116028
+ let body;
116029
+ if (isFormElement(target)) {
116030
+ let attr = target.getAttribute("action");
116031
+ action = attr ? stripBasename(attr, basename) : null;
116032
+ method = target.getAttribute("method") || defaultMethod;
116033
+ encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
116034
+ formData = new FormData(target);
116035
+ } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
116036
+ let form = target.form;
116037
+ if (form == null) {
116038
+ throw new Error(`Cannot submit a <button> or <input type="submit"> without a <form>`);
116039
+ }
116040
+ let attr = target.getAttribute("formaction") || form.getAttribute("action");
116041
+ action = attr ? stripBasename(attr, basename) : null;
116042
+ method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
116043
+ encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
116044
+ formData = new FormData(form, target);
116045
+ if (!isFormDataSubmitterSupported()) {
116046
+ let { name, type, value } = target;
116047
+ if (type === "image") {
116048
+ let prefix = name ? `${name}.` : "";
116049
+ formData.append(`${prefix}x`, "0");
116050
+ formData.append(`${prefix}y`, "0");
116051
+ } else if (name) {
116052
+ formData.append(name, value);
116053
+ }
116054
+ }
116055
+ } else if (isHtmlElement(target)) {
116056
+ throw new Error(`Cannot submit element that is not <form>, <button>, or <input type="submit|image">`);
116057
+ } else {
116058
+ method = defaultMethod;
116059
+ action = null;
116060
+ encType = defaultEncType;
116061
+ body = target;
116062
+ }
116063
+ if (formData && encType === "text/plain") {
116064
+ body = formData;
116065
+ formData = void 0;
116066
+ }
116067
+ return {
116068
+ action,
116069
+ method: method.toLowerCase(),
116070
+ encType,
116071
+ formData,
116072
+ body
116073
+ };
116074
+ }
116075
+ Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
116076
+ // lib/dom/ssr/invariant.ts
116077
+ function invariant2(value, message) {
116078
+ if (value === false || value === null || typeof value === "undefined") {
116079
+ throw new Error(message);
116080
+ }
116081
+ }
116082
+ function singleFetchUrl(reqUrl, basename, trailingSlashAware, extension) {
116083
+ let url = typeof reqUrl === "string" ? new URL(reqUrl, // This can be called during the SSR flow via PrefetchPageLinksImpl so
116084
+ // don't assume window is available
116085
+ typeof window === "undefined" ? "server://singlefetch/" : window.location.origin) : reqUrl;
116086
+ if (trailingSlashAware) {
116087
+ if (url.pathname.endsWith("/")) {
116088
+ url.pathname = `${url.pathname}_.${extension}`;
116089
+ } else {
116090
+ url.pathname = `${url.pathname}.${extension}`;
116091
+ }
116092
+ } else {
116093
+ if (url.pathname === "/") {
116094
+ url.pathname = `_root.${extension}`;
116095
+ } else if (basename && stripBasename(url.pathname, basename) === "/") {
116096
+ url.pathname = `${basename.replace(/\/$/, "")}/_root.${extension}`;
116097
+ } else {
116098
+ url.pathname = `${url.pathname.replace(/\/$/, "")}.${extension}`;
116099
+ }
116100
+ }
116101
+ return url;
116102
+ }
116103
+ // lib/dom/ssr/routeModules.ts
116104
+ async function loadRouteModule(route, routeModulesCache) {
116105
+ if (route.id in routeModulesCache) {
116106
+ return routeModulesCache[route.id];
116107
+ }
116108
+ try {
116109
+ let routeModule = await import(/* @vite-ignore */ /* webpackIgnore: true */ route.module);
116110
+ routeModulesCache[route.id] = routeModule;
116111
+ return routeModule;
116112
+ } catch (error) {
116113
+ console.error(`Error loading route module \`${route.module}\`, reloading page...`);
116114
+ console.error(error);
116115
+ if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
116116
+ import.meta.hot) {
116117
+ throw error;
116118
+ }
116119
+ window.location.reload();
116120
+ return new Promise(()=>{});
116121
+ }
116122
+ }
116123
+ function isHtmlLinkDescriptor(object) {
116124
+ if (object == null) {
116125
+ return false;
116126
+ }
116127
+ if (object.href == null) {
116128
+ return object.rel === "preload" && typeof object.imageSrcSet === "string" && typeof object.imageSizes === "string";
116129
+ }
116130
+ return typeof object.rel === "string" && typeof object.href === "string";
116131
+ }
116132
+ async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
116133
+ let links = await Promise.all(matches.map(async (match)=>{
116134
+ let route = manifest.routes[match.route.id];
116135
+ if (route) {
116136
+ let mod = await loadRouteModule(route, routeModules);
116137
+ return mod.links ? mod.links() : [];
116138
+ }
116139
+ return [];
116140
+ }));
116141
+ return dedupeLinkDescriptors(links.flat(1).filter(isHtmlLinkDescriptor).filter((link)=>link.rel === "stylesheet" || link.rel === "preload").map((link)=>link.rel === "stylesheet" ? {
116142
+ ...link,
116143
+ rel: "prefetch",
116144
+ as: "style"
116145
+ } : {
116146
+ ...link,
116147
+ rel: "prefetch"
116148
+ }));
116149
+ }
116150
+ function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
116151
+ let isNew = (match, index)=>{
116152
+ if (!currentMatches[index]) return true;
116153
+ return match.route.id !== currentMatches[index].route.id;
116154
+ };
116155
+ let matchPathChanged = (match, index)=>{
116156
+ return(// param change, /users/123 -> /users/456
116157
+ currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path
116158
+ // e.g. /files/images/avatar.jpg -> files/finances.xls
116159
+ currentMatches[index].route.path?.endsWith("*") && currentMatches[index].params["*"] !== match.params["*"]);
116160
+ };
116161
+ if (mode === "assets") {
116162
+ return nextMatches.filter((match, index)=>isNew(match, index) || matchPathChanged(match, index));
116163
+ }
116164
+ if (mode === "data") {
116165
+ return nextMatches.filter((match, index)=>{
116166
+ let manifestRoute = manifest.routes[match.route.id];
116167
+ if (!manifestRoute || !manifestRoute.hasLoader) {
116168
+ return false;
116169
+ }
116170
+ if (isNew(match, index) || matchPathChanged(match, index)) {
116171
+ return true;
116172
+ }
116173
+ if (match.route.shouldRevalidate) {
116174
+ let routeChoice = match.route.shouldRevalidate({
116175
+ currentUrl: new URL(location.pathname + location.search + location.hash, window.origin),
116176
+ currentParams: currentMatches[0]?.params || {},
116177
+ nextUrl: new URL(page, window.origin),
116178
+ nextParams: match.params,
116179
+ defaultShouldRevalidate: true
116180
+ });
116181
+ if (typeof routeChoice === "boolean") {
116182
+ return routeChoice;
116183
+ }
116184
+ }
116185
+ return true;
116186
+ });
116187
+ }
116188
+ return [];
116189
+ }
116190
+ function getModuleLinkHrefs(matches, manifest, { includeHydrateFallback } = {}) {
116191
+ return dedupeHrefs(matches.map((match)=>{
116192
+ let route = manifest.routes[match.route.id];
116193
+ if (!route) return [];
116194
+ let hrefs = [
116195
+ route.module
116196
+ ];
116197
+ if (route.clientActionModule) {
116198
+ hrefs = hrefs.concat(route.clientActionModule);
116199
+ }
116200
+ if (route.clientLoaderModule) {
116201
+ hrefs = hrefs.concat(route.clientLoaderModule);
116202
+ }
116203
+ if (includeHydrateFallback && route.hydrateFallbackModule) {
116204
+ hrefs = hrefs.concat(route.hydrateFallbackModule);
116205
+ }
116206
+ if (route.imports) {
116207
+ hrefs = hrefs.concat(route.imports);
116208
+ }
116209
+ return hrefs;
116210
+ }).flat(1));
116211
+ }
116212
+ function dedupeHrefs(hrefs) {
116213
+ return [
116214
+ ...new Set(hrefs)
116215
+ ];
116216
+ }
116217
+ function sortKeys(obj) {
116218
+ let sorted = {};
116219
+ let keys = Object.keys(obj).sort();
116220
+ for (let key of keys){
116221
+ sorted[key] = obj[key];
116222
+ }
116223
+ return sorted;
116224
+ }
116225
+ function dedupeLinkDescriptors(descriptors, preloads) {
116226
+ let set = /* @__PURE__ */ new Set();
116227
+ new Set(preloads);
116228
+ return descriptors.reduce((deduped, descriptor)=>{
116229
+ let key = JSON.stringify(sortKeys(descriptor));
116230
+ if (!set.has(key)) {
116231
+ set.add(key);
116232
+ deduped.push({
116233
+ key,
116234
+ link: descriptor
116235
+ });
116236
+ }
116237
+ return deduped;
116238
+ }, []);
116239
+ }
116240
+ // lib/dom/ssr/components.tsx
116241
+ function useDataRouterContext2() {
116242
+ let context = React.useContext(DataRouterContext);
116243
+ invariant2(context, "You must render this element inside a <DataRouterContext.Provider> element");
116244
+ return context;
116245
+ }
116246
+ function useDataRouterStateContext() {
116247
+ let context = React.useContext(DataRouterStateContext);
116248
+ invariant2(context, "You must render this element inside a <DataRouterStateContext.Provider> element");
116249
+ return context;
116250
+ }
116251
+ var FrameworkContext = React.createContext(void 0);
116252
+ FrameworkContext.displayName = "FrameworkContext";
116253
+ function useFrameworkContext() {
116254
+ let context = React.useContext(FrameworkContext);
116255
+ invariant2(context, "You must render this element inside a <HydratedRouter> element");
116256
+ return context;
116257
+ }
116258
+ function usePrefetchBehavior(prefetch, theirElementProps) {
116259
+ let frameworkContext = React.useContext(FrameworkContext);
116260
+ let [maybePrefetch, setMaybePrefetch] = React.useState(false);
116261
+ let [shouldPrefetch, setShouldPrefetch] = React.useState(false);
116262
+ let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
116263
+ let ref = React.useRef(null);
116264
+ React.useEffect(()=>{
116265
+ if (prefetch === "render") {
116266
+ setShouldPrefetch(true);
116267
+ }
116268
+ if (prefetch === "viewport") {
116269
+ let callback = (entries)=>{
116270
+ entries.forEach((entry)=>{
116271
+ setShouldPrefetch(entry.isIntersecting);
116272
+ });
116273
+ };
116274
+ let observer = new IntersectionObserver(callback, {
116275
+ threshold: 0.5
116276
+ });
116277
+ if (ref.current) observer.observe(ref.current);
116278
+ return ()=>{
116279
+ observer.disconnect();
116280
+ };
116281
+ }
116282
+ }, [
116283
+ prefetch
116284
+ ]);
116285
+ React.useEffect(()=>{
116286
+ if (maybePrefetch) {
116287
+ let id = setTimeout(()=>{
116288
+ setShouldPrefetch(true);
116289
+ }, 100);
116290
+ return ()=>{
116291
+ clearTimeout(id);
116292
+ };
116293
+ }
116294
+ }, [
116295
+ maybePrefetch
116296
+ ]);
116297
+ let setIntent = ()=>{
116298
+ setMaybePrefetch(true);
116299
+ };
116300
+ let cancelIntent = ()=>{
116301
+ setMaybePrefetch(false);
116302
+ setShouldPrefetch(false);
116303
+ };
116304
+ if (!frameworkContext) {
116305
+ return [
116306
+ false,
116307
+ ref,
116308
+ {}
116309
+ ];
116310
+ }
116311
+ if (prefetch !== "intent") {
116312
+ return [
116313
+ shouldPrefetch,
116314
+ ref,
116315
+ {}
116316
+ ];
116317
+ }
116318
+ return [
116319
+ shouldPrefetch,
116320
+ ref,
116321
+ {
116322
+ onFocus: composeEventHandlers(onFocus, setIntent),
116323
+ onBlur: composeEventHandlers(onBlur, cancelIntent),
116324
+ onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
116325
+ onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
116326
+ onTouchStart: composeEventHandlers(onTouchStart, setIntent)
116327
+ }
116328
+ ];
116329
+ }
116330
+ function composeEventHandlers(theirHandler, ourHandler) {
116331
+ return (event)=>{
116332
+ theirHandler && theirHandler(event);
116333
+ if (!event.defaultPrevented) {
116334
+ ourHandler(event);
116335
+ }
116336
+ };
116337
+ }
116338
+ function PrefetchPageLinks({ page, ...linkProps }) {
116339
+ let { router } = useDataRouterContext2();
116340
+ let matches = React.useMemo(()=>matchRoutes(router.routes, page, router.basename), [
116341
+ router.routes,
116342
+ page,
116343
+ router.basename
116344
+ ]);
116345
+ if (!matches) {
116346
+ return null;
116347
+ }
116348
+ return /* @__PURE__ */ React.createElement(PrefetchPageLinksImpl, {
116349
+ page,
116350
+ matches,
116351
+ ...linkProps
116352
+ });
116353
+ }
116354
+ function useKeyedPrefetchLinks(matches) {
116355
+ let { manifest, routeModules } = useFrameworkContext();
116356
+ let [keyedPrefetchLinks, setKeyedPrefetchLinks] = React.useState([]);
116357
+ React.useEffect(()=>{
116358
+ let interrupted = false;
116359
+ void getKeyedPrefetchLinks(matches, manifest, routeModules).then((links)=>{
116360
+ if (!interrupted) {
116361
+ setKeyedPrefetchLinks(links);
116362
+ }
116363
+ });
116364
+ return ()=>{
116365
+ interrupted = true;
116366
+ };
116367
+ }, [
116368
+ matches,
116369
+ manifest,
116370
+ routeModules
116371
+ ]);
116372
+ return keyedPrefetchLinks;
116373
+ }
116374
+ function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
116375
+ let location = useLocation();
116376
+ let { future, manifest, routeModules } = useFrameworkContext();
116377
+ let { basename } = useDataRouterContext2();
116378
+ let { loaderData, matches } = useDataRouterStateContext();
116379
+ let newMatchesForData = React.useMemo(()=>getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [
116380
+ page,
116381
+ nextMatches,
116382
+ matches,
116383
+ manifest,
116384
+ location
116385
+ ]);
116386
+ let newMatchesForAssets = React.useMemo(()=>getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [
116387
+ page,
116388
+ nextMatches,
116389
+ matches,
116390
+ manifest,
116391
+ location
116392
+ ]);
116393
+ let dataHrefs = React.useMemo(()=>{
116394
+ if (page === location.pathname + location.search + location.hash) {
116395
+ return [];
116396
+ }
116397
+ let routesParams = /* @__PURE__ */ new Set();
116398
+ let foundOptOutRoute = false;
116399
+ nextMatches.forEach((m)=>{
116400
+ let manifestRoute = manifest.routes[m.route.id];
116401
+ if (!manifestRoute || !manifestRoute.hasLoader) {
116402
+ return;
116403
+ }
116404
+ if (!newMatchesForData.some((m2)=>m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) {
116405
+ foundOptOutRoute = true;
116406
+ } else if (manifestRoute.hasClientLoader) {
116407
+ foundOptOutRoute = true;
116408
+ } else {
116409
+ routesParams.add(m.route.id);
116410
+ }
116411
+ });
116412
+ if (routesParams.size === 0) {
116413
+ return [];
116414
+ }
116415
+ let url = singleFetchUrl(page, basename, future.unstable_trailingSlashAwareDataRequests, "data");
116416
+ if (foundOptOutRoute && routesParams.size > 0) {
116417
+ url.searchParams.set("_routes", nextMatches.filter((m)=>routesParams.has(m.route.id)).map((m)=>m.route.id).join(","));
116418
+ }
116419
+ return [
116420
+ url.pathname + url.search
116421
+ ];
116422
+ }, [
116423
+ basename,
116424
+ future.unstable_trailingSlashAwareDataRequests,
116425
+ loaderData,
116426
+ location,
116427
+ manifest,
116428
+ newMatchesForData,
116429
+ nextMatches,
116430
+ page,
116431
+ routeModules
116432
+ ]);
116433
+ let moduleHrefs = React.useMemo(()=>getModuleLinkHrefs(newMatchesForAssets, manifest), [
116434
+ newMatchesForAssets,
116435
+ manifest
116436
+ ]);
116437
+ let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
116438
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, dataHrefs.map((href)=>/* @__PURE__ */ React.createElement("link", {
116439
+ key: href,
116440
+ rel: "prefetch",
116441
+ as: "fetch",
116442
+ href,
116443
+ ...linkProps
116444
+ })), moduleHrefs.map((href)=>/* @__PURE__ */ React.createElement("link", {
116445
+ key: href,
116446
+ rel: "modulepreload",
116447
+ href,
116448
+ ...linkProps
116449
+ })), keyedPrefetchLinks.map(({ key, link })=>// these don't spread `linkProps` because they are full link descriptors
116450
+ // already with their own props
116451
+ /* @__PURE__ */ React.createElement("link", {
116452
+ key,
116453
+ nonce: linkProps.nonce,
116454
+ ...link,
116455
+ crossOrigin: link.crossOrigin ?? linkProps.crossOrigin
116456
+ })));
116457
+ }
116458
+ function mergeRefs(...refs) {
116459
+ return (value)=>{
116460
+ refs.forEach((ref)=>{
116461
+ if (typeof ref === "function") {
116462
+ ref(value);
116463
+ } else if (ref != null) {
116464
+ ref.current = value;
116465
+ }
116466
+ });
116467
+ };
116468
+ }
116469
+ var isBrowser2 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
116470
+ try {
116471
+ if (isBrowser2) {
116472
+ window.__reactRouterVersion = "7.13.1";
116473
+ }
116474
+ } catch (e) {}
116475
+ var ABSOLUTE_URL_REGEX2 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
116476
+ var Link = React.forwardRef(function LinkWithRef({ onClick, discover = "render", prefetch = "none", relative, reloadDocument, replace: replace2, unstable_mask, state, target, to, preventScrollReset, viewTransition, unstable_defaultShouldRevalidate, ...rest }, forwardedRef) {
116477
+ let { basename, navigator, unstable_useTransitions } = React.useContext(NavigationContext);
116478
+ let isAbsolute = typeof to === "string" && ABSOLUTE_URL_REGEX2.test(to);
116479
+ let parsed = parseToInfo(to, basename);
116480
+ to = parsed.to;
116481
+ let href = useHref(to, {
116482
+ relative
116483
+ });
116484
+ let location = useLocation();
116485
+ let maskedHref = null;
116486
+ if (unstable_mask) {
116487
+ let resolved = resolveTo(unstable_mask, [], location.unstable_mask ? location.unstable_mask.pathname : "/", true);
116488
+ if (basename !== "/") {
116489
+ resolved.pathname = resolved.pathname === "/" ? basename : joinPaths([
116490
+ basename,
116491
+ resolved.pathname
116492
+ ]);
116493
+ }
116494
+ maskedHref = navigator.createHref(resolved);
116495
+ }
116496
+ let [shouldPrefetch, prefetchRef, prefetchHandlers] = usePrefetchBehavior(prefetch, rest);
116497
+ let internalOnClick = useLinkClickHandler(to, {
116498
+ replace: replace2,
116499
+ unstable_mask,
116500
+ state,
116501
+ target,
116502
+ preventScrollReset,
116503
+ relative,
116504
+ viewTransition,
116505
+ unstable_defaultShouldRevalidate,
116506
+ unstable_useTransitions
116507
+ });
116508
+ function handleClick(event) {
116509
+ if (onClick) onClick(event);
116510
+ if (!event.defaultPrevented) {
116511
+ internalOnClick(event);
116512
+ }
116513
+ }
116514
+ let isSpaLink = !(parsed.isExternal || reloadDocument);
116515
+ let link = // eslint-disable-next-line jsx-a11y/anchor-has-content
116516
+ /* @__PURE__ */ React.createElement("a", {
116517
+ ...rest,
116518
+ ...prefetchHandlers,
116519
+ href: (isSpaLink ? maskedHref : void 0) || parsed.absoluteURL || href,
116520
+ onClick: isSpaLink ? handleClick : onClick,
116521
+ ref: mergeRefs(forwardedRef, prefetchRef),
116522
+ target,
116523
+ "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
116524
+ });
116525
+ return shouldPrefetch && !isAbsolute ? /* @__PURE__ */ React.createElement(React.Fragment, null, link, /* @__PURE__ */ React.createElement(PrefetchPageLinks, {
116526
+ page: href
116527
+ })) : link;
116528
+ });
116529
+ Link.displayName = "Link";
116530
+ var NavLink = React.forwardRef(function NavLinkWithRef({ "aria-current": ariaCurrentProp = "page", caseSensitive = false, className: classNameProp = "", end = false, style: styleProp, to, viewTransition, children, ...rest }, ref) {
116531
+ let path = useResolvedPath(to, {
116532
+ relative: rest.relative
116533
+ });
116534
+ let location = useLocation();
116535
+ let routerState = React.useContext(DataRouterStateContext);
116536
+ let { navigator, basename } = React.useContext(NavigationContext);
116537
+ let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
116538
+ // eslint-disable-next-line react-hooks/rules-of-hooks
116539
+ useViewTransitionState(path) && viewTransition === true;
116540
+ let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
116541
+ let locationPathname = location.pathname;
116542
+ let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
116543
+ if (!caseSensitive) {
116544
+ locationPathname = locationPathname.toLowerCase();
116545
+ nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
116546
+ toPathname = toPathname.toLowerCase();
116547
+ }
116548
+ if (nextLocationPathname && basename) {
116549
+ nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
116550
+ }
116551
+ const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
116552
+ let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
116553
+ let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
116554
+ let renderProps = {
116555
+ isActive,
116556
+ isPending,
116557
+ isTransitioning
116558
+ };
116559
+ let ariaCurrent = isActive ? ariaCurrentProp : void 0;
116560
+ let className;
116561
+ if (typeof classNameProp === "function") {
116562
+ className = classNameProp(renderProps);
116563
+ } else {
116564
+ className = [
116565
+ classNameProp,
116566
+ isActive ? "active" : null,
116567
+ isPending ? "pending" : null,
116568
+ isTransitioning ? "transitioning" : null
116569
+ ].filter(Boolean).join(" ");
116570
+ }
116571
+ let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
116572
+ return /* @__PURE__ */ React.createElement(Link, {
116573
+ ...rest,
116574
+ "aria-current": ariaCurrent,
116575
+ className,
116576
+ ref,
116577
+ style,
116578
+ to,
116579
+ viewTransition
116580
+ }, typeof children === "function" ? children(renderProps) : children);
116581
+ });
116582
+ NavLink.displayName = "NavLink";
116583
+ var Form = React.forwardRef(({ discover = "render", fetcherKey, navigate, reloadDocument, replace: replace2, state, method = defaultMethod, action, onSubmit, relative, preventScrollReset, viewTransition, unstable_defaultShouldRevalidate, ...props }, forwardedRef)=>{
116584
+ let { unstable_useTransitions } = React.useContext(NavigationContext);
116585
+ let submit = useSubmit();
116586
+ let formAction = useFormAction(action, {
116587
+ relative
116588
+ });
116589
+ let formMethod = method.toLowerCase() === "get" ? "get" : "post";
116590
+ let isAbsolute = typeof action === "string" && ABSOLUTE_URL_REGEX2.test(action);
116591
+ let submitHandler = (event)=>{
116592
+ onSubmit && onSubmit(event);
116593
+ if (event.defaultPrevented) return;
116594
+ event.preventDefault();
116595
+ let submitter = event.nativeEvent.submitter;
116596
+ let submitMethod = submitter?.getAttribute("formmethod") || method;
116597
+ let doSubmit = ()=>submit(submitter || event.currentTarget, {
116598
+ fetcherKey,
116599
+ method: submitMethod,
116600
+ navigate,
116601
+ replace: replace2,
116602
+ state,
116603
+ relative,
116604
+ preventScrollReset,
116605
+ viewTransition,
116606
+ unstable_defaultShouldRevalidate
116607
+ });
116608
+ if (unstable_useTransitions && navigate !== false) {
116609
+ React.startTransition(()=>doSubmit());
116610
+ } else {
116611
+ doSubmit();
116612
+ }
116613
+ };
116614
+ return /* @__PURE__ */ React.createElement("form", {
116615
+ ref: forwardedRef,
116616
+ method: formMethod,
116617
+ action: formAction,
116618
+ onSubmit: reloadDocument ? onSubmit : submitHandler,
116619
+ ...props,
116620
+ "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
116621
+ });
116622
+ });
116623
+ Form.displayName = "Form";
116624
+ function getDataRouterConsoleError2(hookName) {
116625
+ return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
116626
+ }
116627
+ function useDataRouterContext3(hookName) {
116628
+ let ctx = React.useContext(DataRouterContext);
116629
+ invariant(ctx, getDataRouterConsoleError2(hookName));
116630
+ return ctx;
116631
+ }
116632
+ function useLinkClickHandler(to, { target, replace: replaceProp, unstable_mask, state, preventScrollReset, relative, viewTransition, unstable_defaultShouldRevalidate, unstable_useTransitions } = {}) {
116633
+ let navigate = useNavigate();
116634
+ let location = useLocation();
116635
+ let path = useResolvedPath(to, {
116636
+ relative
116637
+ });
116638
+ return React.useCallback((event)=>{
116639
+ if (shouldProcessLinkClick(event, target)) {
116640
+ event.preventDefault();
116641
+ let replace2 = replaceProp !== void 0 ? replaceProp : createPath(location) === createPath(path);
116642
+ let doNavigate = ()=>navigate(to, {
116643
+ replace: replace2,
116644
+ unstable_mask,
116645
+ state,
116646
+ preventScrollReset,
116647
+ relative,
116648
+ viewTransition,
116649
+ unstable_defaultShouldRevalidate
116650
+ });
116651
+ if (unstable_useTransitions) {
116652
+ React.startTransition(()=>doNavigate());
116653
+ } else {
116654
+ doNavigate();
116655
+ }
116656
+ }
116657
+ }, [
116658
+ location,
116659
+ navigate,
116660
+ path,
116661
+ replaceProp,
116662
+ unstable_mask,
116663
+ state,
116664
+ target,
116665
+ to,
116666
+ preventScrollReset,
116667
+ relative,
116668
+ viewTransition,
116669
+ unstable_defaultShouldRevalidate,
116670
+ unstable_useTransitions
116671
+ ]);
116672
+ }
116673
+ function useSearchParams(defaultInit) {
116674
+ warning(typeof URLSearchParams !== "undefined", `You cannot use the \`useSearchParams\` hook in a browser that does not support the URLSearchParams API. If you need to support Internet Explorer 11, we recommend you load a polyfill such as https://github.com/ungap/url-search-params.`);
116675
+ let defaultSearchParamsRef = React.useRef(createSearchParams(defaultInit));
116676
+ let hasSetSearchParamsRef = React.useRef(false);
116677
+ let location = useLocation();
116678
+ let searchParams = React.useMemo(()=>// Only merge in the defaults if we haven't yet called setSearchParams.
116679
+ // Once we call that we want those to take precedence, otherwise you can't
116680
+ // remove a param with setSearchParams({}) if it has an initial value
116681
+ getSearchParamsForLocation(location.search, hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current), [
116682
+ location.search
116683
+ ]);
116684
+ let navigate = useNavigate();
116685
+ let setSearchParams = React.useCallback((nextInit, navigateOptions)=>{
116686
+ const newSearchParams = createSearchParams(typeof nextInit === "function" ? nextInit(new URLSearchParams(searchParams)) : nextInit);
116687
+ hasSetSearchParamsRef.current = true;
116688
+ navigate("?" + newSearchParams, navigateOptions);
116689
+ }, [
116690
+ navigate,
116691
+ searchParams
116692
+ ]);
116693
+ return [
116694
+ searchParams,
116695
+ setSearchParams
116696
+ ];
116697
+ }
116698
+ var fetcherId = 0;
116699
+ var getUniqueFetcherId = ()=>`__${String(++fetcherId)}__`;
116700
+ function useSubmit() {
116701
+ let { router } = useDataRouterContext3("useSubmit" /* UseSubmit */ );
116702
+ let { basename } = React.useContext(NavigationContext);
116703
+ let currentRouteId = useRouteId();
116704
+ let routerFetch = router.fetch;
116705
+ let routerNavigate = router.navigate;
116706
+ return React.useCallback(async (target, options = {})=>{
116707
+ let { action, method, encType, formData, body } = getFormSubmissionInfo(target, basename);
116708
+ if (options.navigate === false) {
116709
+ let key = options.fetcherKey || getUniqueFetcherId();
116710
+ await routerFetch(key, currentRouteId, options.action || action, {
116711
+ unstable_defaultShouldRevalidate: options.unstable_defaultShouldRevalidate,
116712
+ preventScrollReset: options.preventScrollReset,
116713
+ formData,
116714
+ body,
116715
+ formMethod: options.method || method,
116716
+ formEncType: options.encType || encType,
116717
+ flushSync: options.flushSync
116718
+ });
116719
+ } else {
116720
+ await routerNavigate(options.action || action, {
116721
+ unstable_defaultShouldRevalidate: options.unstable_defaultShouldRevalidate,
116722
+ preventScrollReset: options.preventScrollReset,
116723
+ formData,
116724
+ body,
116725
+ formMethod: options.method || method,
116726
+ formEncType: options.encType || encType,
116727
+ replace: options.replace,
116728
+ state: options.state,
116729
+ fromRouteId: currentRouteId,
116730
+ flushSync: options.flushSync,
116731
+ viewTransition: options.viewTransition
116732
+ });
116733
+ }
116734
+ }, [
116735
+ routerFetch,
116736
+ routerNavigate,
116737
+ basename,
116738
+ currentRouteId
116739
+ ]);
116740
+ }
116741
+ function useFormAction(action, { relative } = {}) {
116742
+ let { basename } = React.useContext(NavigationContext);
116743
+ let routeContext = React.useContext(RouteContext);
116744
+ invariant(routeContext, "useFormAction must be used inside a RouteContext");
116745
+ let [match] = routeContext.matches.slice(-1);
116746
+ let path = {
116747
+ ...useResolvedPath(action ? action : ".", {
116748
+ relative
116749
+ })
116750
+ };
116751
+ let location = useLocation();
116752
+ if (action == null) {
116753
+ path.search = location.search;
116754
+ let params = new URLSearchParams(path.search);
116755
+ let indexValues = params.getAll("index");
116756
+ let hasNakedIndexParam = indexValues.some((v)=>v === "");
116757
+ if (hasNakedIndexParam) {
116758
+ params.delete("index");
116759
+ indexValues.filter((v)=>v).forEach((v)=>params.append("index", v));
116760
+ let qs = params.toString();
116761
+ path.search = qs ? `?${qs}` : "";
116762
+ }
116763
+ }
116764
+ if ((!action || action === ".") && match.route.index) {
116765
+ path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
116766
+ }
116767
+ if (basename !== "/") {
116768
+ path.pathname = path.pathname === "/" ? basename : joinPaths([
116769
+ basename,
116770
+ path.pathname
116771
+ ]);
116772
+ }
116773
+ return createPath(path);
116774
+ }
116775
+ function useViewTransitionState(to, { relative } = {}) {
116776
+ let vtContext = React.useContext(ViewTransitionContext);
116777
+ invariant(vtContext != null, "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");
116778
+ let { basename } = useDataRouterContext3("useViewTransitionState" /* useViewTransitionState */ );
116779
+ let path = useResolvedPath(to, {
116780
+ relative
116781
+ });
116782
+ if (!vtContext.isTransitioning) {
116783
+ return false;
116784
+ }
116785
+ let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
116786
+ let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
116787
+ return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
116788
+ }
116789
+
116790
+ const EvaluationsMockContext = /*#__PURE__*/ createContext(undefined);
116791
+ const useEvaluationsMock = ()=>{
116792
+ return useContext(EvaluationsMockContext);
116793
+ };
116794
+
116795
+ const API_BASE = "/api";
116796
+ const useEvaluations = ()=>{
116797
+ const mockContext = useEvaluationsMock();
116798
+ const [evaluations, setEvaluations] = useState([]);
116799
+ const [loading, setLoading] = useState(false);
116800
+ const [error, setError] = useState(null);
116801
+ const fetchEvaluations = useCallback(async ()=>{
116802
+ setLoading(true);
116803
+ setError(null);
116804
+ try {
116805
+ // Check for mock data first
116806
+ if (mockContext?.mockEvaluations) {
116807
+ setEvaluations(mockContext.mockEvaluations);
116808
+ setLoading(false);
116809
+ return;
116810
+ }
116811
+ // Otherwise fetch from API (returns raw DTO)
116812
+ const response = await fetch(`${API_BASE}/evaluations`);
116813
+ if (!response.ok) {
116814
+ throw new Error(`HTTP error! status: ${response.status}`);
116815
+ }
116816
+ const data = await response.json();
116817
+ // Handle edge cases: null/undefined or not an array
116818
+ if (!data || !Array.isArray(data)) {
116819
+ setEvaluations([]);
116820
+ return;
116821
+ }
116822
+ setEvaluations(data);
116823
+ } catch (err) {
116824
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
116825
+ setError(errorMessage);
116826
+ setEvaluations([]);
116827
+ } finally{
116828
+ setLoading(false);
116829
+ }
116830
+ }, [
116831
+ mockContext
116832
+ ]);
116833
+ useEffect(()=>{
116834
+ fetchEvaluations();
116835
+ }, [
116836
+ fetchEvaluations
116837
+ ]);
116838
+ return {
116839
+ evaluations,
116840
+ loading,
116841
+ error,
116842
+ refetch: fetchEvaluations
116843
+ };
116844
+ };
116845
+
116846
+ const EvaluationsComparePage = ({ backHref = "#/evaluations" })=>{
116847
+ const { evaluations, loading, error } = useEvaluations();
116848
+ const [searchParams, setSearchParams] = useSearchParams();
116849
+ const normalizedEvaluations = React__default.useMemo(()=>evaluations.map((e)=>isEvaluationDto(e) ? transformEvaluation(e) : e), [
116850
+ evaluations
116851
+ ]);
116852
+ // Support compare=id1,id2 (primary) and legacy evaluationId1/evaluationId2, source/target
116853
+ const [evaluationId1, evaluationId2] = React__default.useMemo(()=>{
116854
+ const compareParam = searchParams.get("compare");
116855
+ if (compareParam) {
116856
+ const [id1, id2] = compareParam.split(",").map((s)=>s.trim()).filter(Boolean);
116857
+ return [
116858
+ id1 ?? null,
116859
+ id2 ?? null
116860
+ ];
116861
+ }
116862
+ const id1 = searchParams.get("evaluationId1") ?? searchParams.get("source");
116863
+ const id2 = searchParams.get("evaluationId2") ?? searchParams.get("target");
116864
+ return [
116865
+ id1,
116866
+ id2
116867
+ ];
116868
+ }, [
116869
+ searchParams
116870
+ ]);
116871
+ const updateCompareParam = React__default.useCallback((id1, id2)=>{
116872
+ const newParams = new URLSearchParams(searchParams);
116873
+ newParams.delete("evaluationId1");
116874
+ newParams.delete("evaluationId2");
116875
+ newParams.delete("source");
116876
+ newParams.delete("target");
116877
+ if (id1 && id2) {
116878
+ newParams.set("compare", `${id1},${id2}`);
116879
+ } else {
116880
+ newParams.delete("compare");
116881
+ }
116882
+ setSearchParams(newParams, {
116883
+ replace: true
116884
+ });
116885
+ }, [
116886
+ searchParams,
116887
+ setSearchParams
116888
+ ]);
116889
+ const handleEvaluationId1Change = (id)=>{
116890
+ updateCompareParam(id, evaluationId2);
116891
+ };
116892
+ const handleEvaluationId2Change = (id)=>{
116893
+ updateCompareParam(evaluationId1, id);
116894
+ };
116895
+ if (error) {
116896
+ return /*#__PURE__*/ React__default.createElement("div", {
116897
+ style: {
116898
+ padding: "24px",
116899
+ textAlign: "center"
116900
+ }
116901
+ }, /*#__PURE__*/ React__default.createElement("p", {
116902
+ style: {
116903
+ color: "red"
116904
+ }
116905
+ }, "Error loading evaluations: ", error));
116906
+ }
116907
+ return /*#__PURE__*/ React__default.createElement("div", {
116908
+ style: {
116909
+ padding: "24px"
116910
+ }
116911
+ }, /*#__PURE__*/ React__default.createElement("h1", {
116912
+ style: {
116913
+ margin: "0 0 24px 0",
116914
+ fontSize: "24px",
116915
+ fontWeight: 600
116916
+ }
116917
+ }, "Compare Evaluations"), /*#__PURE__*/ React__default.createElement(EvaluationsCompareView, {
116918
+ evaluations: normalizedEvaluations,
116919
+ evaluationId1: evaluationId1,
116920
+ evaluationId2: evaluationId2,
116921
+ onEvaluationId1Change: handleEvaluationId1Change,
116922
+ onEvaluationId2Change: handleEvaluationId2Change,
116923
+ loading: loading,
116924
+ showEvaluationComparisonDropdowns: true,
116925
+ backHref: backHref
116926
+ }));
116927
+ };
116928
+
114390
116929
  function isLLMNode(n) {
114391
116930
  return isLLMResult(n);
114392
116931
  }
@@ -117549,6 +120088,15 @@ const GlobalStyles = ()=>{
117549
120088
  border-bottom-right-radius: 0.5rem !important;
117550
120089
  }
117551
120090
 
120091
+ /* Evaluations compare: highlight rows with differing values */
120092
+ .ant-table-tbody > tr.evaluations-compare-diff-row > td {
120093
+ background-color: #fef9c3 !important;
120094
+ }
120095
+
120096
+ html.dark .ant-table-tbody > tr.evaluations-compare-diff-row > td {
120097
+ background-color: #334155 !important;
120098
+ }
120099
+
117552
120100
  /* CSS Variables for backward compatibility */
117553
120101
  :root {
117554
120102
  --background: #ffffff;
@@ -117736,4 +120284,4 @@ const GlobalStyles = ()=>{
117736
120284
  return getSafeColor(props.theme, path, fallback);
117737
120285
  };
117738
120286
 
117739
- export { AgenticFlowVisualizer, AnthropicIcon, AppleIcon, Badge, Drawer, Edge, EvaluationDetailsDrawer, EvaluationsCompare, EvaluationsTable, EvaluatorResult, GlobalStyles, GoogleIcon, JsonTreeViewer, Node$1 as Node, OllamaIcon, OpenAIIcon, SafeThemeProvider, SessionDetails, Sheet, ThemeProvider, Timeline, Visualizer, calculateAutoLayout, cn, conditionalStyle, createSafeTheme, darkTheme, defaultTheme$1 as defaultTheme, detectContentType, formatCurrency, formatDateFriendly, formatDateRelative, formatDateShort, formatDuration, formatLatency, formatMetricValue, formatNumberWithCommas, formatToolCalls, getColor, getSafeColor, getSafeSpacing, getSafeThemeValue, getSpacing, getStatusColor, isEvaluationDto, lightTheme, safeStyled, safeThemeColor, safeThemeSpacing, safeThemeValue, toTitleCase, transformEvaluation, truncateText, useComponentTheme, useSafeTheme, useTheme$1 as useTheme, useThemeValue };
120287
+ export { AgenticFlowVisualizer, AnthropicIcon, AppleIcon, Badge, Drawer, Edge, EvaluationDetailsDrawer, EvaluationsCompareDrawer, EvaluationsComparePage, EvaluationsCompareView, EvaluationsTable, EvaluatorResult, GlobalStyles, GoogleIcon, JsonTreeViewer, Node$1 as Node, OllamaIcon, OpenAIIcon, SafeThemeProvider, SessionDetails, Sheet, ThemeProvider, Timeline, Visualizer, calculateAutoLayout, cn, conditionalStyle, createSafeTheme, darkTheme, defaultTheme$1 as defaultTheme, detectContentType, evaluationsHaveSameMetrics, formatCurrency, formatDateFriendly, formatDateRelative, formatDateShort, formatDuration, formatLatency, formatMetricValue$1 as formatMetricValue, formatNumberWithCommas, formatToolCalls, getColor, getSafeColor, getSafeSpacing, getSafeThemeValue, getSpacing, getStatusColor, isEvaluationDto, lightTheme, safeStyled, safeThemeColor, safeThemeSpacing, safeThemeValue, toTitleCase, transformEvaluation, truncateText, useComponentTheme, useSafeTheme, useTheme$1 as useTheme, useThemeValue };