@railtownai/railtracks-visualizer 0.0.54 → 0.0.56

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/cjs/index.js CHANGED
@@ -8071,7 +8071,7 @@ function fixedForwardRef(render) {
8071
8071
  return React.forwardRef(render);
8072
8072
  }
8073
8073
  // we need this hook to prevent a warning when using react-flow in SSR
8074
- const useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
8074
+ const useIsomorphicLayoutEffect$3 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
8075
8075
  /**
8076
8076
  * This hook returns a queue that can be used to batch updates.
8077
8077
  *
@@ -8096,7 +8096,7 @@ const useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? React.useLay
8096
8096
  * Layout effects are guaranteed to run before the next render which means we
8097
8097
  * shouldn't run into any issues with stale state or weird issues that come from
8098
8098
  * rendering things one frame later than expected (we used to use `setTimeout`).
8099
- */ useIsomorphicLayoutEffect$2(()=>{
8099
+ */ useIsomorphicLayoutEffect$3(()=>{
8100
8100
  const queueItems = queue.get();
8101
8101
  if (queueItems.length) {
8102
8102
  runQueue(queueItems);
@@ -15224,7 +15224,7 @@ function requireHoistNonReactStatics_cjs() {
15224
15224
 
15225
15225
  requireHoistNonReactStatics_cjs();
15226
15226
 
15227
- var isBrowser = true;
15227
+ var isBrowser$1 = true;
15228
15228
  function getRegisteredStyles(registered, registeredStyles, classNames) {
15229
15229
  var rawClassName = '';
15230
15230
  classNames.split(' ').forEach(function(className) {
@@ -15246,7 +15246,7 @@ var registerStyles = function registerStyles(cache, serialized, isStringTag) {
15246
15246
  // in node since emotion-server relies on whether a style is in
15247
15247
  // the registered cache to know whether a style is global or not
15248
15248
  // also, note that this check will be dead code eliminated in the browser
15249
- isBrowser === false) && cache.registered[className] === undefined) {
15249
+ isBrowser$1 === false) && cache.registered[className] === undefined) {
15250
15250
  cache.registered[className] = serialized.styles;
15251
15251
  }
15252
15252
  };
@@ -15894,6 +15894,21 @@ const ThemeProvider = ({ children, theme: propTheme })=>{
15894
15894
  }, [
15895
15895
  propTheme
15896
15896
  ]);
15897
+ // Sync html.dark class for GlobalStyles and other CSS that uses html.dark
15898
+ React.useEffect(()=>{
15899
+ const isDark = currentTheme === darkTheme;
15900
+ try {
15901
+ if (isDark) {
15902
+ document.documentElement.classList.add("dark");
15903
+ } else {
15904
+ document.documentElement.classList.remove("dark");
15905
+ }
15906
+ } catch (e) {
15907
+ // document might not be available (e.g. SSR)
15908
+ }
15909
+ }, [
15910
+ currentTheme
15911
+ ]);
15897
15912
  // Only listen for storage events if no theme prop is provided
15898
15913
  React.useEffect(()=>{
15899
15914
  if (propTheme) {
@@ -21001,7 +21016,7 @@ function cn(...inputs) {
21001
21016
  /**
21002
21017
  * Formats a metric value for display based on evaluator metric definitions.
21003
21018
  * Handles Categorical (index → option label), Continuous (decimal), and fallback.
21004
- */ function formatMetricValue(evaluator, metricName, value) {
21019
+ */ function formatMetricValue$1(evaluator, metricName, value) {
21005
21020
  if (value === undefined || value === null) return "-";
21006
21021
  const numericValue = typeof value === "number" ? value : Number(value);
21007
21022
  if (isNaN(numericValue)) return "-";
@@ -21644,7 +21659,7 @@ if (process.env.NODE_ENV !== 'production') {
21644
21659
  }
21645
21660
  };
21646
21661
  }
21647
- const warning = _warning;
21662
+ const warning$1 = _warning;
21648
21663
  const WarningContext = /*#__PURE__*/ React__namespace.createContext({});
21649
21664
  /**
21650
21665
  * This is a hook but we not named as `useWarning`
@@ -21668,7 +21683,7 @@ const WarningContext = /*#__PURE__*/ React__namespace.createContext({});
21668
21683
  console.warn('[antd] There exists deprecated usage in your code:', deprecatedWarnList);
21669
21684
  }
21670
21685
  } else {
21671
- process.env.NODE_ENV !== "production" ? warning(valid, component, message) : void 0;
21686
+ process.env.NODE_ENV !== "production" ? warning$1(valid, component, message) : void 0;
21672
21687
  }
21673
21688
  }
21674
21689
  };
@@ -23519,6 +23534,367 @@ const useZIndex = (componentType, customZIndex)=>{
23519
23534
  return result;
23520
23535
  };
23521
23536
 
23537
+ const genAlertTypeStyle = (bgColor, borderColor, iconColor, token, alertCls)=>({
23538
+ background: bgColor,
23539
+ border: `${cssinjs.unit(token.lineWidth)} ${token.lineType} ${borderColor}`,
23540
+ [`${alertCls}-icon`]: {
23541
+ color: iconColor
23542
+ }
23543
+ });
23544
+ const genBaseStyle$6 = (token)=>{
23545
+ const { componentCls, motionDurationSlow: duration, marginXS, marginSM, fontSize, fontSizeLG, lineHeight, borderRadiusLG: borderRadius, motionEaseInOutCirc, withDescriptionIconSize, colorText, colorTextHeading, withDescriptionPadding, defaultPadding } = token;
23546
+ return {
23547
+ [componentCls]: {
23548
+ ...resetComponent(token),
23549
+ position: 'relative',
23550
+ display: 'flex',
23551
+ alignItems: 'center',
23552
+ padding: defaultPadding,
23553
+ wordWrap: 'break-word',
23554
+ borderRadius,
23555
+ [`&${componentCls}-rtl`]: {
23556
+ direction: 'rtl'
23557
+ },
23558
+ [`${componentCls}-section`]: {
23559
+ flex: 1,
23560
+ minWidth: 0
23561
+ },
23562
+ [`${componentCls}-icon`]: {
23563
+ marginInlineEnd: marginXS,
23564
+ lineHeight: 0
23565
+ },
23566
+ '&-description': {
23567
+ display: 'none',
23568
+ fontSize,
23569
+ lineHeight
23570
+ },
23571
+ '&-title': {
23572
+ color: colorTextHeading
23573
+ },
23574
+ [`&${componentCls}-motion-leave`]: {
23575
+ overflow: 'hidden',
23576
+ opacity: 1,
23577
+ transition: [
23578
+ `max-height`,
23579
+ `opacity`,
23580
+ `padding-top`,
23581
+ `padding-bottom`,
23582
+ `margin-bottom`
23583
+ ].map((prop)=>`${prop} ${duration} ${motionEaseInOutCirc}`).join(', ')
23584
+ },
23585
+ [`&${componentCls}-motion-leave-active`]: {
23586
+ maxHeight: 0,
23587
+ marginBottom: '0 !important',
23588
+ paddingTop: 0,
23589
+ paddingBottom: 0,
23590
+ opacity: 0
23591
+ }
23592
+ },
23593
+ [`${componentCls}-with-description`]: {
23594
+ alignItems: 'flex-start',
23595
+ padding: withDescriptionPadding,
23596
+ [`${componentCls}-icon`]: {
23597
+ marginInlineEnd: marginSM,
23598
+ fontSize: withDescriptionIconSize,
23599
+ lineHeight: 0
23600
+ },
23601
+ [`${componentCls}-title`]: {
23602
+ display: 'block',
23603
+ marginBottom: marginXS,
23604
+ color: colorTextHeading,
23605
+ fontSize: fontSizeLG
23606
+ },
23607
+ [`${componentCls}-description`]: {
23608
+ display: 'block',
23609
+ color: colorText
23610
+ }
23611
+ },
23612
+ [`${componentCls}-banner`]: {
23613
+ marginBottom: 0,
23614
+ border: '0 !important',
23615
+ borderRadius: 0
23616
+ }
23617
+ };
23618
+ };
23619
+ const genTypeStyle = (token)=>{
23620
+ const { componentCls, colorSuccess, colorSuccessBorder, colorSuccessBg, colorWarning, colorWarningBorder, colorWarningBg, colorError, colorErrorBorder, colorErrorBg, colorInfo, colorInfoBorder, colorInfoBg } = token;
23621
+ return {
23622
+ [componentCls]: {
23623
+ '&-success': genAlertTypeStyle(colorSuccessBg, colorSuccessBorder, colorSuccess, token, componentCls),
23624
+ '&-info': genAlertTypeStyle(colorInfoBg, colorInfoBorder, colorInfo, token, componentCls),
23625
+ '&-warning': genAlertTypeStyle(colorWarningBg, colorWarningBorder, colorWarning, token, componentCls),
23626
+ '&-error': {
23627
+ ...genAlertTypeStyle(colorErrorBg, colorErrorBorder, colorError, token, componentCls),
23628
+ [`${componentCls}-description > pre`]: {
23629
+ margin: 0,
23630
+ padding: 0
23631
+ }
23632
+ }
23633
+ }
23634
+ };
23635
+ };
23636
+ const genActionStyle = (token)=>{
23637
+ const { componentCls, iconCls, motionDurationMid, marginXS, fontSizeIcon, colorIcon, colorIconHover } = token;
23638
+ return {
23639
+ [componentCls]: {
23640
+ '&-actions': {
23641
+ marginInlineStart: marginXS
23642
+ },
23643
+ [`${componentCls}-close-icon`]: {
23644
+ marginInlineStart: marginXS,
23645
+ padding: 0,
23646
+ overflow: 'hidden',
23647
+ fontSize: fontSizeIcon,
23648
+ lineHeight: cssinjs.unit(fontSizeIcon),
23649
+ backgroundColor: 'transparent',
23650
+ border: 'none',
23651
+ outline: 'none',
23652
+ cursor: 'pointer',
23653
+ [`${iconCls}-close`]: {
23654
+ color: colorIcon,
23655
+ transition: `color ${motionDurationMid}`,
23656
+ '&:hover': {
23657
+ color: colorIconHover
23658
+ }
23659
+ }
23660
+ },
23661
+ '&-close-text': {
23662
+ color: colorIcon,
23663
+ transition: `color ${motionDurationMid}`,
23664
+ '&:hover': {
23665
+ color: colorIconHover
23666
+ }
23667
+ }
23668
+ }
23669
+ };
23670
+ };
23671
+ const prepareComponentToken$n = (token)=>{
23672
+ const paddingHorizontal = 12; // Fixed value here.
23673
+ return {
23674
+ withDescriptionIconSize: token.fontSizeHeading3,
23675
+ defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
23676
+ withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`
23677
+ };
23678
+ };
23679
+ var useStyle$u = genStyleHooks('Alert', (token)=>[
23680
+ genBaseStyle$6(token),
23681
+ genTypeStyle(token),
23682
+ genActionStyle(token)
23683
+ ], prepareComponentToken$n);
23684
+
23685
+ const IconNode = (props)=>{
23686
+ const { icon, type, className, style, successIcon, infoIcon, warningIcon, errorIcon } = props;
23687
+ const iconMapFilled = {
23688
+ success: successIcon ?? /*#__PURE__*/ React__namespace.createElement(CheckCircleFilled, null),
23689
+ info: infoIcon ?? /*#__PURE__*/ React__namespace.createElement(InfoCircleFilled, null),
23690
+ error: errorIcon ?? /*#__PURE__*/ React__namespace.createElement(CloseCircleFilled, null),
23691
+ warning: warningIcon ?? /*#__PURE__*/ React__namespace.createElement(ExclamationCircleFilled, null)
23692
+ };
23693
+ return /*#__PURE__*/ React__namespace.createElement("span", {
23694
+ className: className,
23695
+ style: style
23696
+ }, icon ?? iconMapFilled[type]);
23697
+ };
23698
+ const CloseIconNode = (props)=>{
23699
+ const { isClosable, prefixCls, closeIcon, handleClose, ariaProps, className, style } = props;
23700
+ const mergedCloseIcon = closeIcon === true || closeIcon === undefined ? /*#__PURE__*/ React__namespace.createElement(CloseOutlined, null) : closeIcon;
23701
+ return isClosable ? /*#__PURE__*/ React__namespace.createElement("button", {
23702
+ type: "button",
23703
+ onClick: handleClose,
23704
+ className: clsx(`${prefixCls}-close-icon`, className),
23705
+ tabIndex: 0,
23706
+ style: style,
23707
+ ...ariaProps
23708
+ }, mergedCloseIcon) : null;
23709
+ };
23710
+ const Alert$1 = /*#__PURE__*/ React__namespace.forwardRef((props, ref$1)=>{
23711
+ const { description, prefixCls: customizePrefixCls, message, title, banner, className, rootClassName, style, onMouseEnter, onMouseLeave, onClick, afterClose, showIcon, closable, closeText, closeIcon, action, id, styles, classNames, ...otherProps } = props;
23712
+ const mergedTitle = title ?? message;
23713
+ const [closed, setClosed] = React__namespace.useState(false);
23714
+ if (process.env.NODE_ENV !== 'production') {
23715
+ const warning = devUseWarning('Alert');
23716
+ [
23717
+ [
23718
+ 'closeText',
23719
+ 'closable.closeIcon'
23720
+ ],
23721
+ [
23722
+ 'message',
23723
+ 'title'
23724
+ ]
23725
+ ].forEach(([deprecatedName, newName])=>{
23726
+ warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
23727
+ });
23728
+ }
23729
+ const internalRef = React__namespace.useRef(null);
23730
+ React__namespace.useImperativeHandle(ref$1, ()=>({
23731
+ nativeElement: internalRef.current
23732
+ }));
23733
+ const { getPrefixCls, direction, closable: contextClosable, closeIcon: contextCloseIcon, className: contextClassName, style: contextStyle, classNames: contextClassNames, styles: contextStyles, successIcon, infoIcon, warningIcon, errorIcon } = useComponentConfig('alert');
23734
+ const prefixCls = getPrefixCls('alert', customizePrefixCls);
23735
+ const [hashId, cssVarCls] = useStyle$u(prefixCls);
23736
+ const { onClose: closableOnClose, afterClose: closableAfterClose } = closable && typeof closable === 'object' ? closable : {};
23737
+ const handleClose = (e)=>{
23738
+ setClosed(true);
23739
+ (closableOnClose ?? props.onClose)?.(e);
23740
+ };
23741
+ const type = React__namespace.useMemo(()=>{
23742
+ if (props.type !== undefined) {
23743
+ return props.type;
23744
+ }
23745
+ // banner mode defaults to 'warning'
23746
+ return banner ? 'warning' : 'info';
23747
+ }, [
23748
+ props.type,
23749
+ banner
23750
+ ]);
23751
+ // closeable when closeText or closeIcon is assigned
23752
+ const isClosable = React__namespace.useMemo(()=>{
23753
+ if (typeof closable === 'object' && closable.closeIcon) {
23754
+ return true;
23755
+ }
23756
+ if (closeText) {
23757
+ return true;
23758
+ }
23759
+ if (typeof closable === 'boolean') {
23760
+ return closable;
23761
+ }
23762
+ // should be true when closeIcon is 0 or ''
23763
+ if (closeIcon !== false && isNonNullable(closeIcon)) {
23764
+ return true;
23765
+ }
23766
+ return !!contextClosable;
23767
+ }, [
23768
+ closeText,
23769
+ closeIcon,
23770
+ closable,
23771
+ contextClosable
23772
+ ]);
23773
+ // banner mode defaults to Icon
23774
+ const isShowIcon = banner && showIcon === undefined ? true : showIcon;
23775
+ // =========== Merged Props for Semantic ==========
23776
+ const mergedProps = {
23777
+ ...props,
23778
+ prefixCls,
23779
+ type,
23780
+ showIcon: isShowIcon,
23781
+ closable: isClosable
23782
+ };
23783
+ const [mergedClassNames, mergedStyles] = useMergeSemantic([
23784
+ contextClassNames,
23785
+ classNames
23786
+ ], [
23787
+ contextStyles,
23788
+ styles
23789
+ ], {
23790
+ props: mergedProps
23791
+ });
23792
+ const alertCls = clsx(prefixCls, `${prefixCls}-${type}`, {
23793
+ [`${prefixCls}-with-description`]: !!description,
23794
+ [`${prefixCls}-no-icon`]: !isShowIcon,
23795
+ [`${prefixCls}-banner`]: !!banner,
23796
+ [`${prefixCls}-rtl`]: direction === 'rtl'
23797
+ }, contextClassName, className, rootClassName, mergedClassNames.root, cssVarCls, hashId);
23798
+ const restProps = pickAttrs(otherProps, {
23799
+ aria: true,
23800
+ data: true
23801
+ });
23802
+ const mergedCloseIcon = React__namespace.useMemo(()=>{
23803
+ if (typeof closable === 'object' && closable.closeIcon) {
23804
+ return closable.closeIcon;
23805
+ }
23806
+ if (closeText) {
23807
+ return closeText;
23808
+ }
23809
+ if (closeIcon !== undefined) {
23810
+ return closeIcon;
23811
+ }
23812
+ if (typeof contextClosable === 'object' && contextClosable.closeIcon) {
23813
+ return contextClosable.closeIcon;
23814
+ }
23815
+ return contextCloseIcon;
23816
+ }, [
23817
+ closeIcon,
23818
+ closable,
23819
+ contextClosable,
23820
+ closeText,
23821
+ contextCloseIcon
23822
+ ]);
23823
+ const mergedAriaProps = React__namespace.useMemo(()=>{
23824
+ const merged = closable ?? contextClosable;
23825
+ if (typeof merged === 'object') {
23826
+ return pickAttrs(merged, {
23827
+ data: true,
23828
+ aria: true
23829
+ });
23830
+ }
23831
+ return {};
23832
+ }, [
23833
+ closable,
23834
+ contextClosable
23835
+ ]);
23836
+ return /*#__PURE__*/ React__namespace.createElement(CSSMotion, {
23837
+ visible: !closed,
23838
+ motionName: `${prefixCls}-motion`,
23839
+ motionAppear: false,
23840
+ motionEnter: false,
23841
+ onLeaveStart: (node)=>({
23842
+ maxHeight: node.offsetHeight
23843
+ }),
23844
+ onLeaveEnd: closableAfterClose ?? afterClose
23845
+ }, ({ className: motionClassName, style: motionStyle }, setRef)=>/*#__PURE__*/ React__namespace.createElement("div", {
23846
+ id: id,
23847
+ ref: ref.composeRef(internalRef, setRef),
23848
+ "data-show": !closed,
23849
+ className: clsx(alertCls, motionClassName),
23850
+ style: {
23851
+ ...mergedStyles.root,
23852
+ ...contextStyle,
23853
+ ...style,
23854
+ ...motionStyle
23855
+ },
23856
+ onMouseEnter: onMouseEnter,
23857
+ onMouseLeave: onMouseLeave,
23858
+ onClick: onClick,
23859
+ role: "alert",
23860
+ ...restProps
23861
+ }, isShowIcon ? /*#__PURE__*/ React__namespace.createElement(IconNode, {
23862
+ className: clsx(`${prefixCls}-icon`, mergedClassNames.icon),
23863
+ style: mergedStyles.icon,
23864
+ description: description,
23865
+ icon: props.icon,
23866
+ prefixCls: prefixCls,
23867
+ type: type,
23868
+ successIcon: successIcon,
23869
+ infoIcon: infoIcon,
23870
+ warningIcon: warningIcon,
23871
+ errorIcon: errorIcon
23872
+ }) : null, /*#__PURE__*/ React__namespace.createElement("div", {
23873
+ className: clsx(`${prefixCls}-section`, mergedClassNames.section),
23874
+ style: mergedStyles.section
23875
+ }, mergedTitle ? /*#__PURE__*/ React__namespace.createElement("div", {
23876
+ className: clsx(`${prefixCls}-title`, mergedClassNames.title),
23877
+ style: mergedStyles.title
23878
+ }, mergedTitle) : null, description ? /*#__PURE__*/ React__namespace.createElement("div", {
23879
+ className: clsx(`${prefixCls}-description`, mergedClassNames.description),
23880
+ style: mergedStyles.description
23881
+ }, description) : null), action ? /*#__PURE__*/ React__namespace.createElement("div", {
23882
+ className: clsx(`${prefixCls}-actions`, mergedClassNames.actions),
23883
+ style: mergedStyles.actions
23884
+ }, action) : null, /*#__PURE__*/ React__namespace.createElement(CloseIconNode, {
23885
+ className: mergedClassNames.close,
23886
+ style: mergedStyles.close,
23887
+ isClosable: isClosable,
23888
+ prefixCls: prefixCls,
23889
+ closeIcon: mergedCloseIcon,
23890
+ handleClose: handleClose,
23891
+ ariaProps: mergedAriaProps
23892
+ })));
23893
+ });
23894
+ if (process.env.NODE_ENV !== 'production') {
23895
+ Alert$1.displayName = 'Alert';
23896
+ }
23897
+
23522
23898
  function _classCallCheck(a, n) {
23523
23899
  if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
23524
23900
  }
@@ -23560,6 +23936,110 @@ function _createClass(e, r, t) {
23560
23936
  }), e;
23561
23937
  }
23562
23938
 
23939
+ function _getPrototypeOf(t) {
23940
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function(t) {
23941
+ return t.__proto__ || Object.getPrototypeOf(t);
23942
+ }, _getPrototypeOf(t);
23943
+ }
23944
+
23945
+ function _isNativeReflectConstruct() {
23946
+ try {
23947
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
23948
+ } catch (t) {}
23949
+ return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
23950
+ return !!t;
23951
+ })();
23952
+ }
23953
+
23954
+ function _assertThisInitialized(e) {
23955
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
23956
+ return e;
23957
+ }
23958
+
23959
+ function _possibleConstructorReturn(t, e) {
23960
+ if (e && ("object" == _typeof(e) || "function" == typeof e)) return e;
23961
+ if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
23962
+ return _assertThisInitialized(t);
23963
+ }
23964
+
23965
+ function _callSuper(t, o, e) {
23966
+ return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
23967
+ }
23968
+
23969
+ function _setPrototypeOf(t, e) {
23970
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(t, e) {
23971
+ return t.__proto__ = e, t;
23972
+ }, _setPrototypeOf(t, e);
23973
+ }
23974
+
23975
+ function _inherits(t, e) {
23976
+ if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
23977
+ t.prototype = Object.create(e && e.prototype, {
23978
+ constructor: {
23979
+ value: t,
23980
+ writable: true,
23981
+ configurable: true
23982
+ }
23983
+ }), Object.defineProperty(t, "prototype", {
23984
+ writable: false
23985
+ }), e && _setPrototypeOf(t, e);
23986
+ }
23987
+
23988
+ let ErrorBoundary$1 = /*#__PURE__*/ function(_React$Component) {
23989
+ function ErrorBoundary() {
23990
+ var _this;
23991
+ _classCallCheck(this, ErrorBoundary);
23992
+ _this = _callSuper(this, ErrorBoundary, arguments);
23993
+ _this.state = {
23994
+ error: undefined,
23995
+ info: {
23996
+ componentStack: ''
23997
+ }
23998
+ };
23999
+ return _this;
24000
+ }
24001
+ _inherits(ErrorBoundary, _React$Component);
24002
+ return _createClass(ErrorBoundary, [
24003
+ {
24004
+ key: "componentDidCatch",
24005
+ value: function componentDidCatch(error, info) {
24006
+ this.setState({
24007
+ error,
24008
+ info
24009
+ });
24010
+ }
24011
+ },
24012
+ {
24013
+ key: "render",
24014
+ value: function render() {
24015
+ const { message, title, description, id, children } = this.props;
24016
+ const { error, info } = this.state;
24017
+ const mergedTitle = title ?? message;
24018
+ const componentStack = info?.componentStack || null;
24019
+ const errorMessage = typeof mergedTitle === 'undefined' ? (error || '').toString() : mergedTitle;
24020
+ const errorDescription = typeof description === 'undefined' ? componentStack : description;
24021
+ if (error) {
24022
+ return /*#__PURE__*/ React__namespace.createElement(Alert$1, {
24023
+ id: id,
24024
+ type: "error",
24025
+ title: errorMessage,
24026
+ description: /*#__PURE__*/ React__namespace.createElement("pre", {
24027
+ style: {
24028
+ fontSize: '0.9em',
24029
+ overflowX: 'auto'
24030
+ }
24031
+ }, errorDescription)
24032
+ });
24033
+ }
24034
+ return children;
24035
+ }
24036
+ }
24037
+ ]);
24038
+ }(React__namespace.Component);
24039
+
24040
+ const Alert = Alert$1;
24041
+ Alert.ErrorBoundary = ErrorBoundary$1;
24042
+
23563
24043
  function isWindow(obj) {
23564
24044
  return isNonNullable(obj) && obj === obj.window;
23565
24045
  }
@@ -23842,7 +24322,7 @@ var PropWarning = process.env.NODE_ENV !== 'production' ? PropWarning$1 : ()=>nu
23842
24322
  * theme register info here to help developer get warning info.
23843
24323
  */ let existThemeConfig = false;
23844
24324
  const warnContext = process.env.NODE_ENV !== 'production' ? (componentName)=>{
23845
- process.env.NODE_ENV !== "production" ? warning(!existThemeConfig, componentName, `Static function can not consume context like dynamic theme. Please use 'App' component instead.`) : void 0;
24325
+ 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;
23846
24326
  } : /* istanbul ignore next */ null;
23847
24327
  // These props is used by `useContext` directly in sub component
23848
24328
  const PASSED_PROPS = [
@@ -24158,7 +24638,7 @@ ConfigProvider.config = setGlobalConfig;
24158
24638
  ConfigProvider.useConfig = useConfig;
24159
24639
  Object.defineProperty(ConfigProvider, 'SizeContext', {
24160
24640
  get: ()=>{
24161
- process.env.NODE_ENV !== "production" ? warning(false, 'ConfigProvider', 'ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.') : void 0;
24641
+ process.env.NODE_ENV !== "production" ? warning$1(false, 'ConfigProvider', 'ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.') : void 0;
24162
24642
  return SizeContext;
24163
24643
  }
24164
24644
  });
@@ -46810,7 +47290,7 @@ const asyncCopy = async (text, isHtmlFormat)=>{
46810
47290
  };
46811
47291
  async function copy(text, config) {
46812
47292
  if (typeof text !== 'string') {
46813
- process.env.NODE_ENV !== "production" ? warning(false, 'The clipboard content must be of string type', '') : void 0;
47293
+ process.env.NODE_ENV !== "production" ? warning$1(false, 'The clipboard content must be of string type', '') : void 0;
46814
47294
  return false;
46815
47295
  }
46816
47296
  const isHtmlFormat = config?.format === 'text/html';
@@ -47599,7 +48079,7 @@ const Base = /*#__PURE__*/ React__namespace.forwardRef((props, ref$1)=>{
47599
48079
  }, node) : node, renderEllipsis(canEllipsis)))))));
47600
48080
  });
47601
48081
 
47602
- const Link = /*#__PURE__*/ React__namespace.forwardRef((props, ref)=>{
48082
+ const Link$1 = /*#__PURE__*/ React__namespace.forwardRef((props, ref)=>{
47603
48083
  const { ellipsis, rel, children, // @ts-expect-error: https://github.com/ant-design/ant-design/issues/26622
47604
48084
  navigate: _navigate, ...restProps } = props;
47605
48085
  if (process.env.NODE_ENV !== 'production') {
@@ -47675,7 +48155,7 @@ const Title$1 = /*#__PURE__*/ React__namespace.forwardRef((props, ref)=>{
47675
48155
 
47676
48156
  const Typography = Typography$1;
47677
48157
  Typography.Text = Text$1;
47678
- Typography.Link = Link;
48158
+ Typography.Link = Link$1;
47679
48159
  Typography.Title = Title$1;
47680
48160
  Typography.Paragraph = Paragraph;
47681
48161
 
@@ -49659,7 +50139,7 @@ const Timeline = ({ stamps, currentStep, onStepChange, onToggle })=>{
49659
50139
  };
49660
50140
 
49661
50141
  // src/primitive.tsx
49662
- function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
50142
+ function composeEventHandlers$1(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
49663
50143
  return function handleEvent(event) {
49664
50144
  originalEventHandler?.(event);
49665
50145
  if (checkForDefaultPrevented === false || !event.defaultPrevented) {
@@ -50172,9 +50652,9 @@ var DismissableLayer = React__namespace.forwardRef((props, forwardedRef)=>{
50172
50652
  pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
50173
50653
  ...props.style
50174
50654
  },
50175
- onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
50176
- onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
50177
- onPointerDownCapture: composeEventHandlers(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture)
50655
+ onFocusCapture: composeEventHandlers$1(props.onFocusCapture, focusOutside.onFocusCapture),
50656
+ onBlurCapture: composeEventHandlers$1(props.onBlurCapture, focusOutside.onBlurCapture),
50657
+ onPointerDownCapture: composeEventHandlers$1(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture)
50178
50658
  });
50179
50659
  });
50180
50660
  DismissableLayer.displayName = DISMISSABLE_LAYER_NAME;
@@ -50808,7 +51288,7 @@ var noScrollbarsClassName = 'with-scroll-bars-hidden';
50808
51288
  return ref.facade;
50809
51289
  }
50810
51290
 
50811
- var useIsomorphicLayoutEffect$1 = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
51291
+ var useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
50812
51292
  var currentValues = new WeakMap();
50813
51293
  /**
50814
51294
  * Merges two or more refs together providing a single interface to set their value
@@ -50830,7 +51310,7 @@ var currentValues = new WeakMap();
50830
51310
  });
50831
51311
  });
50832
51312
  // handle refs changes - added or removed
50833
- useIsomorphicLayoutEffect$1(function() {
51313
+ useIsomorphicLayoutEffect$2(function() {
50834
51314
  var oldValue = currentValues.get(callbackRef);
50835
51315
  if (oldValue) {
50836
51316
  var prevRefs_1 = new Set(oldValue);
@@ -51719,7 +52199,7 @@ var DialogTrigger = React__namespace.forwardRef((props, forwardedRef)=>{
51719
52199
  "data-state": getState(context.open),
51720
52200
  ...triggerProps,
51721
52201
  ref: composedTriggerRef,
51722
- onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
52202
+ onClick: composeEventHandlers$1(props.onClick, context.onOpenToggle)
51723
52203
  });
51724
52204
  });
51725
52205
  DialogTrigger.displayName = TRIGGER_NAME;
@@ -51811,17 +52291,17 @@ var DialogContentModal = React__namespace.forwardRef((props, forwardedRef)=>{
51811
52291
  ref: composedRefs,
51812
52292
  trapFocus: context.open,
51813
52293
  disableOutsidePointerEvents: true,
51814
- onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event)=>{
52294
+ onCloseAutoFocus: composeEventHandlers$1(props.onCloseAutoFocus, (event)=>{
51815
52295
  event.preventDefault();
51816
52296
  context.triggerRef.current?.focus();
51817
52297
  }),
51818
- onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event)=>{
52298
+ onPointerDownOutside: composeEventHandlers$1(props.onPointerDownOutside, (event)=>{
51819
52299
  const originalEvent = event.detail.originalEvent;
51820
52300
  const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
51821
52301
  const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
51822
52302
  if (isRightClick) event.preventDefault();
51823
52303
  }),
51824
- onFocusOutside: composeEventHandlers(props.onFocusOutside, (event)=>event.preventDefault())
52304
+ onFocusOutside: composeEventHandlers$1(props.onFocusOutside, (event)=>event.preventDefault())
51825
52305
  });
51826
52306
  });
51827
52307
  var DialogContentNonModal = React__namespace.forwardRef((props, forwardedRef)=>{
@@ -51928,7 +52408,7 @@ var DialogClose = React__namespace.forwardRef((props, forwardedRef)=>{
51928
52408
  type: "button",
51929
52409
  ...closeProps,
51930
52410
  ref: forwardedRef,
51931
- onClick: composeEventHandlers(props.onClick, ()=>context.onOpenChange(false))
52411
+ onClick: composeEventHandlers$1(props.onClick, ()=>context.onOpenChange(false))
51932
52412
  });
51933
52413
  });
51934
52414
  DialogClose.displayName = CLOSE_NAME;
@@ -113521,6 +114001,12 @@ function dtoMetricToMetric(def) {
113521
114001
  if (idx !== undefined && idx >= 0) {
113522
114002
  aggregatedResults[evaluatorId][item.metric.name] = idx;
113523
114003
  }
114004
+ } else if ((isLLMResult(item) || isToolResult(item)) && "result_name" in item && typeof item.value === "number") {
114005
+ // Raw LLM/Tool results: aggregate by result_name (metric name) for comparison view
114006
+ const name = item.result_name;
114007
+ const arr = valuesByMetric.get(name) ?? [];
114008
+ arr.push(item.value);
114009
+ valuesByMetric.set(name, arr);
113524
114010
  }
113525
114011
  }
113526
114012
  // Compute mean across all values for each metric
@@ -113572,117 +114058,114 @@ function dtoMetricToMetric(def) {
113572
114058
  return "evaluator_results" in x && Array.isArray(x.evaluator_results);
113573
114059
  }
113574
114060
 
113575
- const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluationId, evaluations, onSourceChange, onTargetChange })=>{
113576
- const { isDarkMode } = useTheme$1();
114061
+ /** Returns set of "evaluatorId:metricName" for all metrics in the evaluation. */ function getMetricKeys(evaluation) {
114062
+ const keys = new Set();
114063
+ for (const evaluator of evaluation.evaluators){
114064
+ for (const metric of evaluator.metrics){
114065
+ keys.add(`${evaluator.evaluator_id}:${metric.name}`);
114066
+ }
114067
+ }
114068
+ return keys;
114069
+ }
114070
+ /**
114071
+ * Returns true if both evaluations have the same set of metrics
114072
+ * (evaluator_id + metric name) across all evaluators.
114073
+ */ function evaluationsHaveSameMetrics(a, b) {
114074
+ if (a == null || b == null) return false;
114075
+ const evalA = isEvaluationDto(a) ? transformEvaluation(a) : a;
114076
+ const evalB = isEvaluationDto(b) ? transformEvaluation(b) : b;
114077
+ const keysA = getMetricKeys(evalA);
114078
+ const keysB = getMetricKeys(evalB);
114079
+ if (keysA.size !== keysB.size) return false;
114080
+ for (const key of keysA){
114081
+ if (!keysB.has(key)) return false;
114082
+ }
114083
+ return true;
114084
+ }
114085
+
114086
+ function formatMetricValue(evaluation, evaluatorId, metricName, metricType, options) {
114087
+ const evaluatorResults = evaluation.results[evaluatorId];
114088
+ const value = evaluatorResults?.[metricName];
114089
+ if (value === undefined) return "-";
114090
+ if (metricType === "Categorical" && options?.length) {
114091
+ const index = Math.round(value);
114092
+ return options[index] || value.toString();
114093
+ }
114094
+ if (metricType === "Continuous") {
114095
+ return value.toFixed(1);
114096
+ }
114097
+ return value.toString();
114098
+ }
114099
+ function getMetricValue(evaluation, evaluatorId, metricName) {
114100
+ const evaluatorResults = evaluation.results[evaluatorId];
114101
+ return evaluatorResults?.[metricName];
114102
+ }
114103
+ const EvaluationsCompareView = ({ evaluations, evaluationId1, evaluationId2, onEvaluationId1Change, onEvaluationId2Change, loading = false, showEvaluationComparisonDropdowns = false, backHref })=>{
114104
+ const { theme } = useTheme$1();
113577
114105
  const normalizedEvaluations = React.useMemo(()=>evaluations.map((e)=>isEvaluationDto(e) ? transformEvaluation(e) : e), [
113578
114106
  evaluations
113579
114107
  ]);
113580
- // Handler for copying evaluation IDs to clipboard
113581
- const handleCopyIds = async ()=>{
113582
- if (!sourceEvaluationId || !targetEvaluationId) {
113583
- staticMethods.error("No evaluation IDs available");
113584
- return;
113585
- }
113586
- try {
113587
- const idsText = `Source: ${sourceEvaluationId}\nTarget: ${targetEvaluationId}`;
113588
- await navigator.clipboard.writeText(idsText);
113589
- staticMethods.success("Evaluation IDs copied to clipboard");
113590
- } catch (err) {
113591
- staticMethods.error("Failed to copy evaluation IDs");
113592
- }
113593
- };
113594
- // Handler for sharing evaluation comparison
113595
- const handleShare = async ()=>{
113596
- if (!sourceEvaluationId || !targetEvaluationId) {
113597
- staticMethods.error("No evaluations available to share");
113598
- return;
113599
- }
113600
- const shareUrl = `${window.location.origin}${window.location.pathname}#/evaluations/compare?source=${sourceEvaluationId}&target=${targetEvaluationId}`;
113601
- // Try Web Share API if available
113602
- if (navigator.share) {
113603
- try {
113604
- await navigator.share({
113605
- title: "Evaluation Comparison",
113606
- text: `Compare evaluations: ${sourceEvaluationId} vs ${targetEvaluationId}`,
113607
- url: shareUrl
114108
+ const evaluation1 = normalizedEvaluations.find((e)=>e.evaluation_id === evaluationId1);
114109
+ const evaluation2 = normalizedEvaluations.find((e)=>e.evaluation_id === evaluationId2);
114110
+ const metricsMismatch = React.useMemo(()=>!evaluationsHaveSameMetrics(evaluation1, evaluation2), [
114111
+ evaluation1,
114112
+ evaluation2
114113
+ ]);
114114
+ const comparisonData = React.useMemo(()=>{
114115
+ if (!evaluation1 || !evaluation2) return [];
114116
+ const rows = [];
114117
+ // Build evaluator lookup by id for evaluation2 (to match evaluators between evaluations)
114118
+ const eval2EvaluatorsById = new Map(evaluation2.evaluators.map((e)=>[
114119
+ e.evaluator_id,
114120
+ e
114121
+ ]));
114122
+ // Iterate over ALL evaluators in evaluation1 (LLM, Tool, Judge, etc.)
114123
+ for (const evaluator1 of evaluation1.evaluators){
114124
+ const evaluator2 = eval2EvaluatorsById.get(evaluator1.evaluator_id);
114125
+ if (!evaluator2) continue;
114126
+ const allMetricNames = new Set();
114127
+ evaluator1.metrics.forEach((m)=>allMetricNames.add(m.name));
114128
+ evaluator2.metrics.forEach((m)=>allMetricNames.add(m.name));
114129
+ for (const metricName of allMetricNames){
114130
+ const metric1 = evaluator1.metrics.find((m)=>m.name === metricName);
114131
+ const metric2 = evaluator2.metrics.find((m)=>m.name === metricName);
114132
+ const metricType = metric1?.type || metric2?.type || "Continuous";
114133
+ const options = metric1?.type === "Categorical" ? metric1.options : metric2?.type === "Categorical" ? metric2.options : undefined;
114134
+ const value1 = getMetricValue(evaluation1, evaluator1.evaluator_id, metricName);
114135
+ const value2 = getMetricValue(evaluation2, evaluator2.evaluator_id, metricName);
114136
+ const formatted1 = formatMetricValue(evaluation1, evaluator1.evaluator_id, metricName, metricType, options);
114137
+ const formatted2 = formatMetricValue(evaluation2, evaluator2.evaluator_id, metricName, metricType, options);
114138
+ let difference;
114139
+ if (metricType === "Continuous" && value1 !== undefined && value2 !== undefined) {
114140
+ difference = value2 - value1;
114141
+ }
114142
+ rows.push({
114143
+ metricName,
114144
+ evaluatorName: evaluator1.name,
114145
+ metricType,
114146
+ value1,
114147
+ value2,
114148
+ formatted1,
114149
+ formatted2,
114150
+ difference,
114151
+ rowKey: `${evaluator1.evaluator_id}:${metricName}`
113608
114152
  });
113609
- return;
113610
- } catch (err) {
113611
- // User cancelled or error occurred, fall back to clipboard
113612
114153
  }
113613
114154
  }
113614
- // Fall back to copying URL to clipboard
113615
- try {
113616
- await navigator.clipboard.writeText(shareUrl);
113617
- staticMethods.success("Share link copied to clipboard");
113618
- } catch (err) {
113619
- staticMethods.error("Failed to copy share link");
113620
- }
113621
- };
113622
- // Find the evaluations
113623
- const sourceEvaluation = normalizedEvaluations.find((e)=>e.evaluation_id === sourceEvaluationId);
113624
- const targetEvaluation = normalizedEvaluations.find((e)=>e.evaluation_id === targetEvaluationId);
113625
- // Helper to format metric value (same logic as evaluations.tsx)
113626
- const formatMetricValue = (evaluation, metricName)=>{
113627
- const evaluator = evaluation.evaluators[0];
113628
- const metric = evaluator?.metrics.find((m)=>m.name === metricName);
113629
- const evaluatorId = evaluator?.evaluator_id || "";
113630
- const evaluatorResults = evaluation.results[evaluatorId];
113631
- const value = evaluatorResults?.[metricName];
113632
- if (value === undefined) return "-";
113633
- if (metric?.type === "Categorical" && metric.options) {
113634
- const index = Math.round(value);
113635
- return metric.options[index] || value.toString();
113636
- }
113637
- if (metric?.type === "Continuous") {
113638
- return value.toFixed(1);
113639
- }
113640
- return value.toString();
113641
- };
113642
- // Get metric value as number for comparison
113643
- const getMetricValue = (evaluation, metricName)=>{
113644
- const evaluator = evaluation.evaluators[0];
113645
- const evaluatorId = evaluator?.evaluator_id || "";
113646
- const evaluatorResults = evaluation.results[evaluatorId];
113647
- return evaluatorResults?.[metricName];
113648
- };
113649
- // Build comparison data
113650
- const comparisonData = React.useMemo(()=>{
113651
- if (!sourceEvaluation || !targetEvaluation) return [];
113652
- const sourceEvaluator = sourceEvaluation.evaluators[0];
113653
- const targetEvaluator = targetEvaluation.evaluators[0];
113654
- if (!sourceEvaluator || !targetEvaluator) return [];
113655
- // Get all unique metric names
113656
- const allMetricNames = new Set();
113657
- sourceEvaluator.metrics.forEach((m)=>allMetricNames.add(m.name));
113658
- targetEvaluator.metrics.forEach((m)=>allMetricNames.add(m.name));
113659
- return Array.from(allMetricNames).map((metricName)=>{
113660
- const sourceMetric = sourceEvaluator.metrics.find((m)=>m.name === metricName);
113661
- const targetMetric = targetEvaluator.metrics.find((m)=>m.name === metricName);
113662
- const metricType = sourceMetric?.type || targetMetric?.type || "Continuous";
113663
- const sourceValue = getMetricValue(sourceEvaluation, metricName);
113664
- const targetValue = getMetricValue(targetEvaluation, metricName);
113665
- const sourceFormatted = formatMetricValue(sourceEvaluation, metricName);
113666
- const targetFormatted = formatMetricValue(targetEvaluation, metricName);
113667
- let difference;
113668
- if (metricType === "Continuous" && sourceValue !== undefined && targetValue !== undefined) {
113669
- difference = targetValue - sourceValue;
113670
- }
113671
- return {
113672
- metricName,
113673
- metricType,
113674
- sourceValue,
113675
- targetValue,
113676
- sourceFormatted,
113677
- targetFormatted,
113678
- difference
113679
- };
114155
+ return rows;
114156
+ }, [
114157
+ evaluation1,
114158
+ evaluation2
114159
+ ]);
114160
+ const allValuesIdentical = React.useMemo(()=>{
114161
+ if (comparisonData.length === 0) return false;
114162
+ return comparisonData.every((r)=>{
114163
+ if (r.metricType === "Continuous" && r.difference !== undefined) return r.difference === 0;
114164
+ return r.formatted1 === r.formatted2;
113680
114165
  });
113681
114166
  }, [
113682
- sourceEvaluation,
113683
- targetEvaluation
114167
+ comparisonData
113684
114168
  ]);
113685
- // Prepare options for dropdowns
113686
114169
  const evaluationOptions = React.useMemo(()=>{
113687
114170
  return normalizedEvaluations.map((evaluation)=>({
113688
114171
  label: `${evaluation.name || "Unnamed Evaluation"} (${evaluation.agent_name})`,
@@ -113699,54 +114182,261 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113699
114182
  width: 200,
113700
114183
  render: (name, record)=>/*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("div", {
113701
114184
  style: {
113702
- fontWeight: 500
114185
+ fontWeight: theme.fontWeight.medium
113703
114186
  }
113704
114187
  }, name), /*#__PURE__*/ React.createElement("div", {
113705
114188
  style: {
113706
- fontSize: "12px",
113707
- color: isDarkMode ? "#8c8c8c" : "#595959"
114189
+ fontSize: theme.fontSize.xs,
114190
+ color: theme.colors.mutedForeground
113708
114191
  }
113709
- }, record.metricType))
114192
+ }, record.evaluatorName, " • ", record.metricType))
113710
114193
  },
113711
114194
  {
113712
- title: sourceEvaluation?.name || "Source",
113713
- key: "source",
114195
+ title: evaluation1?.name || "Evaluation 1",
114196
+ key: "evaluation1",
113714
114197
  width: 150,
113715
114198
  render: (_, record)=>/*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement(Tag, {
113716
114199
  color: "blue"
113717
- }, record.sourceFormatted))
114200
+ }, record.formatted1))
113718
114201
  },
113719
114202
  {
113720
- title: targetEvaluation?.name || "Target",
113721
- key: "target",
114203
+ title: evaluation2?.name || "Evaluation 2",
114204
+ key: "evaluation2",
113722
114205
  width: 150,
113723
114206
  render: (_, record)=>/*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement(Tag, {
113724
114207
  color: "green"
113725
- }, record.targetFormatted))
114208
+ }, record.formatted2))
113726
114209
  },
113727
114210
  {
113728
114211
  title: "Difference",
113729
114212
  key: "difference",
113730
114213
  width: 120,
113731
114214
  render: (_, record)=>{
113732
- if (record.difference === undefined) return "-";
113733
- const isPositive = record.difference > 0;
113734
- const isNegative = record.difference < 0;
113735
- return /*#__PURE__*/ React.createElement(Tag, {
113736
- color: isPositive ? "green" : isNegative ? "red" : "default"
113737
- }, isPositive ? "+" : "", record.difference.toFixed(1));
114215
+ if (record.difference !== undefined) {
114216
+ const isPositive = record.difference > 0;
114217
+ const isNegative = record.difference < 0;
114218
+ return /*#__PURE__*/ React.createElement(Tag, {
114219
+ color: isPositive ? "green" : isNegative ? "red" : "default"
114220
+ }, isPositive ? "+" : "", record.difference.toFixed(1));
114221
+ }
114222
+ // Categorical: show "Different" when values differ
114223
+ if (record.formatted1 !== record.formatted2) {
114224
+ return /*#__PURE__*/ React.createElement(Tag, {
114225
+ color: "orange"
114226
+ }, "Different");
114227
+ }
114228
+ return "-";
113738
114229
  }
113739
114230
  }
113740
114231
  ];
113741
- const extraButtonsIconSize = 24;
114232
+ const evaluation1Label = evaluation1 ? `${evaluation1.name || "Unnamed Evaluation"} (${evaluation1.agent_name})` : "Select evaluation 1";
114233
+ const evaluation2Label = evaluation2 ? `${evaluation2.name || "Unnamed Evaluation"} (${evaluation2.agent_name})` : "Select evaluation 2";
114234
+ return /*#__PURE__*/ React.createElement(React.Fragment, null, backHref && /*#__PURE__*/ React.createElement("a", {
114235
+ href: backHref,
114236
+ style: {
114237
+ display: "inline-flex",
114238
+ alignItems: "center",
114239
+ gap: 6,
114240
+ marginBottom: 24,
114241
+ color: theme.colors.mutedForeground,
114242
+ textDecoration: "none",
114243
+ fontSize: 14
114244
+ }
114245
+ }, /*#__PURE__*/ React.createElement(ArrowLeft, {
114246
+ size: 16
114247
+ }), "Back to Evaluations"), /*#__PURE__*/ React.createElement("div", {
114248
+ style: {
114249
+ marginBottom: theme.spacing.md,
114250
+ color: theme.colors.mutedForeground
114251
+ }
114252
+ }, showEvaluationComparisonDropdowns ? "Select two evaluations to compare their metrics" : /*#__PURE__*/ React.createElement("div", {
114253
+ style: {
114254
+ display: "flex",
114255
+ alignItems: "center",
114256
+ gap: theme.spacing.sm,
114257
+ flexWrap: "wrap"
114258
+ }
114259
+ }, /*#__PURE__*/ React.createElement("span", null, /*#__PURE__*/ React.createElement("strong", null, "Evaluation 1:"), " ", evaluation1Label), /*#__PURE__*/ React.createElement("span", {
114260
+ style: {
114261
+ color: theme.colors.border
114262
+ }
114263
+ }, "•"), /*#__PURE__*/ React.createElement("span", null, /*#__PURE__*/ React.createElement("strong", null, "Evaluation 2:"), " ", evaluation2Label))), showEvaluationComparisonDropdowns && /*#__PURE__*/ React.createElement("div", {
114264
+ style: {
114265
+ marginBottom: theme.spacing.lg
114266
+ }
114267
+ }, /*#__PURE__*/ React.createElement(Space, {
114268
+ size: "middle",
114269
+ style: {
114270
+ width: "100%"
114271
+ }
114272
+ }, /*#__PURE__*/ React.createElement("div", {
114273
+ style: {
114274
+ flex: 1
114275
+ }
114276
+ }, /*#__PURE__*/ React.createElement("label", {
114277
+ style: {
114278
+ display: "block",
114279
+ marginBottom: theme.spacing.sm,
114280
+ fontWeight: theme.fontWeight.medium,
114281
+ color: theme.colors.foreground
114282
+ }
114283
+ }, "Evaluation 1"), /*#__PURE__*/ React.createElement(Select, {
114284
+ style: {
114285
+ width: "100%"
114286
+ },
114287
+ placeholder: "Select evaluation 1",
114288
+ value: evaluationId1,
114289
+ onChange: (value)=>onEvaluationId1Change(value),
114290
+ options: evaluationOptions,
114291
+ showSearch: true,
114292
+ loading: loading,
114293
+ filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
114294
+ })), /*#__PURE__*/ React.createElement("div", {
114295
+ style: {
114296
+ flex: 1
114297
+ }
114298
+ }, /*#__PURE__*/ React.createElement("label", {
114299
+ style: {
114300
+ display: "block",
114301
+ marginBottom: theme.spacing.sm,
114302
+ fontWeight: theme.fontWeight.medium,
114303
+ color: theme.colors.foreground
114304
+ }
114305
+ }, "Evaluation 2"), /*#__PURE__*/ React.createElement(Select, {
114306
+ style: {
114307
+ width: "100%"
114308
+ },
114309
+ placeholder: "Select evaluation 2",
114310
+ value: evaluationId2,
114311
+ onChange: (value)=>onEvaluationId2Change(value),
114312
+ options: evaluationOptions,
114313
+ showSearch: true,
114314
+ loading: loading,
114315
+ filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
114316
+ })))), !evaluation1 || !evaluation2 ? /*#__PURE__*/ React.createElement("div", {
114317
+ style: {
114318
+ textAlign: "center",
114319
+ padding: theme.spacing["2xl"],
114320
+ color: theme.colors.mutedForeground
114321
+ }
114322
+ }, /*#__PURE__*/ React.createElement("p", null, "Please select both evaluations to compare")) : metricsMismatch ? /*#__PURE__*/ React.createElement(Alert, {
114323
+ type: "error",
114324
+ showIcon: true,
114325
+ message: "Cannot compare evaluations",
114326
+ description: "The two evaluations must have the same metrics in order to be diffed. Please select evaluations that share the same metric set."
114327
+ }) : /*#__PURE__*/ React.createElement("div", null, allValuesIdentical && /*#__PURE__*/ React.createElement(Alert, {
114328
+ type: "info",
114329
+ showIcon: true,
114330
+ message: "Evaluations are identical",
114331
+ description: "All metric values match between the two evaluations.",
114332
+ style: {
114333
+ marginBottom: theme.spacing.lg
114334
+ }
114335
+ }), /*#__PURE__*/ React.createElement("div", {
114336
+ style: {
114337
+ display: "grid",
114338
+ gridTemplateColumns: "1fr 1fr",
114339
+ gap: theme.spacing.lg,
114340
+ marginBottom: theme.spacing.lg,
114341
+ padding: theme.spacing.md,
114342
+ borderRadius: theme.borderRadius.lg,
114343
+ border: `1px solid ${theme.colors.border}`,
114344
+ backgroundColor: theme.colors.muted
114345
+ }
114346
+ }, /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("h3", {
114347
+ style: {
114348
+ margin: `0 0 ${theme.spacing.sm} 0`,
114349
+ fontSize: theme.fontSize.base,
114350
+ fontWeight: theme.fontWeight.semibold
114351
+ }
114352
+ }, "Evaluation 1: ", evaluation1.name || "Unnamed Evaluation"), /*#__PURE__*/ React.createElement("div", {
114353
+ style: {
114354
+ fontSize: theme.fontSize.sm,
114355
+ color: theme.colors.mutedForeground
114356
+ }
114357
+ }, /*#__PURE__*/ React.createElement("div", null, "Agent: ", evaluation1.agent_name), /*#__PURE__*/ React.createElement("div", null, "Runs: ", evaluation1.runs.length), /*#__PURE__*/ React.createElement("div", null, "Created: ", moment(evaluation1.created_at).format("YYYY-MM-DD HH:mm:ss")))), /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("h3", {
114358
+ style: {
114359
+ margin: `0 0 ${theme.spacing.sm} 0`,
114360
+ fontSize: theme.fontSize.base,
114361
+ fontWeight: theme.fontWeight.semibold
114362
+ }
114363
+ }, "Evaluation 2: ", evaluation2.name || "Unnamed Evaluation"), /*#__PURE__*/ React.createElement("div", {
114364
+ style: {
114365
+ fontSize: theme.fontSize.sm,
114366
+ color: theme.colors.mutedForeground
114367
+ }
114368
+ }, /*#__PURE__*/ React.createElement("div", null, "Agent: ", evaluation2.agent_name), /*#__PURE__*/ React.createElement("div", null, "Runs: ", evaluation2.runs.length), /*#__PURE__*/ React.createElement("div", null, "Created: ", moment(evaluation2.created_at).format("YYYY-MM-DD HH:mm:ss"))))), /*#__PURE__*/ React.createElement("h3", {
114369
+ style: {
114370
+ margin: `0 0 ${theme.spacing.md} 0`,
114371
+ fontSize: theme.fontSize.lg,
114372
+ fontWeight: theme.fontWeight.semibold
114373
+ }
114374
+ }, "Metrics Comparison"), /*#__PURE__*/ React.createElement(ForwardTable, {
114375
+ columns: comparisonColumns,
114376
+ dataSource: comparisonData,
114377
+ rowKey: "rowKey",
114378
+ pagination: false,
114379
+ style: {
114380
+ background: theme.colors.card
114381
+ },
114382
+ rowClassName: (record)=>{
114383
+ const hasDiff = record.metricType === "Continuous" ? record.difference !== undefined && record.difference !== 0 : record.formatted1 !== record.formatted2;
114384
+ return hasDiff ? "evaluations-compare-diff-row" : "";
114385
+ }
114386
+ })));
114387
+ };
114388
+
114389
+ const extraButtonsIconSize = 24;
114390
+ const EvaluationsCompareDrawer = ({ open, onClose, evaluationId1, evaluationId2, evaluations, onEvaluationId1Change, onEvaluationId2Change })=>{
114391
+ const handleCopyIds = async ()=>{
114392
+ if (!evaluationId1 || !evaluationId2) {
114393
+ staticMethods.error("No evaluation IDs available");
114394
+ return;
114395
+ }
114396
+ try {
114397
+ const idsText = `Evaluation 1: ${evaluationId1}\nEvaluation 2: ${evaluationId2}`;
114398
+ await navigator.clipboard.writeText(idsText);
114399
+ staticMethods.success("Evaluation IDs copied to clipboard");
114400
+ } catch (err) {
114401
+ staticMethods.error("Failed to copy evaluation IDs");
114402
+ }
114403
+ };
114404
+ const handleShare = async ()=>{
114405
+ if (!evaluationId1 || !evaluationId2) {
114406
+ staticMethods.error("No evaluations available to share");
114407
+ return;
114408
+ }
114409
+ const shareUrl = `${window.location.origin}${window.location.pathname}#/evaluations?compare=${evaluationId1},${evaluationId2}`;
114410
+ if (navigator.share) {
114411
+ try {
114412
+ await navigator.share({
114413
+ title: "Evaluation Comparison",
114414
+ text: `Compare evaluations: ${evaluationId1} vs ${evaluationId2}`,
114415
+ url: shareUrl
114416
+ });
114417
+ return;
114418
+ } catch (err) {
114419
+ // User cancelled or error occurred, fall back to clipboard
114420
+ }
114421
+ }
114422
+ try {
114423
+ await navigator.clipboard.writeText(shareUrl);
114424
+ staticMethods.success("Share link copied to clipboard");
114425
+ } catch (err) {
114426
+ staticMethods.error("Failed to copy share link");
114427
+ }
114428
+ };
113742
114429
  return /*#__PURE__*/ React.createElement(Drawer$2, {
113743
114430
  title: "Compare Evaluations",
113744
114431
  placement: "right",
113745
114432
  size: "60%",
113746
114433
  open: open,
113747
114434
  onClose: onClose,
113748
- extra: /*#__PURE__*/ React.createElement(Space, {
113749
- size: "middle"
114435
+ extra: /*#__PURE__*/ React.createElement("div", {
114436
+ style: {
114437
+ display: "flex",
114438
+ gap: 8
114439
+ }
113750
114440
  }, /*#__PURE__*/ React.createElement(Tooltip, {
113751
114441
  title: "Copy IDs to Clipboard"
113752
114442
  }, /*#__PURE__*/ React.createElement(Button$1, {
@@ -113755,7 +114445,7 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113755
114445
  size: extraButtonsIconSize
113756
114446
  }),
113757
114447
  onClick: handleCopyIds,
113758
- disabled: !sourceEvaluationId || !targetEvaluationId
114448
+ disabled: !evaluationId1 || !evaluationId2
113759
114449
  })), /*#__PURE__*/ React.createElement(Tooltip, {
113760
114450
  title: "Share"
113761
114451
  }, /*#__PURE__*/ React.createElement(Button$1, {
@@ -113764,123 +114454,21 @@ const EvaluationsCompare = ({ open, onClose, sourceEvaluationId, targetEvaluatio
113764
114454
  size: extraButtonsIconSize
113765
114455
  }),
113766
114456
  onClick: handleShare,
113767
- disabled: !sourceEvaluationId || !targetEvaluationId
114457
+ disabled: !evaluationId1 || !evaluationId2
113768
114458
  }))),
113769
114459
  styles: {
113770
114460
  body: {
113771
114461
  padding: "24px"
113772
114462
  }
113773
114463
  }
113774
- }, /*#__PURE__*/ React.createElement("div", {
113775
- style: {
113776
- marginBottom: "16px",
113777
- color: isDarkMode ? "#8c8c8c" : "#595959"
113778
- }
113779
- }, "Select two evaluations to compare their metrics"), /*#__PURE__*/ React.createElement("div", {
113780
- style: {
113781
- marginBottom: "24px"
113782
- }
113783
- }, /*#__PURE__*/ React.createElement(Space, {
113784
- size: "middle",
113785
- style: {
113786
- width: "100%"
113787
- }
113788
- }, /*#__PURE__*/ React.createElement("div", {
113789
- style: {
113790
- flex: 1
113791
- }
113792
- }, /*#__PURE__*/ React.createElement("label", {
113793
- style: {
113794
- display: "block",
113795
- marginBottom: "8px",
113796
- fontWeight: 500,
113797
- color: isDarkMode ? "#e5e7eb" : "#1f2937"
113798
- }
113799
- }, "Source Evaluation"), /*#__PURE__*/ React.createElement(Select, {
113800
- style: {
113801
- width: "100%"
113802
- },
113803
- placeholder: "Select source evaluation",
113804
- value: sourceEvaluationId,
113805
- onChange: (value)=>onSourceChange(value),
113806
- options: evaluationOptions,
113807
- showSearch: true,
113808
- filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
113809
- })), /*#__PURE__*/ React.createElement("div", {
113810
- style: {
113811
- flex: 1
113812
- }
113813
- }, /*#__PURE__*/ React.createElement("label", {
113814
- style: {
113815
- display: "block",
113816
- marginBottom: "8px",
113817
- fontWeight: 500,
113818
- color: isDarkMode ? "#e5e7eb" : "#1f2937"
113819
- }
113820
- }, "Target Evaluation"), /*#__PURE__*/ React.createElement(Select, {
113821
- style: {
113822
- width: "100%"
113823
- },
113824
- placeholder: "Select target evaluation",
113825
- value: targetEvaluationId,
113826
- onChange: (value)=>onTargetChange(value),
113827
- options: evaluationOptions,
113828
- showSearch: true,
113829
- filterOption: (input, option)=>(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
113830
- })))), !sourceEvaluation || !targetEvaluation ? /*#__PURE__*/ React.createElement("div", {
113831
- style: {
113832
- textAlign: "center",
113833
- padding: "48px",
113834
- color: isDarkMode ? "#8c8c8c" : "#595959"
113835
- }
113836
- }, /*#__PURE__*/ React.createElement("p", null, "Please select both source and target evaluations to compare")) : /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("div", {
113837
- style: {
113838
- display: "grid",
113839
- gridTemplateColumns: "1fr 1fr",
113840
- gap: "24px",
113841
- marginBottom: "24px",
113842
- padding: "16px",
113843
- borderRadius: "8px",
113844
- border: `1px solid ${isDarkMode ? "#2d2d2d" : "#e5e7eb"}`,
113845
- backgroundColor: isDarkMode ? "#1a1a1a" : "#f9fafb"
113846
- }
113847
- }, /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("h3", {
113848
- style: {
113849
- margin: "0 0 12px 0",
113850
- fontSize: "16px",
113851
- fontWeight: 600
113852
- }
113853
- }, "Source: ", sourceEvaluation.name || "Unnamed Evaluation"), /*#__PURE__*/ React.createElement("div", {
113854
- style: {
113855
- fontSize: "14px",
113856
- color: isDarkMode ? "#a3a3a3" : "#6b7280"
113857
- }
113858
- }, /*#__PURE__*/ React.createElement("div", null, "Agent: ", sourceEvaluation.agent_name), /*#__PURE__*/ React.createElement("div", null, "Runs: ", sourceEvaluation.runs.length), /*#__PURE__*/ React.createElement("div", null, "Created: ", moment(sourceEvaluation.created_at).format("YYYY-MM-DD HH:mm:ss")))), /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("h3", {
113859
- style: {
113860
- margin: "0 0 12px 0",
113861
- fontSize: "16px",
113862
- fontWeight: 600
113863
- }
113864
- }, "Target: ", targetEvaluation.name || "Unnamed Evaluation"), /*#__PURE__*/ React.createElement("div", {
113865
- style: {
113866
- fontSize: "14px",
113867
- color: isDarkMode ? "#a3a3a3" : "#6b7280"
113868
- }
113869
- }, /*#__PURE__*/ React.createElement("div", null, "Agent: ", targetEvaluation.agent_name), /*#__PURE__*/ React.createElement("div", null, "Runs: ", targetEvaluation.runs.length), /*#__PURE__*/ React.createElement("div", null, "Created: ", moment(targetEvaluation.created_at).format("YYYY-MM-DD HH:mm:ss"))))), /*#__PURE__*/ React.createElement("h3", {
113870
- style: {
113871
- margin: "0 0 16px 0",
113872
- fontSize: "18px",
113873
- fontWeight: 600
113874
- }
113875
- }, "Metrics Comparison"), /*#__PURE__*/ React.createElement(ForwardTable, {
113876
- columns: comparisonColumns,
113877
- dataSource: comparisonData,
113878
- rowKey: "metricName",
113879
- pagination: false,
113880
- style: {
113881
- background: isDarkMode ? "#141414" : "#fff"
113882
- }
113883
- })));
114464
+ }, /*#__PURE__*/ React.createElement(EvaluationsCompareView, {
114465
+ evaluations: evaluations,
114466
+ evaluationId1: evaluationId1,
114467
+ evaluationId2: evaluationId2,
114468
+ onEvaluationId1Change: onEvaluationId1Change,
114469
+ onEvaluationId2Change: onEvaluationId2Change,
114470
+ showEvaluationComparisonDropdowns: false
114471
+ }));
113884
114472
  };
113885
114473
 
113886
114474
  const defaultGetEvaluatorResultsHref = (evaluationId, evaluatorId)=>`#/evaluations/${evaluationId}/results/${evaluatorId}`;
@@ -114114,17 +114702,19 @@ const EvaluationDetailsDrawer = ({ evaluation, open, onClose, getEvaluatorResult
114114
114702
  })))));
114115
114703
  };
114116
114704
 
114117
- const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefresh, onRowClick, onCompare, showFilters = true, showCompare = true, emptyMessage, title })=>{
114705
+ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefresh, onRowClick, onCompare, compareIdsFromUrl, onCompareUrlChange, showFilters = true, showCompare = true, emptyMessage, title, pagination: serverPagination, onFiltersChange, onFetchEvaluationsByIds })=>{
114118
114706
  const { theme } = useTheme$1();
114119
114707
  const [selectedAgents, setSelectedAgents] = React.useState([]);
114120
114708
  const [selectedRowKeys, setSelectedRowKeys] = React.useState([]);
114121
114709
  const [compareDrawerOpen, setCompareDrawerOpen] = React.useState(false);
114122
- const [sourceEvaluationId, setSourceEvaluationId] = React.useState(null);
114123
- const [targetEvaluationId, setTargetEvaluationId] = React.useState(null);
114710
+ const [evaluationId1, setEvaluationId1] = React.useState(null);
114711
+ const [evaluationId2, setEvaluationId2] = React.useState(null);
114124
114712
  const [selectedEvaluation, setSelectedEvaluation] = React.useState(null);
114125
114713
  const [detailsDrawerOpen, setDetailsDrawerOpen] = React.useState(false);
114126
114714
  const [pageSize, setPageSize] = React.useState(50);
114127
114715
  const [selectedMetricFilter, setSelectedMetricFilter] = React.useState(null);
114716
+ const [drawerEvaluations, setDrawerEvaluations] = React.useState([]);
114717
+ const isServerPagination = !!serverPagination;
114128
114718
  const normalized = React.useMemo(()=>evaluations.map((e)=>isEvaluationDto(e) ? transformEvaluation(e) : e), [
114129
114719
  evaluations
114130
114720
  ]);
@@ -114173,6 +114763,63 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114173
114763
  selectedAgents,
114174
114764
  selectedMetricFilter
114175
114765
  ]);
114766
+ const tableDataSource = filteredEvaluations;
114767
+ const compareDrawerEvaluations = React.useMemo(()=>{
114768
+ if (drawerEvaluations.length === 0) return normalized;
114769
+ const byId = new Map(normalized.map((e)=>[
114770
+ e.evaluation_id,
114771
+ e
114772
+ ]));
114773
+ for (const e of drawerEvaluations){
114774
+ const id = e.evaluation_id ?? e.evaluation_id;
114775
+ if (id && !byId.has(id)) byId.set(id, e);
114776
+ }
114777
+ return Array.from(byId.values());
114778
+ }, [
114779
+ normalized,
114780
+ drawerEvaluations
114781
+ ]);
114782
+ // Sync drawer when compare param comes from URL
114783
+ React.useEffect(()=>{
114784
+ if (compareIdsFromUrl) {
114785
+ setEvaluationId1(compareIdsFromUrl[0]);
114786
+ setEvaluationId2(compareIdsFromUrl[1]);
114787
+ setCompareDrawerOpen(true);
114788
+ }
114789
+ }, [
114790
+ compareIdsFromUrl
114791
+ ]);
114792
+ // Fetch evaluations by ID for compare drawer when opened from URL (server pagination)
114793
+ React.useEffect(()=>{
114794
+ if (!compareDrawerOpen || !onFetchEvaluationsByIds || !evaluationId1 || !evaluationId2) {
114795
+ setDrawerEvaluations([]);
114796
+ return;
114797
+ }
114798
+ const ids = [
114799
+ evaluationId1,
114800
+ evaluationId2
114801
+ ];
114802
+ const inNormalized = ids.every((id)=>normalized.some((e)=>e.evaluation_id === id));
114803
+ if (inNormalized) {
114804
+ setDrawerEvaluations([]);
114805
+ return;
114806
+ }
114807
+ let cancelled = false;
114808
+ onFetchEvaluationsByIds(ids).then((fetched)=>{
114809
+ if (!cancelled) {
114810
+ setDrawerEvaluations(fetched);
114811
+ }
114812
+ });
114813
+ return ()=>{
114814
+ cancelled = true;
114815
+ };
114816
+ }, [
114817
+ compareDrawerOpen,
114818
+ evaluationId1,
114819
+ evaluationId2,
114820
+ normalized,
114821
+ onFetchEvaluationsByIds
114822
+ ]);
114176
114823
  // Handle row selection - limit to 2 rows
114177
114824
  const handleRowSelectionChange = (selectedKeys)=>{
114178
114825
  if (selectedKeys.length <= 2) {
@@ -114184,14 +114831,23 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114184
114831
  if (selectedRowKeys.length === 2 && onCompare) {
114185
114832
  onCompare(selectedRowKeys[0], selectedRowKeys[1]);
114186
114833
  } else if (selectedRowKeys.length === 2 && !onCompare) {
114187
- setSourceEvaluationId(selectedRowKeys[0]);
114188
- setTargetEvaluationId(selectedRowKeys[1]);
114834
+ setEvaluationId1(selectedRowKeys[0]);
114835
+ setEvaluationId2(selectedRowKeys[1]);
114189
114836
  setCompareDrawerOpen(true);
114190
114837
  }
114191
114838
  };
114192
114839
  // Handle drawer close
114193
114840
  const handleDrawerClose = ()=>{
114194
114841
  setCompareDrawerOpen(false);
114842
+ onCompareUrlChange?.(null, null);
114843
+ };
114844
+ const handleEvaluationId1Change = (id)=>{
114845
+ setEvaluationId1(id);
114846
+ onCompareUrlChange?.(id, evaluationId2);
114847
+ };
114848
+ const handleEvaluationId2Change = (id)=>{
114849
+ setEvaluationId2(id);
114850
+ onCompareUrlChange?.(evaluationId1, id);
114195
114851
  };
114196
114852
  // Handle row click to open evaluation details
114197
114853
  const handleRowClick = (record)=>{
@@ -114315,7 +114971,12 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114315
114971
  placeholder: "Filter by Agent",
114316
114972
  allowClear: true,
114317
114973
  value: selectedAgents,
114318
- onChange: setSelectedAgents,
114974
+ onChange: (v)=>{
114975
+ setSelectedAgents(v);
114976
+ if (isServerPagination && onFiltersChange) {
114977
+ onFiltersChange(v, selectedMetricFilter);
114978
+ }
114979
+ },
114319
114980
  style: {
114320
114981
  width: 200
114321
114982
  },
@@ -114327,7 +114988,13 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114327
114988
  placeholder: "Filter by Evaluator / Metric",
114328
114989
  allowClear: true,
114329
114990
  value: selectedMetricFilter ?? undefined,
114330
- onChange: (v)=>setSelectedMetricFilter(v ?? null),
114991
+ onChange: (v)=>{
114992
+ const next = v ?? null;
114993
+ setSelectedMetricFilter(next);
114994
+ if (isServerPagination && onFiltersChange) {
114995
+ onFiltersChange(selectedAgents, next);
114996
+ }
114997
+ },
114331
114998
  style: {
114332
114999
  width: 240
114333
115000
  },
@@ -114350,7 +115017,7 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114350
115017
  }
114351
115018
  }, emptyMessage ?? defaultEmptyMessage) : /*#__PURE__*/ React.createElement(ForwardTable, {
114352
115019
  columns: columns,
114353
- dataSource: filteredEvaluations,
115020
+ dataSource: tableDataSource,
114354
115021
  loading: loading,
114355
115022
  rowKey: "evaluation_id",
114356
115023
  rowSelection: showCompare ? {
@@ -114361,7 +115028,20 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114361
115028
  disabled: selectedRowKeys.length >= 2 && !selectedRowKeys.includes(record.evaluation_id)
114362
115029
  })
114363
115030
  } : undefined,
114364
- pagination: filteredEvaluations.length <= pageSize ? false : {
115031
+ pagination: isServerPagination && serverPagination ? {
115032
+ total: serverPagination.total,
115033
+ current: serverPagination.current,
115034
+ pageSize: serverPagination.pageSize,
115035
+ showSizeChanger: true,
115036
+ showTotal: (total)=>`Total ${total} evaluations`,
115037
+ pageSizeOptions: [
115038
+ "10",
115039
+ "20",
115040
+ "50",
115041
+ "100"
115042
+ ],
115043
+ onChange: (page, size)=>serverPagination.onPageChange(page, size ?? serverPagination.pageSize)
115044
+ } : tableDataSource.length <= pageSize ? false : {
114365
115045
  pageSize,
114366
115046
  showSizeChanger: true,
114367
115047
  showTotal: (total)=>`Total ${total} evaluations`,
@@ -114392,14 +115072,14 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114392
115072
  cursor: "pointer"
114393
115073
  }
114394
115074
  })
114395
- }), !onCompare && /*#__PURE__*/ React.createElement(EvaluationsCompare, {
115075
+ }), compareDrawerOpen && /*#__PURE__*/ React.createElement(EvaluationsCompareDrawer, {
114396
115076
  open: compareDrawerOpen,
114397
115077
  onClose: handleDrawerClose,
114398
- sourceEvaluationId: sourceEvaluationId,
114399
- targetEvaluationId: targetEvaluationId,
114400
- evaluations: normalized,
114401
- onSourceChange: setSourceEvaluationId,
114402
- onTargetChange: setTargetEvaluationId
115078
+ evaluationId1: evaluationId1,
115079
+ evaluationId2: evaluationId2,
115080
+ evaluations: compareDrawerEvaluations,
115081
+ onEvaluationId1Change: onCompareUrlChange ? handleEvaluationId1Change : setEvaluationId1,
115082
+ onEvaluationId2Change: onCompareUrlChange ? handleEvaluationId2Change : setEvaluationId2
114403
115083
  }), !onRowClick && /*#__PURE__*/ React.createElement(EvaluationDetailsDrawer, {
114404
115084
  evaluation: selectedEvaluation,
114405
115085
  open: detailsDrawerOpen,
@@ -114407,6 +115087,1938 @@ const EvaluationsTable = ({ evaluations, loading = false, error = null, onRefres
114407
115087
  }));
114408
115088
  };
114409
115089
 
115090
+ function invariant(value, message) {
115091
+ if (value === false || value === null || typeof value === "undefined") {
115092
+ throw new Error(message);
115093
+ }
115094
+ }
115095
+ function warning(cond, message) {
115096
+ if (!cond) {
115097
+ if (typeof console !== "undefined") console.warn(message);
115098
+ try {
115099
+ throw new Error(message);
115100
+ } catch (e) {}
115101
+ }
115102
+ }
115103
+ function createPath({ pathname = "/", search = "", hash = "" }) {
115104
+ if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
115105
+ if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
115106
+ return pathname;
115107
+ }
115108
+ function parsePath(path) {
115109
+ let parsedPath = {};
115110
+ if (path) {
115111
+ let hashIndex = path.indexOf("#");
115112
+ if (hashIndex >= 0) {
115113
+ parsedPath.hash = path.substring(hashIndex);
115114
+ path = path.substring(0, hashIndex);
115115
+ }
115116
+ let searchIndex = path.indexOf("?");
115117
+ if (searchIndex >= 0) {
115118
+ parsedPath.search = path.substring(searchIndex);
115119
+ path = path.substring(0, searchIndex);
115120
+ }
115121
+ if (path) {
115122
+ parsedPath.pathname = path;
115123
+ }
115124
+ }
115125
+ return parsedPath;
115126
+ }
115127
+ function matchRoutes(routes, locationArg, basename = "/") {
115128
+ return matchRoutesImpl(routes, locationArg, basename, false);
115129
+ }
115130
+ function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
115131
+ let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
115132
+ let pathname = stripBasename(location.pathname || "/", basename);
115133
+ if (pathname == null) {
115134
+ return null;
115135
+ }
115136
+ let branches = flattenRoutes(routes);
115137
+ rankRouteBranches(branches);
115138
+ let matches = null;
115139
+ for(let i = 0; matches == null && i < branches.length; ++i){
115140
+ let decoded = decodePath(pathname);
115141
+ matches = matchRouteBranch(branches[i], decoded, allowPartial);
115142
+ }
115143
+ return matches;
115144
+ }
115145
+ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
115146
+ let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath)=>{
115147
+ let meta = {
115148
+ relativePath: relativePath === void 0 ? route.path || "" : relativePath,
115149
+ caseSensitive: route.caseSensitive === true,
115150
+ childrenIndex: index,
115151
+ route
115152
+ };
115153
+ if (meta.relativePath.startsWith("/")) {
115154
+ if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) {
115155
+ return;
115156
+ }
115157
+ 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.`);
115158
+ meta.relativePath = meta.relativePath.slice(parentPath.length);
115159
+ }
115160
+ let path = joinPaths([
115161
+ parentPath,
115162
+ meta.relativePath
115163
+ ]);
115164
+ let routesMeta = parentsMeta.concat(meta);
115165
+ if (route.children && route.children.length > 0) {
115166
+ invariant(// Our types know better, but runtime JS may not!
115167
+ // @ts-expect-error
115168
+ route.index !== true, `Index routes must not have child routes. Please remove all child routes from route path "${path}".`);
115169
+ flattenRoutes(route.children, branches, routesMeta, path, hasParentOptionalSegments);
115170
+ }
115171
+ if (route.path == null && !route.index) {
115172
+ return;
115173
+ }
115174
+ branches.push({
115175
+ path,
115176
+ score: computeScore(path, route.index),
115177
+ routesMeta
115178
+ });
115179
+ };
115180
+ routes.forEach((route, index)=>{
115181
+ if (route.path === "" || !route.path?.includes("?")) {
115182
+ flattenRoute(route, index);
115183
+ } else {
115184
+ for (let exploded of explodeOptionalSegments(route.path)){
115185
+ flattenRoute(route, index, true, exploded);
115186
+ }
115187
+ }
115188
+ });
115189
+ return branches;
115190
+ }
115191
+ function explodeOptionalSegments(path) {
115192
+ let segments = path.split("/");
115193
+ if (segments.length === 0) return [];
115194
+ let [first, ...rest] = segments;
115195
+ let isOptional = first.endsWith("?");
115196
+ let required = first.replace(/\?$/, "");
115197
+ if (rest.length === 0) {
115198
+ return isOptional ? [
115199
+ required,
115200
+ ""
115201
+ ] : [
115202
+ required
115203
+ ];
115204
+ }
115205
+ let restExploded = explodeOptionalSegments(rest.join("/"));
115206
+ let result = [];
115207
+ result.push(...restExploded.map((subpath)=>subpath === "" ? required : [
115208
+ required,
115209
+ subpath
115210
+ ].join("/")));
115211
+ if (isOptional) {
115212
+ result.push(...restExploded);
115213
+ }
115214
+ return result.map((exploded)=>path.startsWith("/") && exploded === "" ? "/" : exploded);
115215
+ }
115216
+ function rankRouteBranches(branches) {
115217
+ 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)));
115218
+ }
115219
+ var paramRe = /^:[\w-]+$/;
115220
+ var dynamicSegmentValue = 3;
115221
+ var indexRouteValue = 2;
115222
+ var emptySegmentValue = 1;
115223
+ var staticSegmentValue = 10;
115224
+ var splatPenalty = -2;
115225
+ var isSplat = (s)=>s === "*";
115226
+ function computeScore(path, index) {
115227
+ let segments = path.split("/");
115228
+ let initialScore = segments.length;
115229
+ if (segments.some(isSplat)) {
115230
+ initialScore += splatPenalty;
115231
+ }
115232
+ if (index) {
115233
+ initialScore += indexRouteValue;
115234
+ }
115235
+ return segments.filter((s)=>!isSplat(s)).reduce((score, segment)=>score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
115236
+ }
115237
+ function compareIndexes(a, b) {
115238
+ let siblings = a.length === b.length && a.slice(0, -1).every((n, i)=>n === b[i]);
115239
+ return siblings ? // If two routes are siblings, we should try to match the earlier sibling
115240
+ // first. This allows people to have fine-grained control over the matching
115241
+ // behavior by simply putting routes with identical paths in the order they
115242
+ // want them tried.
115243
+ a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
115244
+ // so they sort equally.
115245
+ 0;
115246
+ }
115247
+ function matchRouteBranch(branch, pathname, allowPartial = false) {
115248
+ let { routesMeta } = branch;
115249
+ let matchedParams = {};
115250
+ let matchedPathname = "/";
115251
+ let matches = [];
115252
+ for(let i = 0; i < routesMeta.length; ++i){
115253
+ let meta = routesMeta[i];
115254
+ let end = i === routesMeta.length - 1;
115255
+ let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
115256
+ let match = matchPath({
115257
+ path: meta.relativePath,
115258
+ caseSensitive: meta.caseSensitive,
115259
+ end
115260
+ }, remainingPathname);
115261
+ let route = meta.route;
115262
+ if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
115263
+ match = matchPath({
115264
+ path: meta.relativePath,
115265
+ caseSensitive: meta.caseSensitive,
115266
+ end: false
115267
+ }, remainingPathname);
115268
+ }
115269
+ if (!match) {
115270
+ return null;
115271
+ }
115272
+ Object.assign(matchedParams, match.params);
115273
+ matches.push({
115274
+ // TODO: Can this as be avoided?
115275
+ params: matchedParams,
115276
+ pathname: joinPaths([
115277
+ matchedPathname,
115278
+ match.pathname
115279
+ ]),
115280
+ pathnameBase: normalizePathname(joinPaths([
115281
+ matchedPathname,
115282
+ match.pathnameBase
115283
+ ])),
115284
+ route
115285
+ });
115286
+ if (match.pathnameBase !== "/") {
115287
+ matchedPathname = joinPaths([
115288
+ matchedPathname,
115289
+ match.pathnameBase
115290
+ ]);
115291
+ }
115292
+ }
115293
+ return matches;
115294
+ }
115295
+ function matchPath(pattern, pathname) {
115296
+ if (typeof pattern === "string") {
115297
+ pattern = {
115298
+ path: pattern,
115299
+ caseSensitive: false,
115300
+ end: true
115301
+ };
115302
+ }
115303
+ let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
115304
+ let match = pathname.match(matcher);
115305
+ if (!match) return null;
115306
+ let matchedPathname = match[0];
115307
+ let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
115308
+ let captureGroups = match.slice(1);
115309
+ let params = compiledParams.reduce((memo2, { paramName, isOptional }, index)=>{
115310
+ if (paramName === "*") {
115311
+ let splatValue = captureGroups[index] || "";
115312
+ pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
115313
+ }
115314
+ const value = captureGroups[index];
115315
+ if (isOptional && !value) {
115316
+ memo2[paramName] = void 0;
115317
+ } else {
115318
+ memo2[paramName] = (value || "").replace(/%2F/g, "/");
115319
+ }
115320
+ return memo2;
115321
+ }, {});
115322
+ return {
115323
+ params,
115324
+ pathname: matchedPathname,
115325
+ pathnameBase,
115326
+ pattern
115327
+ };
115328
+ }
115329
+ function compilePath(path, caseSensitive = false, end = true) {
115330
+ 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(/\*$/, "/*")}".`);
115331
+ let params = [];
115332
+ let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (match, paramName, isOptional, index, str)=>{
115333
+ params.push({
115334
+ paramName,
115335
+ isOptional: isOptional != null
115336
+ });
115337
+ if (isOptional) {
115338
+ let nextChar = str.charAt(index + match.length);
115339
+ if (nextChar && nextChar !== "/") {
115340
+ return "/([^\\/]*)";
115341
+ }
115342
+ return "(?:/([^\\/]*))?";
115343
+ }
115344
+ return "/([^\\/]+)";
115345
+ }).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2");
115346
+ if (path.endsWith("*")) {
115347
+ params.push({
115348
+ paramName: "*"
115349
+ });
115350
+ regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
115351
+ } else if (end) {
115352
+ regexpSource += "\\/*$";
115353
+ } else if (path !== "" && path !== "/") {
115354
+ regexpSource += "(?:(?=\\/|$))";
115355
+ } else ;
115356
+ let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
115357
+ return [
115358
+ matcher,
115359
+ params
115360
+ ];
115361
+ }
115362
+ function decodePath(value) {
115363
+ try {
115364
+ return value.split("/").map((v)=>decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
115365
+ } catch (error) {
115366
+ 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}).`);
115367
+ return value;
115368
+ }
115369
+ }
115370
+ function stripBasename(pathname, basename) {
115371
+ if (basename === "/") return pathname;
115372
+ if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
115373
+ return null;
115374
+ }
115375
+ let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
115376
+ let nextChar = pathname.charAt(startIndex);
115377
+ if (nextChar && nextChar !== "/") {
115378
+ return null;
115379
+ }
115380
+ return pathname.slice(startIndex) || "/";
115381
+ }
115382
+ var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
115383
+ function resolvePath(to, fromPathname = "/") {
115384
+ let { pathname: toPathname, search = "", hash = "" } = typeof to === "string" ? parsePath(to) : to;
115385
+ let pathname;
115386
+ if (toPathname) {
115387
+ toPathname = toPathname.replace(/\/\/+/g, "/");
115388
+ if (toPathname.startsWith("/")) {
115389
+ pathname = resolvePathname(toPathname.substring(1), "/");
115390
+ } else {
115391
+ pathname = resolvePathname(toPathname, fromPathname);
115392
+ }
115393
+ } else {
115394
+ pathname = fromPathname;
115395
+ }
115396
+ return {
115397
+ pathname,
115398
+ search: normalizeSearch(search),
115399
+ hash: normalizeHash(hash)
115400
+ };
115401
+ }
115402
+ function resolvePathname(relativePath, fromPathname) {
115403
+ let segments = fromPathname.replace(/\/+$/, "").split("/");
115404
+ let relativeSegments = relativePath.split("/");
115405
+ relativeSegments.forEach((segment)=>{
115406
+ if (segment === "..") {
115407
+ if (segments.length > 1) segments.pop();
115408
+ } else if (segment !== ".") {
115409
+ segments.push(segment);
115410
+ }
115411
+ });
115412
+ return segments.length > 1 ? segments.join("/") : "/";
115413
+ }
115414
+ function getInvalidPathError(char, field, dest, path) {
115415
+ 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.`;
115416
+ }
115417
+ function getPathContributingMatches(matches) {
115418
+ return matches.filter((match, index)=>index === 0 || match.route.path && match.route.path.length > 0);
115419
+ }
115420
+ function getResolveToMatches(matches) {
115421
+ let pathMatches = getPathContributingMatches(matches);
115422
+ return pathMatches.map((match, idx)=>idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);
115423
+ }
115424
+ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
115425
+ let to;
115426
+ if (typeof toArg === "string") {
115427
+ to = parsePath(toArg);
115428
+ } else {
115429
+ to = {
115430
+ ...toArg
115431
+ };
115432
+ invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
115433
+ invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
115434
+ invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
115435
+ }
115436
+ let isEmptyPath = toArg === "" || to.pathname === "";
115437
+ let toPathname = isEmptyPath ? "/" : to.pathname;
115438
+ let from;
115439
+ if (toPathname == null) {
115440
+ from = locationPathname;
115441
+ } else {
115442
+ let routePathnameIndex = routePathnames.length - 1;
115443
+ if (!isPathRelative && toPathname.startsWith("..")) {
115444
+ let toSegments = toPathname.split("/");
115445
+ while(toSegments[0] === ".."){
115446
+ toSegments.shift();
115447
+ routePathnameIndex -= 1;
115448
+ }
115449
+ to.pathname = toSegments.join("/");
115450
+ }
115451
+ from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
115452
+ }
115453
+ let path = resolvePath(to, from);
115454
+ let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
115455
+ let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
115456
+ if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
115457
+ path.pathname += "/";
115458
+ }
115459
+ return path;
115460
+ }
115461
+ var joinPaths = (paths)=>paths.join("/").replace(/\/\/+/g, "/");
115462
+ var normalizePathname = (pathname)=>pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
115463
+ var normalizeSearch = (search)=>!search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
115464
+ var normalizeHash = (hash)=>!hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
115465
+ var ErrorResponseImpl = class {
115466
+ constructor(status, statusText, data2, internal = false){
115467
+ this.status = status;
115468
+ this.statusText = statusText || "";
115469
+ this.internal = internal;
115470
+ if (data2 instanceof Error) {
115471
+ this.data = data2.toString();
115472
+ this.error = data2;
115473
+ } else {
115474
+ this.data = data2;
115475
+ }
115476
+ }
115477
+ };
115478
+ function isRouteErrorResponse(error) {
115479
+ return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
115480
+ }
115481
+ function getRoutePattern(matches) {
115482
+ return matches.map((m)=>m.route.path).filter(Boolean).join("/").replace(/\/\/*/g, "/") || "/";
115483
+ }
115484
+ var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
115485
+ function parseToInfo(_to, basename) {
115486
+ let to = _to;
115487
+ if (typeof to !== "string" || !ABSOLUTE_URL_REGEX.test(to)) {
115488
+ return {
115489
+ absoluteURL: void 0,
115490
+ isExternal: false,
115491
+ to
115492
+ };
115493
+ }
115494
+ let absoluteURL = to;
115495
+ let isExternal = false;
115496
+ if (isBrowser) {
115497
+ try {
115498
+ let currentUrl = new URL(window.location.href);
115499
+ let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
115500
+ let path = stripBasename(targetUrl.pathname, basename);
115501
+ if (targetUrl.origin === currentUrl.origin && path != null) {
115502
+ to = path + targetUrl.search + targetUrl.hash;
115503
+ } else {
115504
+ isExternal = true;
115505
+ }
115506
+ } catch (e) {
115507
+ warning(false, `<Link to="${to}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`);
115508
+ }
115509
+ }
115510
+ return {
115511
+ absoluteURL,
115512
+ isExternal,
115513
+ to
115514
+ };
115515
+ }
115516
+ Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
115517
+ // lib/router/router.ts
115518
+ var validMutationMethodsArr = [
115519
+ "POST",
115520
+ "PUT",
115521
+ "PATCH",
115522
+ "DELETE"
115523
+ ];
115524
+ new Set(validMutationMethodsArr);
115525
+ var validRequestMethodsArr = [
115526
+ "GET",
115527
+ ...validMutationMethodsArr
115528
+ ];
115529
+ new Set(validRequestMethodsArr);
115530
+ var DataRouterContext = React__namespace.createContext(null);
115531
+ DataRouterContext.displayName = "DataRouter";
115532
+ var DataRouterStateContext = React__namespace.createContext(null);
115533
+ DataRouterStateContext.displayName = "DataRouterState";
115534
+ var RSCRouterContext = React__namespace.createContext(false);
115535
+ var ViewTransitionContext = React__namespace.createContext({
115536
+ isTransitioning: false
115537
+ });
115538
+ ViewTransitionContext.displayName = "ViewTransition";
115539
+ var FetchersContext = React__namespace.createContext(/* @__PURE__ */ new Map());
115540
+ FetchersContext.displayName = "Fetchers";
115541
+ var AwaitContext = React__namespace.createContext(null);
115542
+ AwaitContext.displayName = "Await";
115543
+ var NavigationContext = React__namespace.createContext(null);
115544
+ NavigationContext.displayName = "Navigation";
115545
+ var LocationContext = React__namespace.createContext(null);
115546
+ LocationContext.displayName = "Location";
115547
+ var RouteContext = React__namespace.createContext({
115548
+ outlet: null,
115549
+ matches: [],
115550
+ isDataRoute: false
115551
+ });
115552
+ RouteContext.displayName = "Route";
115553
+ var RouteErrorContext = React__namespace.createContext(null);
115554
+ RouteErrorContext.displayName = "RouteError";
115555
+ // lib/errors.ts
115556
+ var ERROR_DIGEST_BASE = "REACT_ROUTER_ERROR";
115557
+ var ERROR_DIGEST_REDIRECT = "REDIRECT";
115558
+ var ERROR_DIGEST_ROUTE_ERROR_RESPONSE = "ROUTE_ERROR_RESPONSE";
115559
+ function decodeRedirectErrorDigest(digest) {
115560
+ if (digest.startsWith(`${ERROR_DIGEST_BASE}:${ERROR_DIGEST_REDIRECT}:{`)) {
115561
+ try {
115562
+ let parsed = JSON.parse(digest.slice(28));
115563
+ 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") {
115564
+ return parsed;
115565
+ }
115566
+ } catch {}
115567
+ }
115568
+ }
115569
+ function decodeRouteErrorResponseDigest(digest) {
115570
+ if (digest.startsWith(`${ERROR_DIGEST_BASE}:${ERROR_DIGEST_ROUTE_ERROR_RESPONSE}:{`)) {
115571
+ try {
115572
+ let parsed = JSON.parse(digest.slice(40));
115573
+ if (typeof parsed === "object" && parsed && typeof parsed.status === "number" && typeof parsed.statusText === "string") {
115574
+ return new ErrorResponseImpl(parsed.status, parsed.statusText, parsed.data);
115575
+ }
115576
+ } catch {}
115577
+ }
115578
+ }
115579
+ // lib/hooks.tsx
115580
+ function useHref(to, { relative } = {}) {
115581
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115582
+ // router loaded. We can help them understand how to avoid that.
115583
+ `useHref() may be used only in the context of a <Router> component.`);
115584
+ let { basename, navigator } = React__namespace.useContext(NavigationContext);
115585
+ let { hash, pathname, search } = useResolvedPath(to, {
115586
+ relative
115587
+ });
115588
+ let joinedPathname = pathname;
115589
+ if (basename !== "/") {
115590
+ joinedPathname = pathname === "/" ? basename : joinPaths([
115591
+ basename,
115592
+ pathname
115593
+ ]);
115594
+ }
115595
+ return navigator.createHref({
115596
+ pathname: joinedPathname,
115597
+ search,
115598
+ hash
115599
+ });
115600
+ }
115601
+ function useInRouterContext() {
115602
+ return React__namespace.useContext(LocationContext) != null;
115603
+ }
115604
+ function useLocation() {
115605
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115606
+ // router loaded. We can help them understand how to avoid that.
115607
+ `useLocation() may be used only in the context of a <Router> component.`);
115608
+ return React__namespace.useContext(LocationContext).location;
115609
+ }
115610
+ var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`;
115611
+ function useIsomorphicLayoutEffect$1(cb) {
115612
+ let isStatic = React__namespace.useContext(NavigationContext).static;
115613
+ if (!isStatic) {
115614
+ React__namespace.useLayoutEffect(cb);
115615
+ }
115616
+ }
115617
+ function useNavigate() {
115618
+ let { isDataRoute } = React__namespace.useContext(RouteContext);
115619
+ return isDataRoute ? useNavigateStable() : useNavigateUnstable();
115620
+ }
115621
+ function useNavigateUnstable() {
115622
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115623
+ // router loaded. We can help them understand how to avoid that.
115624
+ `useNavigate() may be used only in the context of a <Router> component.`);
115625
+ let dataRouterContext = React__namespace.useContext(DataRouterContext);
115626
+ let { basename, navigator } = React__namespace.useContext(NavigationContext);
115627
+ let { matches } = React__namespace.useContext(RouteContext);
115628
+ let { pathname: locationPathname } = useLocation();
115629
+ let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
115630
+ let activeRef = React__namespace.useRef(false);
115631
+ useIsomorphicLayoutEffect$1(()=>{
115632
+ activeRef.current = true;
115633
+ });
115634
+ let navigate = React__namespace.useCallback((to, options = {})=>{
115635
+ warning(activeRef.current, navigateEffectWarning);
115636
+ if (!activeRef.current) return;
115637
+ if (typeof to === "number") {
115638
+ navigator.go(to);
115639
+ return;
115640
+ }
115641
+ let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
115642
+ if (dataRouterContext == null && basename !== "/") {
115643
+ path.pathname = path.pathname === "/" ? basename : joinPaths([
115644
+ basename,
115645
+ path.pathname
115646
+ ]);
115647
+ }
115648
+ (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
115649
+ }, [
115650
+ basename,
115651
+ navigator,
115652
+ routePathnamesJson,
115653
+ locationPathname,
115654
+ dataRouterContext
115655
+ ]);
115656
+ return navigate;
115657
+ }
115658
+ React__namespace.createContext(null);
115659
+ function useResolvedPath(to, { relative } = {}) {
115660
+ let { matches } = React__namespace.useContext(RouteContext);
115661
+ let { pathname: locationPathname } = useLocation();
115662
+ let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
115663
+ return React__namespace.useMemo(()=>resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [
115664
+ to,
115665
+ routePathnamesJson,
115666
+ locationPathname,
115667
+ relative
115668
+ ]);
115669
+ }
115670
+ function useRoutesImpl(routes, locationArg, dataRouterOpts) {
115671
+ invariant(useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the
115672
+ // router loaded. We can help them understand how to avoid that.
115673
+ `useRoutes() may be used only in the context of a <Router> component.`);
115674
+ let { navigator } = React__namespace.useContext(NavigationContext);
115675
+ let { matches: parentMatches } = React__namespace.useContext(RouteContext);
115676
+ let routeMatch = parentMatches[parentMatches.length - 1];
115677
+ let parentParams = routeMatch ? routeMatch.params : {};
115678
+ let parentPathname = routeMatch ? routeMatch.pathname : "/";
115679
+ let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
115680
+ let parentRoute = routeMatch && routeMatch.route;
115681
+ {
115682
+ let parentPath = parentRoute && parentRoute.path || "";
115683
+ 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.
115684
+
115685
+ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`);
115686
+ }
115687
+ let locationFromContext = useLocation();
115688
+ let location;
115689
+ {
115690
+ location = locationFromContext;
115691
+ }
115692
+ let pathname = location.pathname || "/";
115693
+ let remainingPathname = pathname;
115694
+ if (parentPathnameBase !== "/") {
115695
+ let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
115696
+ let segments = pathname.replace(/^\//, "").split("/");
115697
+ remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
115698
+ }
115699
+ let matches = matchRoutes(routes, {
115700
+ pathname: remainingPathname
115701
+ });
115702
+ {
115703
+ warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `);
115704
+ 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.`);
115705
+ }
115706
+ let renderedMatches = _renderMatches(matches && matches.map((match)=>Object.assign({}, match, {
115707
+ params: Object.assign({}, parentParams, match.params),
115708
+ pathname: joinPaths([
115709
+ parentPathnameBase,
115710
+ // Re-encode pathnames that were decoded inside matchRoutes.
115711
+ // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses
115712
+ // `new URL()` internally and we need to prevent it from treating
115713
+ // them as separators
115714
+ navigator.encodeLocation ? navigator.encodeLocation(match.pathname.replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathname
115715
+ ]),
115716
+ pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([
115717
+ parentPathnameBase,
115718
+ // Re-encode pathnames that were decoded inside matchRoutes
115719
+ // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses
115720
+ // `new URL()` internally and we need to prevent it from treating
115721
+ // them as separators
115722
+ navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase.replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathnameBase
115723
+ ])
115724
+ })), parentMatches, dataRouterOpts);
115725
+ return renderedMatches;
115726
+ }
115727
+ function DefaultErrorComponent() {
115728
+ let error = useRouteError();
115729
+ let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
115730
+ let stack = error instanceof Error ? error.stack : null;
115731
+ let lightgrey = "rgba(200,200,200, 0.5)";
115732
+ let preStyles = {
115733
+ padding: "0.5rem",
115734
+ backgroundColor: lightgrey
115735
+ };
115736
+ let codeStyles = {
115737
+ padding: "2px 4px",
115738
+ backgroundColor: lightgrey
115739
+ };
115740
+ let devInfo = null;
115741
+ {
115742
+ console.error("Error handled by React Router default ErrorBoundary:", error);
115743
+ devInfo = /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("p", null, "\u{1F4BF} Hey developer \u{1F44B}"), /* @__PURE__ */ React__namespace.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /* @__PURE__ */ React__namespace.createElement("code", {
115744
+ style: codeStyles
115745
+ }, "ErrorBoundary"), " or", " ", /* @__PURE__ */ React__namespace.createElement("code", {
115746
+ style: codeStyles
115747
+ }, "errorElement"), " prop on your route."));
115748
+ }
115749
+ return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h2", null, "Unexpected Application Error!"), /* @__PURE__ */ React__namespace.createElement("h3", {
115750
+ style: {
115751
+ fontStyle: "italic"
115752
+ }
115753
+ }, message), stack ? /* @__PURE__ */ React__namespace.createElement("pre", {
115754
+ style: preStyles
115755
+ }, stack) : null, devInfo);
115756
+ }
115757
+ var defaultErrorElement = /* @__PURE__ */ React__namespace.createElement(DefaultErrorComponent, null);
115758
+ var RenderErrorBoundary = class extends React__namespace.Component {
115759
+ static getDerivedStateFromError(error) {
115760
+ return {
115761
+ error
115762
+ };
115763
+ }
115764
+ static getDerivedStateFromProps(props, state) {
115765
+ if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
115766
+ return {
115767
+ error: props.error,
115768
+ location: props.location,
115769
+ revalidation: props.revalidation
115770
+ };
115771
+ }
115772
+ return {
115773
+ error: props.error !== void 0 ? props.error : state.error,
115774
+ location: state.location,
115775
+ revalidation: props.revalidation || state.revalidation
115776
+ };
115777
+ }
115778
+ componentDidCatch(error, errorInfo) {
115779
+ if (this.props.onError) {
115780
+ this.props.onError(error, errorInfo);
115781
+ } else {
115782
+ console.error("React Router caught the following error during render", error);
115783
+ }
115784
+ }
115785
+ render() {
115786
+ let error = this.state.error;
115787
+ if (this.context && typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
115788
+ const decoded = decodeRouteErrorResponseDigest(error.digest);
115789
+ if (decoded) error = decoded;
115790
+ }
115791
+ let result = error !== void 0 ? /* @__PURE__ */ React__namespace.createElement(RouteContext.Provider, {
115792
+ value: this.props.routeContext
115793
+ }, /* @__PURE__ */ React__namespace.createElement(RouteErrorContext.Provider, {
115794
+ value: error,
115795
+ children: this.props.component
115796
+ })) : this.props.children;
115797
+ if (this.context) {
115798
+ return /* @__PURE__ */ React__namespace.createElement(RSCErrorHandler, {
115799
+ error
115800
+ }, result);
115801
+ }
115802
+ return result;
115803
+ }
115804
+ constructor(props){
115805
+ super(props);
115806
+ this.state = {
115807
+ location: props.location,
115808
+ revalidation: props.revalidation,
115809
+ error: props.error
115810
+ };
115811
+ }
115812
+ };
115813
+ RenderErrorBoundary.contextType = RSCRouterContext;
115814
+ var errorRedirectHandledMap = /* @__PURE__ */ new WeakMap();
115815
+ function RSCErrorHandler({ children, error }) {
115816
+ let { basename } = React__namespace.useContext(NavigationContext);
115817
+ if (typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
115818
+ let redirect2 = decodeRedirectErrorDigest(error.digest);
115819
+ if (redirect2) {
115820
+ let existingRedirect = errorRedirectHandledMap.get(error);
115821
+ if (existingRedirect) throw existingRedirect;
115822
+ let parsed = parseToInfo(redirect2.location, basename);
115823
+ if (isBrowser && !errorRedirectHandledMap.get(error)) {
115824
+ if (parsed.isExternal || redirect2.reloadDocument) {
115825
+ window.location.href = parsed.absoluteURL || parsed.to;
115826
+ } else {
115827
+ const redirectPromise = Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(parsed.to, {
115828
+ replace: redirect2.replace
115829
+ }));
115830
+ errorRedirectHandledMap.set(error, redirectPromise);
115831
+ throw redirectPromise;
115832
+ }
115833
+ }
115834
+ return /* @__PURE__ */ React__namespace.createElement("meta", {
115835
+ httpEquiv: "refresh",
115836
+ content: `0;url=${parsed.absoluteURL || parsed.to}`
115837
+ });
115838
+ }
115839
+ }
115840
+ return children;
115841
+ }
115842
+ function RenderedRoute({ routeContext, match, children }) {
115843
+ let dataRouterContext = React__namespace.useContext(DataRouterContext);
115844
+ if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
115845
+ dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
115846
+ }
115847
+ return /* @__PURE__ */ React__namespace.createElement(RouteContext.Provider, {
115848
+ value: routeContext
115849
+ }, children);
115850
+ }
115851
+ function _renderMatches(matches, parentMatches = [], dataRouterOpts) {
115852
+ let dataRouterState = dataRouterOpts?.state;
115853
+ if (matches == null) {
115854
+ if (!dataRouterState) {
115855
+ return null;
115856
+ }
115857
+ if (dataRouterState.errors) {
115858
+ matches = dataRouterState.matches;
115859
+ } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) {
115860
+ matches = dataRouterState.matches;
115861
+ } else {
115862
+ return null;
115863
+ }
115864
+ }
115865
+ let renderedMatches = matches;
115866
+ let errors = dataRouterState?.errors;
115867
+ if (errors != null) {
115868
+ let errorIndex = renderedMatches.findIndex((m)=>m.route.id && errors?.[m.route.id] !== void 0);
115869
+ invariant(errorIndex >= 0, `Could not find a matching route for errors on route IDs: ${Object.keys(errors).join(",")}`);
115870
+ renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
115871
+ }
115872
+ let renderFallback = false;
115873
+ let fallbackIndex = -1;
115874
+ if (dataRouterOpts && dataRouterState) {
115875
+ renderFallback = dataRouterState.renderFallback;
115876
+ for(let i = 0; i < renderedMatches.length; i++){
115877
+ let match = renderedMatches[i];
115878
+ if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
115879
+ fallbackIndex = i;
115880
+ }
115881
+ if (match.route.id) {
115882
+ let { loaderData, errors: errors2 } = dataRouterState;
115883
+ let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0);
115884
+ if (match.route.lazy || needsToRunLoader) {
115885
+ if (dataRouterOpts.isStatic) {
115886
+ renderFallback = true;
115887
+ }
115888
+ if (fallbackIndex >= 0) {
115889
+ renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
115890
+ } else {
115891
+ renderedMatches = [
115892
+ renderedMatches[0]
115893
+ ];
115894
+ }
115895
+ break;
115896
+ }
115897
+ }
115898
+ }
115899
+ }
115900
+ let onErrorHandler = dataRouterOpts?.onError;
115901
+ let onError = dataRouterState && onErrorHandler ? (error, errorInfo)=>{
115902
+ onErrorHandler(error, {
115903
+ location: dataRouterState.location,
115904
+ params: dataRouterState.matches?.[0]?.params ?? {},
115905
+ unstable_pattern: getRoutePattern(dataRouterState.matches),
115906
+ errorInfo
115907
+ });
115908
+ } : void 0;
115909
+ return renderedMatches.reduceRight((outlet, match, index)=>{
115910
+ let error;
115911
+ let shouldRenderHydrateFallback = false;
115912
+ let errorElement = null;
115913
+ let hydrateFallbackElement = null;
115914
+ if (dataRouterState) {
115915
+ error = errors && match.route.id ? errors[match.route.id] : void 0;
115916
+ errorElement = match.route.errorElement || defaultErrorElement;
115917
+ if (renderFallback) {
115918
+ if (fallbackIndex < 0 && index === 0) {
115919
+ warningOnce("route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration");
115920
+ shouldRenderHydrateFallback = true;
115921
+ hydrateFallbackElement = null;
115922
+ } else if (fallbackIndex === index) {
115923
+ shouldRenderHydrateFallback = true;
115924
+ hydrateFallbackElement = match.route.hydrateFallbackElement || null;
115925
+ }
115926
+ }
115927
+ }
115928
+ let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1));
115929
+ let getChildren = ()=>{
115930
+ let children;
115931
+ if (error) {
115932
+ children = errorElement;
115933
+ } else if (shouldRenderHydrateFallback) {
115934
+ children = hydrateFallbackElement;
115935
+ } else if (match.route.Component) {
115936
+ children = /* @__PURE__ */ React__namespace.createElement(match.route.Component, null);
115937
+ } else if (match.route.element) {
115938
+ children = match.route.element;
115939
+ } else {
115940
+ children = outlet;
115941
+ }
115942
+ return /* @__PURE__ */ React__namespace.createElement(RenderedRoute, {
115943
+ match,
115944
+ routeContext: {
115945
+ outlet,
115946
+ matches: matches2,
115947
+ isDataRoute: dataRouterState != null
115948
+ },
115949
+ children
115950
+ });
115951
+ };
115952
+ return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React__namespace.createElement(RenderErrorBoundary, {
115953
+ location: dataRouterState.location,
115954
+ revalidation: dataRouterState.revalidation,
115955
+ component: errorElement,
115956
+ error,
115957
+ children: getChildren(),
115958
+ routeContext: {
115959
+ outlet: null,
115960
+ matches: matches2,
115961
+ isDataRoute: true
115962
+ },
115963
+ onError
115964
+ }) : getChildren();
115965
+ }, null);
115966
+ }
115967
+ function getDataRouterConsoleError(hookName) {
115968
+ return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
115969
+ }
115970
+ function useDataRouterContext(hookName) {
115971
+ let ctx = React__namespace.useContext(DataRouterContext);
115972
+ invariant(ctx, getDataRouterConsoleError(hookName));
115973
+ return ctx;
115974
+ }
115975
+ function useDataRouterState(hookName) {
115976
+ let state = React__namespace.useContext(DataRouterStateContext);
115977
+ invariant(state, getDataRouterConsoleError(hookName));
115978
+ return state;
115979
+ }
115980
+ function useRouteContext(hookName) {
115981
+ let route = React__namespace.useContext(RouteContext);
115982
+ invariant(route, getDataRouterConsoleError(hookName));
115983
+ return route;
115984
+ }
115985
+ function useCurrentRouteId(hookName) {
115986
+ let route = useRouteContext(hookName);
115987
+ let thisRoute = route.matches[route.matches.length - 1];
115988
+ invariant(thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"`);
115989
+ return thisRoute.route.id;
115990
+ }
115991
+ function useRouteId() {
115992
+ return useCurrentRouteId("useRouteId" /* UseRouteId */ );
115993
+ }
115994
+ function useRouteError() {
115995
+ let error = React__namespace.useContext(RouteErrorContext);
115996
+ let state = useDataRouterState("useRouteError" /* UseRouteError */ );
115997
+ let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */ );
115998
+ if (error !== void 0) {
115999
+ return error;
116000
+ }
116001
+ return state.errors?.[routeId];
116002
+ }
116003
+ function useNavigateStable() {
116004
+ let { router } = useDataRouterContext("useNavigate" /* UseNavigateStable */ );
116005
+ let id = useCurrentRouteId("useNavigate" /* UseNavigateStable */ );
116006
+ let activeRef = React__namespace.useRef(false);
116007
+ useIsomorphicLayoutEffect$1(()=>{
116008
+ activeRef.current = true;
116009
+ });
116010
+ let navigate = React__namespace.useCallback(async (to, options = {})=>{
116011
+ warning(activeRef.current, navigateEffectWarning);
116012
+ if (!activeRef.current) return;
116013
+ if (typeof to === "number") {
116014
+ await router.navigate(to);
116015
+ } else {
116016
+ await router.navigate(to, {
116017
+ fromRouteId: id,
116018
+ ...options
116019
+ });
116020
+ }
116021
+ }, [
116022
+ router,
116023
+ id
116024
+ ]);
116025
+ return navigate;
116026
+ }
116027
+ var alreadyWarned = {};
116028
+ function warningOnce(key, cond, message) {
116029
+ if (!cond && !alreadyWarned[key]) {
116030
+ alreadyWarned[key] = true;
116031
+ warning(false, message);
116032
+ }
116033
+ }
116034
+ React__namespace.memo(DataRoutes);
116035
+ function DataRoutes({ routes, future, state, isStatic, onError }) {
116036
+ return useRoutesImpl(routes, void 0, {
116037
+ state,
116038
+ isStatic,
116039
+ onError});
116040
+ }
116041
+ // lib/dom/dom.ts
116042
+ var defaultMethod = "get";
116043
+ var defaultEncType = "application/x-www-form-urlencoded";
116044
+ function isHtmlElement(object) {
116045
+ return typeof HTMLElement !== "undefined" && object instanceof HTMLElement;
116046
+ }
116047
+ function isButtonElement(object) {
116048
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
116049
+ }
116050
+ function isFormElement(object) {
116051
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
116052
+ }
116053
+ function isInputElement(object) {
116054
+ return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
116055
+ }
116056
+ function isModifiedEvent(event) {
116057
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
116058
+ }
116059
+ function shouldProcessLinkClick(event, target) {
116060
+ return event.button === 0 && // Ignore everything but left clicks
116061
+ (!target || target === "_self") && // Let browser handle "target=_blank" etc.
116062
+ !isModifiedEvent(event);
116063
+ }
116064
+ function createSearchParams(init = "") {
116065
+ return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key)=>{
116066
+ let value = init[key];
116067
+ return memo2.concat(Array.isArray(value) ? value.map((v)=>[
116068
+ key,
116069
+ v
116070
+ ]) : [
116071
+ [
116072
+ key,
116073
+ value
116074
+ ]
116075
+ ]);
116076
+ }, []));
116077
+ }
116078
+ function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
116079
+ let searchParams = createSearchParams(locationSearch);
116080
+ if (defaultSearchParams) {
116081
+ defaultSearchParams.forEach((_, key)=>{
116082
+ if (!searchParams.has(key)) {
116083
+ defaultSearchParams.getAll(key).forEach((value)=>{
116084
+ searchParams.append(key, value);
116085
+ });
116086
+ }
116087
+ });
116088
+ }
116089
+ return searchParams;
116090
+ }
116091
+ var _formDataSupportsSubmitter = null;
116092
+ function isFormDataSubmitterSupported() {
116093
+ if (_formDataSupportsSubmitter === null) {
116094
+ try {
116095
+ new FormData(document.createElement("form"), // @ts-expect-error if FormData supports the submitter parameter, this will throw
116096
+ 0);
116097
+ _formDataSupportsSubmitter = false;
116098
+ } catch (e) {
116099
+ _formDataSupportsSubmitter = true;
116100
+ }
116101
+ }
116102
+ return _formDataSupportsSubmitter;
116103
+ }
116104
+ var supportedFormEncTypes = /* @__PURE__ */ new Set([
116105
+ "application/x-www-form-urlencoded",
116106
+ "multipart/form-data",
116107
+ "text/plain"
116108
+ ]);
116109
+ function getFormEncType(encType) {
116110
+ if (encType != null && !supportedFormEncTypes.has(encType)) {
116111
+ warning(false, `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`);
116112
+ return null;
116113
+ }
116114
+ return encType;
116115
+ }
116116
+ function getFormSubmissionInfo(target, basename) {
116117
+ let method;
116118
+ let action;
116119
+ let encType;
116120
+ let formData;
116121
+ let body;
116122
+ if (isFormElement(target)) {
116123
+ let attr = target.getAttribute("action");
116124
+ action = attr ? stripBasename(attr, basename) : null;
116125
+ method = target.getAttribute("method") || defaultMethod;
116126
+ encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
116127
+ formData = new FormData(target);
116128
+ } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
116129
+ let form = target.form;
116130
+ if (form == null) {
116131
+ throw new Error(`Cannot submit a <button> or <input type="submit"> without a <form>`);
116132
+ }
116133
+ let attr = target.getAttribute("formaction") || form.getAttribute("action");
116134
+ action = attr ? stripBasename(attr, basename) : null;
116135
+ method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
116136
+ encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
116137
+ formData = new FormData(form, target);
116138
+ if (!isFormDataSubmitterSupported()) {
116139
+ let { name, type, value } = target;
116140
+ if (type === "image") {
116141
+ let prefix = name ? `${name}.` : "";
116142
+ formData.append(`${prefix}x`, "0");
116143
+ formData.append(`${prefix}y`, "0");
116144
+ } else if (name) {
116145
+ formData.append(name, value);
116146
+ }
116147
+ }
116148
+ } else if (isHtmlElement(target)) {
116149
+ throw new Error(`Cannot submit element that is not <form>, <button>, or <input type="submit|image">`);
116150
+ } else {
116151
+ method = defaultMethod;
116152
+ action = null;
116153
+ encType = defaultEncType;
116154
+ body = target;
116155
+ }
116156
+ if (formData && encType === "text/plain") {
116157
+ body = formData;
116158
+ formData = void 0;
116159
+ }
116160
+ return {
116161
+ action,
116162
+ method: method.toLowerCase(),
116163
+ encType,
116164
+ formData,
116165
+ body
116166
+ };
116167
+ }
116168
+ Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
116169
+ // lib/dom/ssr/invariant.ts
116170
+ function invariant2(value, message) {
116171
+ if (value === false || value === null || typeof value === "undefined") {
116172
+ throw new Error(message);
116173
+ }
116174
+ }
116175
+ function singleFetchUrl(reqUrl, basename, trailingSlashAware, extension) {
116176
+ let url = typeof reqUrl === "string" ? new URL(reqUrl, // This can be called during the SSR flow via PrefetchPageLinksImpl so
116177
+ // don't assume window is available
116178
+ typeof window === "undefined" ? "server://singlefetch/" : window.location.origin) : reqUrl;
116179
+ if (trailingSlashAware) {
116180
+ if (url.pathname.endsWith("/")) {
116181
+ url.pathname = `${url.pathname}_.${extension}`;
116182
+ } else {
116183
+ url.pathname = `${url.pathname}.${extension}`;
116184
+ }
116185
+ } else {
116186
+ if (url.pathname === "/") {
116187
+ url.pathname = `_root.${extension}`;
116188
+ } else if (basename && stripBasename(url.pathname, basename) === "/") {
116189
+ url.pathname = `${basename.replace(/\/$/, "")}/_root.${extension}`;
116190
+ } else {
116191
+ url.pathname = `${url.pathname.replace(/\/$/, "")}.${extension}`;
116192
+ }
116193
+ }
116194
+ return url;
116195
+ }
116196
+ // lib/dom/ssr/routeModules.ts
116197
+ async function loadRouteModule(route, routeModulesCache) {
116198
+ if (route.id in routeModulesCache) {
116199
+ return routeModulesCache[route.id];
116200
+ }
116201
+ try {
116202
+ let routeModule = await import(/* @vite-ignore */ /* webpackIgnore: true */ route.module);
116203
+ routeModulesCache[route.id] = routeModule;
116204
+ return routeModule;
116205
+ } catch (error) {
116206
+ console.error(`Error loading route module \`${route.module}\`, reloading page...`);
116207
+ console.error(error);
116208
+ if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
116209
+ undefined) {
116210
+ throw error;
116211
+ }
116212
+ window.location.reload();
116213
+ return new Promise(()=>{});
116214
+ }
116215
+ }
116216
+ function isHtmlLinkDescriptor(object) {
116217
+ if (object == null) {
116218
+ return false;
116219
+ }
116220
+ if (object.href == null) {
116221
+ return object.rel === "preload" && typeof object.imageSrcSet === "string" && typeof object.imageSizes === "string";
116222
+ }
116223
+ return typeof object.rel === "string" && typeof object.href === "string";
116224
+ }
116225
+ async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
116226
+ let links = await Promise.all(matches.map(async (match)=>{
116227
+ let route = manifest.routes[match.route.id];
116228
+ if (route) {
116229
+ let mod = await loadRouteModule(route, routeModules);
116230
+ return mod.links ? mod.links() : [];
116231
+ }
116232
+ return [];
116233
+ }));
116234
+ return dedupeLinkDescriptors(links.flat(1).filter(isHtmlLinkDescriptor).filter((link)=>link.rel === "stylesheet" || link.rel === "preload").map((link)=>link.rel === "stylesheet" ? {
116235
+ ...link,
116236
+ rel: "prefetch",
116237
+ as: "style"
116238
+ } : {
116239
+ ...link,
116240
+ rel: "prefetch"
116241
+ }));
116242
+ }
116243
+ function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
116244
+ let isNew = (match, index)=>{
116245
+ if (!currentMatches[index]) return true;
116246
+ return match.route.id !== currentMatches[index].route.id;
116247
+ };
116248
+ let matchPathChanged = (match, index)=>{
116249
+ return(// param change, /users/123 -> /users/456
116250
+ currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path
116251
+ // e.g. /files/images/avatar.jpg -> files/finances.xls
116252
+ currentMatches[index].route.path?.endsWith("*") && currentMatches[index].params["*"] !== match.params["*"]);
116253
+ };
116254
+ if (mode === "assets") {
116255
+ return nextMatches.filter((match, index)=>isNew(match, index) || matchPathChanged(match, index));
116256
+ }
116257
+ if (mode === "data") {
116258
+ return nextMatches.filter((match, index)=>{
116259
+ let manifestRoute = manifest.routes[match.route.id];
116260
+ if (!manifestRoute || !manifestRoute.hasLoader) {
116261
+ return false;
116262
+ }
116263
+ if (isNew(match, index) || matchPathChanged(match, index)) {
116264
+ return true;
116265
+ }
116266
+ if (match.route.shouldRevalidate) {
116267
+ let routeChoice = match.route.shouldRevalidate({
116268
+ currentUrl: new URL(location.pathname + location.search + location.hash, window.origin),
116269
+ currentParams: currentMatches[0]?.params || {},
116270
+ nextUrl: new URL(page, window.origin),
116271
+ nextParams: match.params,
116272
+ defaultShouldRevalidate: true
116273
+ });
116274
+ if (typeof routeChoice === "boolean") {
116275
+ return routeChoice;
116276
+ }
116277
+ }
116278
+ return true;
116279
+ });
116280
+ }
116281
+ return [];
116282
+ }
116283
+ function getModuleLinkHrefs(matches, manifest, { includeHydrateFallback } = {}) {
116284
+ return dedupeHrefs(matches.map((match)=>{
116285
+ let route = manifest.routes[match.route.id];
116286
+ if (!route) return [];
116287
+ let hrefs = [
116288
+ route.module
116289
+ ];
116290
+ if (route.clientActionModule) {
116291
+ hrefs = hrefs.concat(route.clientActionModule);
116292
+ }
116293
+ if (route.clientLoaderModule) {
116294
+ hrefs = hrefs.concat(route.clientLoaderModule);
116295
+ }
116296
+ if (includeHydrateFallback && route.hydrateFallbackModule) {
116297
+ hrefs = hrefs.concat(route.hydrateFallbackModule);
116298
+ }
116299
+ if (route.imports) {
116300
+ hrefs = hrefs.concat(route.imports);
116301
+ }
116302
+ return hrefs;
116303
+ }).flat(1));
116304
+ }
116305
+ function dedupeHrefs(hrefs) {
116306
+ return [
116307
+ ...new Set(hrefs)
116308
+ ];
116309
+ }
116310
+ function sortKeys(obj) {
116311
+ let sorted = {};
116312
+ let keys = Object.keys(obj).sort();
116313
+ for (let key of keys){
116314
+ sorted[key] = obj[key];
116315
+ }
116316
+ return sorted;
116317
+ }
116318
+ function dedupeLinkDescriptors(descriptors, preloads) {
116319
+ let set = /* @__PURE__ */ new Set();
116320
+ new Set(preloads);
116321
+ return descriptors.reduce((deduped, descriptor)=>{
116322
+ let key = JSON.stringify(sortKeys(descriptor));
116323
+ if (!set.has(key)) {
116324
+ set.add(key);
116325
+ deduped.push({
116326
+ key,
116327
+ link: descriptor
116328
+ });
116329
+ }
116330
+ return deduped;
116331
+ }, []);
116332
+ }
116333
+ // lib/dom/ssr/components.tsx
116334
+ function useDataRouterContext2() {
116335
+ let context = React__namespace.useContext(DataRouterContext);
116336
+ invariant2(context, "You must render this element inside a <DataRouterContext.Provider> element");
116337
+ return context;
116338
+ }
116339
+ function useDataRouterStateContext() {
116340
+ let context = React__namespace.useContext(DataRouterStateContext);
116341
+ invariant2(context, "You must render this element inside a <DataRouterStateContext.Provider> element");
116342
+ return context;
116343
+ }
116344
+ var FrameworkContext = React__namespace.createContext(void 0);
116345
+ FrameworkContext.displayName = "FrameworkContext";
116346
+ function useFrameworkContext() {
116347
+ let context = React__namespace.useContext(FrameworkContext);
116348
+ invariant2(context, "You must render this element inside a <HydratedRouter> element");
116349
+ return context;
116350
+ }
116351
+ function usePrefetchBehavior(prefetch, theirElementProps) {
116352
+ let frameworkContext = React__namespace.useContext(FrameworkContext);
116353
+ let [maybePrefetch, setMaybePrefetch] = React__namespace.useState(false);
116354
+ let [shouldPrefetch, setShouldPrefetch] = React__namespace.useState(false);
116355
+ let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
116356
+ let ref = React__namespace.useRef(null);
116357
+ React__namespace.useEffect(()=>{
116358
+ if (prefetch === "render") {
116359
+ setShouldPrefetch(true);
116360
+ }
116361
+ if (prefetch === "viewport") {
116362
+ let callback = (entries)=>{
116363
+ entries.forEach((entry)=>{
116364
+ setShouldPrefetch(entry.isIntersecting);
116365
+ });
116366
+ };
116367
+ let observer = new IntersectionObserver(callback, {
116368
+ threshold: 0.5
116369
+ });
116370
+ if (ref.current) observer.observe(ref.current);
116371
+ return ()=>{
116372
+ observer.disconnect();
116373
+ };
116374
+ }
116375
+ }, [
116376
+ prefetch
116377
+ ]);
116378
+ React__namespace.useEffect(()=>{
116379
+ if (maybePrefetch) {
116380
+ let id = setTimeout(()=>{
116381
+ setShouldPrefetch(true);
116382
+ }, 100);
116383
+ return ()=>{
116384
+ clearTimeout(id);
116385
+ };
116386
+ }
116387
+ }, [
116388
+ maybePrefetch
116389
+ ]);
116390
+ let setIntent = ()=>{
116391
+ setMaybePrefetch(true);
116392
+ };
116393
+ let cancelIntent = ()=>{
116394
+ setMaybePrefetch(false);
116395
+ setShouldPrefetch(false);
116396
+ };
116397
+ if (!frameworkContext) {
116398
+ return [
116399
+ false,
116400
+ ref,
116401
+ {}
116402
+ ];
116403
+ }
116404
+ if (prefetch !== "intent") {
116405
+ return [
116406
+ shouldPrefetch,
116407
+ ref,
116408
+ {}
116409
+ ];
116410
+ }
116411
+ return [
116412
+ shouldPrefetch,
116413
+ ref,
116414
+ {
116415
+ onFocus: composeEventHandlers(onFocus, setIntent),
116416
+ onBlur: composeEventHandlers(onBlur, cancelIntent),
116417
+ onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
116418
+ onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
116419
+ onTouchStart: composeEventHandlers(onTouchStart, setIntent)
116420
+ }
116421
+ ];
116422
+ }
116423
+ function composeEventHandlers(theirHandler, ourHandler) {
116424
+ return (event)=>{
116425
+ theirHandler && theirHandler(event);
116426
+ if (!event.defaultPrevented) {
116427
+ ourHandler(event);
116428
+ }
116429
+ };
116430
+ }
116431
+ function PrefetchPageLinks({ page, ...linkProps }) {
116432
+ let { router } = useDataRouterContext2();
116433
+ let matches = React__namespace.useMemo(()=>matchRoutes(router.routes, page, router.basename), [
116434
+ router.routes,
116435
+ page,
116436
+ router.basename
116437
+ ]);
116438
+ if (!matches) {
116439
+ return null;
116440
+ }
116441
+ return /* @__PURE__ */ React__namespace.createElement(PrefetchPageLinksImpl, {
116442
+ page,
116443
+ matches,
116444
+ ...linkProps
116445
+ });
116446
+ }
116447
+ function useKeyedPrefetchLinks(matches) {
116448
+ let { manifest, routeModules } = useFrameworkContext();
116449
+ let [keyedPrefetchLinks, setKeyedPrefetchLinks] = React__namespace.useState([]);
116450
+ React__namespace.useEffect(()=>{
116451
+ let interrupted = false;
116452
+ void getKeyedPrefetchLinks(matches, manifest, routeModules).then((links)=>{
116453
+ if (!interrupted) {
116454
+ setKeyedPrefetchLinks(links);
116455
+ }
116456
+ });
116457
+ return ()=>{
116458
+ interrupted = true;
116459
+ };
116460
+ }, [
116461
+ matches,
116462
+ manifest,
116463
+ routeModules
116464
+ ]);
116465
+ return keyedPrefetchLinks;
116466
+ }
116467
+ function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
116468
+ let location = useLocation();
116469
+ let { future, manifest, routeModules } = useFrameworkContext();
116470
+ let { basename } = useDataRouterContext2();
116471
+ let { loaderData, matches } = useDataRouterStateContext();
116472
+ let newMatchesForData = React__namespace.useMemo(()=>getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [
116473
+ page,
116474
+ nextMatches,
116475
+ matches,
116476
+ manifest,
116477
+ location
116478
+ ]);
116479
+ let newMatchesForAssets = React__namespace.useMemo(()=>getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [
116480
+ page,
116481
+ nextMatches,
116482
+ matches,
116483
+ manifest,
116484
+ location
116485
+ ]);
116486
+ let dataHrefs = React__namespace.useMemo(()=>{
116487
+ if (page === location.pathname + location.search + location.hash) {
116488
+ return [];
116489
+ }
116490
+ let routesParams = /* @__PURE__ */ new Set();
116491
+ let foundOptOutRoute = false;
116492
+ nextMatches.forEach((m)=>{
116493
+ let manifestRoute = manifest.routes[m.route.id];
116494
+ if (!manifestRoute || !manifestRoute.hasLoader) {
116495
+ return;
116496
+ }
116497
+ if (!newMatchesForData.some((m2)=>m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) {
116498
+ foundOptOutRoute = true;
116499
+ } else if (manifestRoute.hasClientLoader) {
116500
+ foundOptOutRoute = true;
116501
+ } else {
116502
+ routesParams.add(m.route.id);
116503
+ }
116504
+ });
116505
+ if (routesParams.size === 0) {
116506
+ return [];
116507
+ }
116508
+ let url = singleFetchUrl(page, basename, future.unstable_trailingSlashAwareDataRequests, "data");
116509
+ if (foundOptOutRoute && routesParams.size > 0) {
116510
+ url.searchParams.set("_routes", nextMatches.filter((m)=>routesParams.has(m.route.id)).map((m)=>m.route.id).join(","));
116511
+ }
116512
+ return [
116513
+ url.pathname + url.search
116514
+ ];
116515
+ }, [
116516
+ basename,
116517
+ future.unstable_trailingSlashAwareDataRequests,
116518
+ loaderData,
116519
+ location,
116520
+ manifest,
116521
+ newMatchesForData,
116522
+ nextMatches,
116523
+ page,
116524
+ routeModules
116525
+ ]);
116526
+ let moduleHrefs = React__namespace.useMemo(()=>getModuleLinkHrefs(newMatchesForAssets, manifest), [
116527
+ newMatchesForAssets,
116528
+ manifest
116529
+ ]);
116530
+ let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
116531
+ return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, dataHrefs.map((href)=>/* @__PURE__ */ React__namespace.createElement("link", {
116532
+ key: href,
116533
+ rel: "prefetch",
116534
+ as: "fetch",
116535
+ href,
116536
+ ...linkProps
116537
+ })), moduleHrefs.map((href)=>/* @__PURE__ */ React__namespace.createElement("link", {
116538
+ key: href,
116539
+ rel: "modulepreload",
116540
+ href,
116541
+ ...linkProps
116542
+ })), keyedPrefetchLinks.map(({ key, link })=>// these don't spread `linkProps` because they are full link descriptors
116543
+ // already with their own props
116544
+ /* @__PURE__ */ React__namespace.createElement("link", {
116545
+ key,
116546
+ nonce: linkProps.nonce,
116547
+ ...link,
116548
+ crossOrigin: link.crossOrigin ?? linkProps.crossOrigin
116549
+ })));
116550
+ }
116551
+ function mergeRefs(...refs) {
116552
+ return (value)=>{
116553
+ refs.forEach((ref)=>{
116554
+ if (typeof ref === "function") {
116555
+ ref(value);
116556
+ } else if (ref != null) {
116557
+ ref.current = value;
116558
+ }
116559
+ });
116560
+ };
116561
+ }
116562
+ var isBrowser2 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
116563
+ try {
116564
+ if (isBrowser2) {
116565
+ window.__reactRouterVersion = "7.13.1";
116566
+ }
116567
+ } catch (e) {}
116568
+ var ABSOLUTE_URL_REGEX2 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
116569
+ var Link = React__namespace.forwardRef(function LinkWithRef({ onClick, discover = "render", prefetch = "none", relative, reloadDocument, replace: replace2, unstable_mask, state, target, to, preventScrollReset, viewTransition, unstable_defaultShouldRevalidate, ...rest }, forwardedRef) {
116570
+ let { basename, navigator, unstable_useTransitions } = React__namespace.useContext(NavigationContext);
116571
+ let isAbsolute = typeof to === "string" && ABSOLUTE_URL_REGEX2.test(to);
116572
+ let parsed = parseToInfo(to, basename);
116573
+ to = parsed.to;
116574
+ let href = useHref(to, {
116575
+ relative
116576
+ });
116577
+ let location = useLocation();
116578
+ let maskedHref = null;
116579
+ if (unstable_mask) {
116580
+ let resolved = resolveTo(unstable_mask, [], location.unstable_mask ? location.unstable_mask.pathname : "/", true);
116581
+ if (basename !== "/") {
116582
+ resolved.pathname = resolved.pathname === "/" ? basename : joinPaths([
116583
+ basename,
116584
+ resolved.pathname
116585
+ ]);
116586
+ }
116587
+ maskedHref = navigator.createHref(resolved);
116588
+ }
116589
+ let [shouldPrefetch, prefetchRef, prefetchHandlers] = usePrefetchBehavior(prefetch, rest);
116590
+ let internalOnClick = useLinkClickHandler(to, {
116591
+ replace: replace2,
116592
+ unstable_mask,
116593
+ state,
116594
+ target,
116595
+ preventScrollReset,
116596
+ relative,
116597
+ viewTransition,
116598
+ unstable_defaultShouldRevalidate,
116599
+ unstable_useTransitions
116600
+ });
116601
+ function handleClick(event) {
116602
+ if (onClick) onClick(event);
116603
+ if (!event.defaultPrevented) {
116604
+ internalOnClick(event);
116605
+ }
116606
+ }
116607
+ let isSpaLink = !(parsed.isExternal || reloadDocument);
116608
+ let link = // eslint-disable-next-line jsx-a11y/anchor-has-content
116609
+ /* @__PURE__ */ React__namespace.createElement("a", {
116610
+ ...rest,
116611
+ ...prefetchHandlers,
116612
+ href: (isSpaLink ? maskedHref : void 0) || parsed.absoluteURL || href,
116613
+ onClick: isSpaLink ? handleClick : onClick,
116614
+ ref: mergeRefs(forwardedRef, prefetchRef),
116615
+ target,
116616
+ "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
116617
+ });
116618
+ return shouldPrefetch && !isAbsolute ? /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, link, /* @__PURE__ */ React__namespace.createElement(PrefetchPageLinks, {
116619
+ page: href
116620
+ })) : link;
116621
+ });
116622
+ Link.displayName = "Link";
116623
+ var NavLink = React__namespace.forwardRef(function NavLinkWithRef({ "aria-current": ariaCurrentProp = "page", caseSensitive = false, className: classNameProp = "", end = false, style: styleProp, to, viewTransition, children, ...rest }, ref) {
116624
+ let path = useResolvedPath(to, {
116625
+ relative: rest.relative
116626
+ });
116627
+ let location = useLocation();
116628
+ let routerState = React__namespace.useContext(DataRouterStateContext);
116629
+ let { navigator, basename } = React__namespace.useContext(NavigationContext);
116630
+ let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
116631
+ // eslint-disable-next-line react-hooks/rules-of-hooks
116632
+ useViewTransitionState(path) && viewTransition === true;
116633
+ let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
116634
+ let locationPathname = location.pathname;
116635
+ let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
116636
+ if (!caseSensitive) {
116637
+ locationPathname = locationPathname.toLowerCase();
116638
+ nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
116639
+ toPathname = toPathname.toLowerCase();
116640
+ }
116641
+ if (nextLocationPathname && basename) {
116642
+ nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
116643
+ }
116644
+ const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
116645
+ let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
116646
+ let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
116647
+ let renderProps = {
116648
+ isActive,
116649
+ isPending,
116650
+ isTransitioning
116651
+ };
116652
+ let ariaCurrent = isActive ? ariaCurrentProp : void 0;
116653
+ let className;
116654
+ if (typeof classNameProp === "function") {
116655
+ className = classNameProp(renderProps);
116656
+ } else {
116657
+ className = [
116658
+ classNameProp,
116659
+ isActive ? "active" : null,
116660
+ isPending ? "pending" : null,
116661
+ isTransitioning ? "transitioning" : null
116662
+ ].filter(Boolean).join(" ");
116663
+ }
116664
+ let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
116665
+ return /* @__PURE__ */ React__namespace.createElement(Link, {
116666
+ ...rest,
116667
+ "aria-current": ariaCurrent,
116668
+ className,
116669
+ ref,
116670
+ style,
116671
+ to,
116672
+ viewTransition
116673
+ }, typeof children === "function" ? children(renderProps) : children);
116674
+ });
116675
+ NavLink.displayName = "NavLink";
116676
+ var Form = React__namespace.forwardRef(({ discover = "render", fetcherKey, navigate, reloadDocument, replace: replace2, state, method = defaultMethod, action, onSubmit, relative, preventScrollReset, viewTransition, unstable_defaultShouldRevalidate, ...props }, forwardedRef)=>{
116677
+ let { unstable_useTransitions } = React__namespace.useContext(NavigationContext);
116678
+ let submit = useSubmit();
116679
+ let formAction = useFormAction(action, {
116680
+ relative
116681
+ });
116682
+ let formMethod = method.toLowerCase() === "get" ? "get" : "post";
116683
+ let isAbsolute = typeof action === "string" && ABSOLUTE_URL_REGEX2.test(action);
116684
+ let submitHandler = (event)=>{
116685
+ onSubmit && onSubmit(event);
116686
+ if (event.defaultPrevented) return;
116687
+ event.preventDefault();
116688
+ let submitter = event.nativeEvent.submitter;
116689
+ let submitMethod = submitter?.getAttribute("formmethod") || method;
116690
+ let doSubmit = ()=>submit(submitter || event.currentTarget, {
116691
+ fetcherKey,
116692
+ method: submitMethod,
116693
+ navigate,
116694
+ replace: replace2,
116695
+ state,
116696
+ relative,
116697
+ preventScrollReset,
116698
+ viewTransition,
116699
+ unstable_defaultShouldRevalidate
116700
+ });
116701
+ if (unstable_useTransitions && navigate !== false) {
116702
+ React__namespace.startTransition(()=>doSubmit());
116703
+ } else {
116704
+ doSubmit();
116705
+ }
116706
+ };
116707
+ return /* @__PURE__ */ React__namespace.createElement("form", {
116708
+ ref: forwardedRef,
116709
+ method: formMethod,
116710
+ action: formAction,
116711
+ onSubmit: reloadDocument ? onSubmit : submitHandler,
116712
+ ...props,
116713
+ "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
116714
+ });
116715
+ });
116716
+ Form.displayName = "Form";
116717
+ function getDataRouterConsoleError2(hookName) {
116718
+ return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
116719
+ }
116720
+ function useDataRouterContext3(hookName) {
116721
+ let ctx = React__namespace.useContext(DataRouterContext);
116722
+ invariant(ctx, getDataRouterConsoleError2(hookName));
116723
+ return ctx;
116724
+ }
116725
+ function useLinkClickHandler(to, { target, replace: replaceProp, unstable_mask, state, preventScrollReset, relative, viewTransition, unstable_defaultShouldRevalidate, unstable_useTransitions } = {}) {
116726
+ let navigate = useNavigate();
116727
+ let location = useLocation();
116728
+ let path = useResolvedPath(to, {
116729
+ relative
116730
+ });
116731
+ return React__namespace.useCallback((event)=>{
116732
+ if (shouldProcessLinkClick(event, target)) {
116733
+ event.preventDefault();
116734
+ let replace2 = replaceProp !== void 0 ? replaceProp : createPath(location) === createPath(path);
116735
+ let doNavigate = ()=>navigate(to, {
116736
+ replace: replace2,
116737
+ unstable_mask,
116738
+ state,
116739
+ preventScrollReset,
116740
+ relative,
116741
+ viewTransition,
116742
+ unstable_defaultShouldRevalidate
116743
+ });
116744
+ if (unstable_useTransitions) {
116745
+ React__namespace.startTransition(()=>doNavigate());
116746
+ } else {
116747
+ doNavigate();
116748
+ }
116749
+ }
116750
+ }, [
116751
+ location,
116752
+ navigate,
116753
+ path,
116754
+ replaceProp,
116755
+ unstable_mask,
116756
+ state,
116757
+ target,
116758
+ to,
116759
+ preventScrollReset,
116760
+ relative,
116761
+ viewTransition,
116762
+ unstable_defaultShouldRevalidate,
116763
+ unstable_useTransitions
116764
+ ]);
116765
+ }
116766
+ function useSearchParams(defaultInit) {
116767
+ 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.`);
116768
+ let defaultSearchParamsRef = React__namespace.useRef(createSearchParams(defaultInit));
116769
+ let hasSetSearchParamsRef = React__namespace.useRef(false);
116770
+ let location = useLocation();
116771
+ let searchParams = React__namespace.useMemo(()=>// Only merge in the defaults if we haven't yet called setSearchParams.
116772
+ // Once we call that we want those to take precedence, otherwise you can't
116773
+ // remove a param with setSearchParams({}) if it has an initial value
116774
+ getSearchParamsForLocation(location.search, hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current), [
116775
+ location.search
116776
+ ]);
116777
+ let navigate = useNavigate();
116778
+ let setSearchParams = React__namespace.useCallback((nextInit, navigateOptions)=>{
116779
+ const newSearchParams = createSearchParams(typeof nextInit === "function" ? nextInit(new URLSearchParams(searchParams)) : nextInit);
116780
+ hasSetSearchParamsRef.current = true;
116781
+ navigate("?" + newSearchParams, navigateOptions);
116782
+ }, [
116783
+ navigate,
116784
+ searchParams
116785
+ ]);
116786
+ return [
116787
+ searchParams,
116788
+ setSearchParams
116789
+ ];
116790
+ }
116791
+ var fetcherId = 0;
116792
+ var getUniqueFetcherId = ()=>`__${String(++fetcherId)}__`;
116793
+ function useSubmit() {
116794
+ let { router } = useDataRouterContext3("useSubmit" /* UseSubmit */ );
116795
+ let { basename } = React__namespace.useContext(NavigationContext);
116796
+ let currentRouteId = useRouteId();
116797
+ let routerFetch = router.fetch;
116798
+ let routerNavigate = router.navigate;
116799
+ return React__namespace.useCallback(async (target, options = {})=>{
116800
+ let { action, method, encType, formData, body } = getFormSubmissionInfo(target, basename);
116801
+ if (options.navigate === false) {
116802
+ let key = options.fetcherKey || getUniqueFetcherId();
116803
+ await routerFetch(key, currentRouteId, options.action || action, {
116804
+ unstable_defaultShouldRevalidate: options.unstable_defaultShouldRevalidate,
116805
+ preventScrollReset: options.preventScrollReset,
116806
+ formData,
116807
+ body,
116808
+ formMethod: options.method || method,
116809
+ formEncType: options.encType || encType,
116810
+ flushSync: options.flushSync
116811
+ });
116812
+ } else {
116813
+ await routerNavigate(options.action || action, {
116814
+ unstable_defaultShouldRevalidate: options.unstable_defaultShouldRevalidate,
116815
+ preventScrollReset: options.preventScrollReset,
116816
+ formData,
116817
+ body,
116818
+ formMethod: options.method || method,
116819
+ formEncType: options.encType || encType,
116820
+ replace: options.replace,
116821
+ state: options.state,
116822
+ fromRouteId: currentRouteId,
116823
+ flushSync: options.flushSync,
116824
+ viewTransition: options.viewTransition
116825
+ });
116826
+ }
116827
+ }, [
116828
+ routerFetch,
116829
+ routerNavigate,
116830
+ basename,
116831
+ currentRouteId
116832
+ ]);
116833
+ }
116834
+ function useFormAction(action, { relative } = {}) {
116835
+ let { basename } = React__namespace.useContext(NavigationContext);
116836
+ let routeContext = React__namespace.useContext(RouteContext);
116837
+ invariant(routeContext, "useFormAction must be used inside a RouteContext");
116838
+ let [match] = routeContext.matches.slice(-1);
116839
+ let path = {
116840
+ ...useResolvedPath(action ? action : ".", {
116841
+ relative
116842
+ })
116843
+ };
116844
+ let location = useLocation();
116845
+ if (action == null) {
116846
+ path.search = location.search;
116847
+ let params = new URLSearchParams(path.search);
116848
+ let indexValues = params.getAll("index");
116849
+ let hasNakedIndexParam = indexValues.some((v)=>v === "");
116850
+ if (hasNakedIndexParam) {
116851
+ params.delete("index");
116852
+ indexValues.filter((v)=>v).forEach((v)=>params.append("index", v));
116853
+ let qs = params.toString();
116854
+ path.search = qs ? `?${qs}` : "";
116855
+ }
116856
+ }
116857
+ if ((!action || action === ".") && match.route.index) {
116858
+ path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
116859
+ }
116860
+ if (basename !== "/") {
116861
+ path.pathname = path.pathname === "/" ? basename : joinPaths([
116862
+ basename,
116863
+ path.pathname
116864
+ ]);
116865
+ }
116866
+ return createPath(path);
116867
+ }
116868
+ function useViewTransitionState(to, { relative } = {}) {
116869
+ let vtContext = React__namespace.useContext(ViewTransitionContext);
116870
+ invariant(vtContext != null, "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");
116871
+ let { basename } = useDataRouterContext3("useViewTransitionState" /* useViewTransitionState */ );
116872
+ let path = useResolvedPath(to, {
116873
+ relative
116874
+ });
116875
+ if (!vtContext.isTransitioning) {
116876
+ return false;
116877
+ }
116878
+ let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
116879
+ let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
116880
+ return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
116881
+ }
116882
+
116883
+ const EvaluationsMockContext = /*#__PURE__*/ React.createContext(undefined);
116884
+ const useEvaluationsMock = ()=>{
116885
+ return React.useContext(EvaluationsMockContext);
116886
+ };
116887
+
116888
+ const API_BASE = "/api";
116889
+ const useEvaluations = ()=>{
116890
+ const mockContext = useEvaluationsMock();
116891
+ const [evaluations, setEvaluations] = React.useState([]);
116892
+ const [loading, setLoading] = React.useState(false);
116893
+ const [error, setError] = React.useState(null);
116894
+ const fetchEvaluations = React.useCallback(async ()=>{
116895
+ setLoading(true);
116896
+ setError(null);
116897
+ try {
116898
+ // Check for mock data first
116899
+ if (mockContext?.mockEvaluations) {
116900
+ setEvaluations(mockContext.mockEvaluations);
116901
+ setLoading(false);
116902
+ return;
116903
+ }
116904
+ // Otherwise fetch from API (returns raw DTO)
116905
+ const response = await fetch(`${API_BASE}/evaluations`);
116906
+ if (!response.ok) {
116907
+ throw new Error(`HTTP error! status: ${response.status}`);
116908
+ }
116909
+ const data = await response.json();
116910
+ // Handle edge cases: null/undefined or not an array
116911
+ if (!data || !Array.isArray(data)) {
116912
+ setEvaluations([]);
116913
+ return;
116914
+ }
116915
+ setEvaluations(data);
116916
+ } catch (err) {
116917
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
116918
+ setError(errorMessage);
116919
+ setEvaluations([]);
116920
+ } finally{
116921
+ setLoading(false);
116922
+ }
116923
+ }, [
116924
+ mockContext
116925
+ ]);
116926
+ React.useEffect(()=>{
116927
+ fetchEvaluations();
116928
+ }, [
116929
+ fetchEvaluations
116930
+ ]);
116931
+ return {
116932
+ evaluations,
116933
+ loading,
116934
+ error,
116935
+ refetch: fetchEvaluations
116936
+ };
116937
+ };
116938
+
116939
+ const EvaluationsComparePage = ({ backHref = "#/evaluations" })=>{
116940
+ const { evaluations, loading, error } = useEvaluations();
116941
+ const [searchParams, setSearchParams] = useSearchParams();
116942
+ const normalizedEvaluations = React.useMemo(()=>evaluations.map((e)=>isEvaluationDto(e) ? transformEvaluation(e) : e), [
116943
+ evaluations
116944
+ ]);
116945
+ // Support compare=id1,id2 (primary) and legacy evaluationId1/evaluationId2, source/target
116946
+ const [evaluationId1, evaluationId2] = React.useMemo(()=>{
116947
+ const compareParam = searchParams.get("compare");
116948
+ if (compareParam) {
116949
+ const [id1, id2] = compareParam.split(",").map((s)=>s.trim()).filter(Boolean);
116950
+ return [
116951
+ id1 ?? null,
116952
+ id2 ?? null
116953
+ ];
116954
+ }
116955
+ const id1 = searchParams.get("evaluationId1") ?? searchParams.get("source");
116956
+ const id2 = searchParams.get("evaluationId2") ?? searchParams.get("target");
116957
+ return [
116958
+ id1,
116959
+ id2
116960
+ ];
116961
+ }, [
116962
+ searchParams
116963
+ ]);
116964
+ const updateCompareParam = React.useCallback((id1, id2)=>{
116965
+ const newParams = new URLSearchParams(searchParams);
116966
+ newParams.delete("evaluationId1");
116967
+ newParams.delete("evaluationId2");
116968
+ newParams.delete("source");
116969
+ newParams.delete("target");
116970
+ if (id1 && id2) {
116971
+ newParams.set("compare", `${id1},${id2}`);
116972
+ } else {
116973
+ newParams.delete("compare");
116974
+ }
116975
+ setSearchParams(newParams, {
116976
+ replace: true
116977
+ });
116978
+ }, [
116979
+ searchParams,
116980
+ setSearchParams
116981
+ ]);
116982
+ const handleEvaluationId1Change = (id)=>{
116983
+ updateCompareParam(id, evaluationId2);
116984
+ };
116985
+ const handleEvaluationId2Change = (id)=>{
116986
+ updateCompareParam(evaluationId1, id);
116987
+ };
116988
+ if (error) {
116989
+ return /*#__PURE__*/ React.createElement("div", {
116990
+ style: {
116991
+ padding: "24px",
116992
+ textAlign: "center"
116993
+ }
116994
+ }, /*#__PURE__*/ React.createElement("p", {
116995
+ style: {
116996
+ color: "red"
116997
+ }
116998
+ }, "Error loading evaluations: ", error));
116999
+ }
117000
+ return /*#__PURE__*/ React.createElement("div", {
117001
+ style: {
117002
+ padding: "24px"
117003
+ }
117004
+ }, /*#__PURE__*/ React.createElement("h1", {
117005
+ style: {
117006
+ margin: "0 0 24px 0",
117007
+ fontSize: "24px",
117008
+ fontWeight: 600
117009
+ }
117010
+ }, "Compare Evaluations"), /*#__PURE__*/ React.createElement(EvaluationsCompareView, {
117011
+ evaluations: normalizedEvaluations,
117012
+ evaluationId1: evaluationId1,
117013
+ evaluationId2: evaluationId2,
117014
+ onEvaluationId1Change: handleEvaluationId1Change,
117015
+ onEvaluationId2Change: handleEvaluationId2Change,
117016
+ loading: loading,
117017
+ showEvaluationComparisonDropdowns: true,
117018
+ backHref: backHref
117019
+ }));
117020
+ };
117021
+
114410
117022
  function isLLMNode(n) {
114411
117023
  return isLLMResult(n);
114412
117024
  }
@@ -117569,6 +120181,15 @@ const GlobalStyles = ()=>{
117569
120181
  border-bottom-right-radius: 0.5rem !important;
117570
120182
  }
117571
120183
 
120184
+ /* Evaluations compare: highlight rows with differing values */
120185
+ .ant-table-tbody > tr.evaluations-compare-diff-row > td {
120186
+ background-color: #fef9c3 !important;
120187
+ }
120188
+
120189
+ html.dark .ant-table-tbody > tr.evaluations-compare-diff-row > td {
120190
+ background-color: #334155 !important;
120191
+ }
120192
+
117572
120193
  /* CSS Variables for backward compatibility */
117573
120194
  :root {
117574
120195
  --background: #ffffff;
@@ -117763,7 +120384,9 @@ exports.Badge = Badge;
117763
120384
  exports.Drawer = Drawer;
117764
120385
  exports.Edge = Edge;
117765
120386
  exports.EvaluationDetailsDrawer = EvaluationDetailsDrawer;
117766
- exports.EvaluationsCompare = EvaluationsCompare;
120387
+ exports.EvaluationsCompareDrawer = EvaluationsCompareDrawer;
120388
+ exports.EvaluationsComparePage = EvaluationsComparePage;
120389
+ exports.EvaluationsCompareView = EvaluationsCompareView;
117767
120390
  exports.EvaluationsTable = EvaluationsTable;
117768
120391
  exports.EvaluatorResult = EvaluatorResult;
117769
120392
  exports.GlobalStyles = GlobalStyles;
@@ -117785,13 +120408,14 @@ exports.createSafeTheme = createSafeTheme;
117785
120408
  exports.darkTheme = darkTheme;
117786
120409
  exports.defaultTheme = defaultTheme$1;
117787
120410
  exports.detectContentType = detectContentType;
120411
+ exports.evaluationsHaveSameMetrics = evaluationsHaveSameMetrics;
117788
120412
  exports.formatCurrency = formatCurrency;
117789
120413
  exports.formatDateFriendly = formatDateFriendly;
117790
120414
  exports.formatDateRelative = formatDateRelative;
117791
120415
  exports.formatDateShort = formatDateShort;
117792
120416
  exports.formatDuration = formatDuration;
117793
120417
  exports.formatLatency = formatLatency;
117794
- exports.formatMetricValue = formatMetricValue;
120418
+ exports.formatMetricValue = formatMetricValue$1;
117795
120419
  exports.formatNumberWithCommas = formatNumberWithCommas;
117796
120420
  exports.formatToolCalls = formatToolCalls;
117797
120421
  exports.getColor = getColor;