@0xsquid/ui 0.13.9 → 0.13.10

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
@@ -2831,6 +2831,12 @@ const themeTypesKeys = {
2831
2831
  'status-partial': {
2832
2832
  cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}status-partial`,
2833
2833
  },
2834
+ 'grey-100-005': {
2835
+ cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}grey-100-005`,
2836
+ },
2837
+ 'material-light-blend-grey-900': {
2838
+ cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}material-light-blend-grey-900`,
2839
+ },
2834
2840
  };
2835
2841
 
2836
2842
  function PlusIcon() {
@@ -2882,6 +2888,7 @@ const ANIMATION_DURATIONS = {
2882
2888
  CHANGE_SWAP_STEP: 300,
2883
2889
  SHOW_MODAL: 400,
2884
2890
  HIDE_MODAL: 400,
2891
+ BOOST_BUTTON: 500,
2885
2892
  };
2886
2893
  const ANIMATION_TIMINGS = {
2887
2894
  EXPAND_ROUTE: 'linear', //'cubic-bezier(.32, .72, 0, 1)',
@@ -3107,7 +3114,7 @@ const borderRadiusClassMap = {
3107
3114
  };
3108
3115
  function Menu(_a) {
3109
3116
  var { children, containerClassName, contentClassName, title, displayControls, rounded = 'lg', menuRef } = _a, props = __rest(_a, ["children", "containerClassName", "contentClassName", "title", "displayControls", "rounded", "menuRef"]);
3110
- return (jsxRuntime.jsx("div", Object.assign({}, props, { className: cn('tw-max-w-[320px]', containerClassName), ref: menuRef, children: jsxRuntime.jsxs("div", { className: cn('tw-relative tw-inline-flex tw-max-w-full tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-rounded-squid-m tw-bg-material-dark-thick tw-p-squid-s tw-text-center tw-text-material-light-thick tw-backdrop-blur/20 tw-backdrop-saturate-150 group-data-[squid-theme-type=dark]:tw-shadow-elevation-dark-2 group-data-[squid-theme-type=light]:tw-shadow-elevation-light-2', borderRadiusClassMap[rounded], contentClassName), children: [title ? (jsxRuntime.jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-self-stretch tw-py-squid-xxs tw-text-grey-100", children: jsxRuntime.jsx(BodyText, { size: "small", className: "tw-self-stretch !tw-leading-[10px]", children: title }) })) : null, typeof children === 'string' ? (jsxRuntime.jsx(CaptionText, { className: "tw-z-20 tw-self-stretch", children: children })) : (jsxRuntime.jsx("div", { className: "tw-z-20 tw-max-w-full tw-text-caption", children: children })), displayControls ? (jsxRuntime.jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-self-stretch tw-pt-squid-xs", children: jsxRuntime.jsx(Button, { size: "md", variant: "tertiary", label: "Learn more", className: "tw-self-stretch" }) })) : null, jsxRuntime.jsx("div", { className: cn('tw-absolute tw-z-10 tw-h-full tw-w-full tw-border tw-border-material-light-thin tw-bg-material-light-thin', borderRadiusClassMap[rounded]) })] }) })));
3117
+ return (jsxRuntime.jsx("div", Object.assign({}, props, { className: cn('tw-max-w-[320px]', containerClassName), ref: menuRef, children: jsxRuntime.jsxs("div", { className: cn('tw-relative tw-inline-flex tw-max-w-full tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-rounded-squid-m tw-bg-material-dark-thick tw-p-squid-xs tw-text-center tw-text-material-light-thick tw-backdrop-blur/20 tw-backdrop-saturate-150 group-data-[squid-theme-type=dark]:tw-shadow-elevation-dark-2 group-data-[squid-theme-type=light]:tw-shadow-elevation-light-2', borderRadiusClassMap[rounded], contentClassName), children: [title ? (jsxRuntime.jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-self-stretch tw-py-squid-xxs tw-text-grey-100", children: jsxRuntime.jsx(BodyText, { size: "small", className: "tw-self-stretch !tw-leading-[10px]", children: title }) })) : null, typeof children === 'string' ? (jsxRuntime.jsx(CaptionText, { className: "tw-z-20 tw-self-stretch !tw-leading-[10px]", children: children })) : (jsxRuntime.jsx("div", { className: "tw-z-20 tw-max-w-full tw-text-caption", children: children })), displayControls ? (jsxRuntime.jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-self-stretch tw-pt-squid-xs", children: jsxRuntime.jsx(Button, { size: "md", variant: "tertiary", label: "Learn more", className: "tw-self-stretch" }) })) : null, jsxRuntime.jsx("div", { className: cn('tw-absolute tw-z-10 tw-h-full tw-w-full tw-border tw-border-material-light-thin tw-bg-material-light-thin', borderRadiusClassMap[rounded]) })] }) })));
3111
3118
  }
3112
3119
 
3113
3120
  const tooltipWidthClassMap = {
@@ -3133,28 +3140,13 @@ function Tooltip({ children, tooltipContent, tooltipWidth = 'container', thresho
3133
3140
  'tw-animate-hide peer-hover:tw-animate-display-delayed hover:tw-animate-display-delayed', tooltipWidthClassMap[tooltipWidth], tooltipThresholdClassMap[threshold], tooltipClassName), children: tooltipContent })) : null] }));
3134
3141
  }
3135
3142
 
3136
- const animationDuration = '500ms';
3137
- function BoostButton({ boostMode, onToggleBoostMode, canToggleBoostMode = true, boostDisabledMessage = 'Boost disabled', tooltipDisplayDelayMs = 0, }) {
3138
- const boostIndicatorRef = React.useRef(null);
3139
- function handleToggleBoostMode() {
3140
- if (!boostIndicatorRef.current || !canToggleBoostMode)
3141
- return;
3142
- // we don't want to trigger the animation when the component is mounted
3143
- // so we set the animation duration only when user clicks the button
3144
- boostIndicatorRef.current.style.setProperty(CSS_VARS.MOVE_WITH_SPRING_BOUNCE_DURATION, animationDuration);
3145
- if (boostIndicatorRef.current.dataset.boostMode === 'normal') {
3146
- boostIndicatorRef.current.dataset.boostMode = 'boost';
3147
- onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'boost' });
3148
- }
3149
- else {
3150
- boostIndicatorRef.current.dataset.boostMode = 'normal';
3151
- onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'normal' });
3152
- }
3153
- }
3154
- return (jsxRuntime.jsx(Tooltip, { tooltipWidth: "max", displayDelayMs: tooltipDisplayDelayMs, tooltipContent: canToggleBoostMode ? null : boostDisabledMessage, children: jsxRuntime.jsxs("button", { onClick: handleToggleBoostMode, disabled: !canToggleBoostMode, className: "tw-group tw-relative tw-flex tw-h-squid-xl tw-w-[140px] tw-flex-col tw-justify-between tw-overflow-hidden tw-bg-grey-900 tw-pb-squid-xxs tw-text-grey-300", children: [jsxRuntime.jsx("span", { className: "tw-via-grey-900/70 tw-absolute tw-left-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-r tw-from-grey-900 tw-to-transparent" }), jsxRuntime.jsx("span", { className: "tw-via-grey-900/70 tw-absolute tw-right-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-l tw-from-grey-900 tw-to-transparent" }), jsxRuntime.jsxs("div", { ref: boostIndicatorRef, "data-boost-mode": boostMode, className: "tw-group tw-peer tw-flex tw-h-full tw-w-full tw-items-center tw-justify-between tw-transition-transform group-disabled:tw-grayscale data-[boost-mode=boost]:tw-animate-move-to-left-with-spring-bounce data-[boost-mode=normal]:tw-animate-move-to-right-with-spring-bounce", children: [jsxRuntime.jsx("div", { className: "tw-w-1/2 tw-text-center group-disabled:tw-grayscale", children: jsxRuntime.jsx(BodyText, { size: "small", className: "tw-text-grey-300", children: "Normal" }) }), jsxRuntime.jsxs("div", { className: "tw-w-1/2 tw-text-center group-disabled:tw-grayscale", children: [jsxRuntime.jsx(BodyText, { size: "small", className: "tw-text-status-positive", children: "Boost" }), ' '] }), jsxRuntime.jsx("div", { className: "tw-absolute tw-bottom-0 tw-h-1.5 tw-w-[1.5px] tw-rounded-sm tw-bg-grey-500 tw-text-grey-500 group-data-[boost-mode=boost]:tw-left-[calc(50%-2px)] group-data-[boost-mode=normal]:tw-left-[calc(50%-6px)]", style: {
3143
+ function BoostButton({ boostMode, canToggleBoostMode = true, boostDisabledMessage = 'Boost disabled', tooltipDisplayDelayMs = 0, boostIndicatorRef, }) {
3144
+ return (jsxRuntime.jsx(Tooltip, { tooltipWidth: "max", displayDelayMs: tooltipDisplayDelayMs, tooltipContent: canToggleBoostMode ? null : boostDisabledMessage, children: jsxRuntime.jsxs("div", { className: "tw-relative tw-flex tw-h-squid-xl tw-w-[140px] tw-flex-col tw-justify-between tw-overflow-hidden tw-rounded-squid-m tw-pb-squid-xxs tw-text-grey-300 focus:tw-outline-none", children: [jsxRuntime.jsx("span", { className: cn('tw-absolute tw-left-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-r tw-from-grey-900 tw-to-transparent', canToggleBoostMode &&
3145
+ 'group-hover/boost-toggle:tw-from-material-light-blend-grey-900') }), jsxRuntime.jsx("span", { className: cn('tw-absolute tw-right-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-l tw-from-grey-900 tw-to-transparent', canToggleBoostMode &&
3146
+ 'group-hover/boost-toggle:tw-from-material-light-blend-grey-900') }), jsxRuntime.jsxs("div", { ref: boostIndicatorRef, "data-boost-mode": boostMode, className: "tw-group tw-peer tw-flex tw-h-full tw-w-full tw-items-center tw-justify-between tw-transition-transform group-disabled/boost-toggle:tw-grayscale data-[boost-mode=boost]:tw-animate-move-to-left-with-spring-bounce data-[boost-mode=normal]:tw-animate-move-to-right-with-spring-bounce", children: [jsxRuntime.jsx("div", { className: "tw-w-1/2 tw-text-center group-disabled/boost-toggle:tw-grayscale", children: jsxRuntime.jsx(BodyText, { size: "small", className: "tw-text-grey-300", children: "Normal" }) }), jsxRuntime.jsxs("div", { className: "tw-w-1/2 tw-text-center group-disabled/boost-toggle:tw-grayscale", children: [jsxRuntime.jsx(BodyText, { size: "small", className: "tw-text-status-positive", children: "Boost" }), ' '] }), jsxRuntime.jsx("div", { className: "tw-absolute tw-bottom-0 tw-h-1.5 tw-w-[1.5px] tw-rounded-sm tw-bg-grey-500 tw-text-grey-500 group-data-[boost-mode=boost]:tw-left-[calc(50%-2px)] group-data-[boost-mode=normal]:tw-left-[calc(50%-6px)]", style: {
3155
3147
  boxShadow: generateMarkerLines(40),
3156
- } })] }), jsxRuntime.jsx("div", { className: cn('tw-absolute tw-bottom-0.5 tw-left-[calc(50%-1.5px)] tw-z-20 tw-h-[10px] tw-w-[3px] tw-rounded-sm tw-transition-colors group-disabled:tw-grayscale peer-data-[boost-mode=boost]:tw-bg-status-positive peer-data-[boost-mode=normal]:tw-bg-current'), style: {
3157
- transitionDuration: animationDuration,
3148
+ } })] }), jsxRuntime.jsx("div", { className: cn('tw-absolute tw-bottom-0.5 tw-left-[calc(50%-1.5px)] tw-z-20 tw-h-[10px] tw-w-[3px] tw-rounded-sm tw-transition-colors group-disabled/boost-toggle:tw-grayscale peer-data-[boost-mode=boost]:tw-bg-status-positive peer-data-[boost-mode=normal]:tw-bg-current'), style: {
3149
+ transitionDuration: `${ANIMATION_DURATIONS.BOOST_BUTTON}ms`,
3158
3150
  } })] }) }));
3159
3151
  }
3160
3152
  function generateMarkerLines(count) {
@@ -3188,9 +3180,25 @@ function SettingsButton({ label, isSelected = false, onClick, }) {
3188
3180
  }
3189
3181
 
3190
3182
  function Boost({ boostMode, onToggleBoostMode, estimatedTime, boostDisabledMessage, canToggleBoostMode = true, boostTooltipDisplayDelayMs = 0, }) {
3191
- return (jsxRuntime.jsxs("div", { className: "tw-flex tw-h-squid-xl tw-items-center tw-gap-x-squid-xxs tw-bg-grey-900 tw-pr-squid-xxs", children: [jsxRuntime.jsx(BoostButton, { boostMode: boostMode, boostDisabledMessage: boostDisabledMessage, canToggleBoostMode: canToggleBoostMode, onToggleBoostMode: onToggleBoostMode, tooltipDisplayDelayMs: boostTooltipDisplayDelayMs }), jsxRuntime.jsx(Chip, { label: estimatedTime, className: cn('tw-text-grey-900 tw-transition-colors', boostMode === 'normal' || !canToggleBoostMode
3192
- ? 'tw-bg-grey-300'
3193
- : 'tw-bg-status-positive') })] }));
3183
+ const boostIndicatorRef = React.useRef(null);
3184
+ function handleToggleBoostMode() {
3185
+ if (!boostIndicatorRef.current || !canToggleBoostMode)
3186
+ return;
3187
+ // we don't want to trigger the animation when the component is mounted
3188
+ // so we set the animation duration only when user clicks the button
3189
+ boostIndicatorRef.current.style.setProperty(CSS_VARS.MOVE_WITH_SPRING_BOUNCE_DURATION, `${ANIMATION_DURATIONS.BOOST_BUTTON}ms`);
3190
+ if (boostIndicatorRef.current.dataset.boostMode === 'normal') {
3191
+ boostIndicatorRef.current.dataset.boostMode = 'boost';
3192
+ onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'boost' });
3193
+ }
3194
+ else {
3195
+ boostIndicatorRef.current.dataset.boostMode = 'normal';
3196
+ onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'normal' });
3197
+ }
3198
+ }
3199
+ return (jsxRuntime.jsx("div", { className: "tw-bg-grey-900", children: jsxRuntime.jsxs("button", { onClick: handleToggleBoostMode, disabled: !canToggleBoostMode, className: cn('tw-group/boost-toggle tw-flex tw-h-squid-xl tw-items-center tw-gap-x-squid-xxs tw-rounded-squid-m tw-bg-grey-900 tw-pr-squid-xs', canToggleBoostMode && 'hover:tw-bg-material-light-thin'), children: [jsxRuntime.jsx(BoostButton, { boostIndicatorRef: boostIndicatorRef, boostMode: boostMode, boostDisabledMessage: boostDisabledMessage, canToggleBoostMode: canToggleBoostMode, tooltipDisplayDelayMs: boostTooltipDisplayDelayMs }), jsxRuntime.jsx(Chip, { label: estimatedTime, className: cn('tw-text-grey-900 tw-transition-colors', boostMode === 'normal' || !canToggleBoostMode
3200
+ ? 'tw-bg-grey-300'
3201
+ : 'tw-bg-status-positive') })] }) }));
3194
3202
  }
3195
3203
 
3196
3204
  function EmojiSadIcon({ className }) {
@@ -3210,7 +3218,7 @@ const detailStateClassMap = {
3210
3218
  error: 'tw-opacity-33 tw-pointer-events-none',
3211
3219
  full: '',
3212
3220
  };
3213
- function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs = 0, }) {
3221
+ function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs = 0, isFlipButtonDisabled, flipButtonDisabledMessage, }) {
3214
3222
  const state = React.useMemo(() => {
3215
3223
  if (errorMessage)
3216
3224
  return 'error';
@@ -3221,7 +3229,8 @@ function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode,
3221
3229
  return 'full';
3222
3230
  }, [errorMessage, isLoading, isEmpty]);
3223
3231
  const detailClassName = cn('tw-w-[190px]', detailStateClassMap[state]);
3224
- return (jsxRuntime.jsx("aside", { className: cn('tw-flex tw-h-[50px] tw-w-[480px] tw-items-center tw-justify-around tw-border-t tw-border-t-material-light-thin tw-bg-grey-900 tw-py-squid-xxs tw-text-grey-500', state === 'error' ? 'tw-px-squid-l' : 'tw-px-squid-m'), children: state === 'error' && errorMessage ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ErrorMessage, { message: errorMessage }), helpButton ? (jsxRuntime.jsx(Button, { onClick: helpButton.onClick, size: "md", variant: "tertiary", label: helpButton.label })) : null] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: detailClassName, children: jsxRuntime.jsx(FeeButton, { feeInUsd: feeInUsd, onClick: onFeeButtonClick }) }), jsxRuntime.jsx("div", { className: "tw-flex tw-h-squid-xl tw-w-squid-xxl tw-items-center tw-justify-center", children: state === 'loading' ? (jsxRuntime.jsx(Loader, { size: "32" })) : (jsxRuntime.jsx(Button, { variant: "tertiary", size: "md", onClick: onInvertSwapButtonClick, className: "tw-group/arrow-button tw-border-transparent tw-bg-transparent", icon: jsxRuntime.jsx(ChevronLargeDownIcon, { className: "tw-transition-transform tw-duration-150 group-hover/arrow-button:tw-rotate-180" }) })) }), jsxRuntime.jsx("div", { className: detailClassName, children: jsxRuntime.jsx(Boost, { estimatedTime: estimatedTime !== null && estimatedTime !== void 0 ? estimatedTime : '0s', boostMode: boostMode, onToggleBoostMode: onToggleBoostMode, canToggleBoostMode: state === 'loading' ? false : canToggleBoostMode, boostDisabledMessage: boostDisabledMessage, boostTooltipDisplayDelayMs: boostTooltipDisplayDelayMs }) })] })) }));
3232
+ return (jsxRuntime.jsx("aside", { className: cn('tw-flex tw-h-[50px] tw-w-[480px] tw-items-center tw-justify-around tw-border-t tw-border-t-material-light-thin tw-bg-grey-900 tw-py-squid-xxs tw-text-grey-500', state === 'error' ? 'tw-px-squid-l' : 'tw-px-squid-m'), children: state === 'error' && errorMessage ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ErrorMessage, { message: errorMessage }), helpButton ? (jsxRuntime.jsx(Button, { onClick: helpButton.onClick, size: "md", variant: "tertiary", label: helpButton.label })) : null] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: detailClassName, children: jsxRuntime.jsx(FeeButton, { feeInUsd: feeInUsd, onClick: onFeeButtonClick }) }), jsxRuntime.jsx("div", { className: "tw-flex tw-h-squid-xl tw-w-squid-xxl tw-items-center tw-justify-center", children: state === 'loading' ? (jsxRuntime.jsx(Loader, { size: "32" })) : (jsxRuntime.jsx(Tooltip, { tooltipContent: isFlipButtonDisabled ? flipButtonDisabledMessage : undefined, tooltipWidth: "max", children: jsxRuntime.jsx("button", { disabled: isFlipButtonDisabled, onClick: onInvertSwapButtonClick, className: "tw-group/flip-button tw-flex tw-h-squid-xl tw-min-w-[60px] tw-items-center tw-justify-center tw-rounded-squid-m tw-bg-transparent tw-px-squid-xs tw-py-squid-xxs tw-text-grey-300 hover:tw-bg-material-light-thin disabled:tw-cursor-not-allowed", children: jsxRuntime.jsx(ChevronLargeDownIcon, { className: cn('tw-transition-transform tw-duration-150', !isFlipButtonDisabled &&
3233
+ 'group-hover/flip-button:tw-rotate-180') }) }) })) }), jsxRuntime.jsx("div", { className: detailClassName, children: jsxRuntime.jsx(Boost, { estimatedTime: estimatedTime !== null && estimatedTime !== void 0 ? estimatedTime : '0s', boostMode: boostMode, onToggleBoostMode: onToggleBoostMode, canToggleBoostMode: state === 'loading' ? false : canToggleBoostMode, boostDisabledMessage: boostDisabledMessage, boostTooltipDisplayDelayMs: boostTooltipDisplayDelayMs }) })] })) }));
3225
3234
  }
3226
3235
 
3227
3236
  function DropdownMenuItem({ label, imageUrl, icon, labelClassName, onClick, }) {
@@ -38875,6 +38884,7 @@ const themeKeysToReplace = [
38875
38884
  * @param style
38876
38885
  */
38877
38886
  const parseSquidTheme = (userTheme) => {
38887
+ var _a;
38878
38888
  if (!userTheme)
38879
38889
  return undefined;
38880
38890
  const squidTheme = Object.entries(userTheme).reduce((internalKeys, [userKey, userValue]) => {
@@ -38914,7 +38924,11 @@ const parseSquidTheme = (userTheme) => {
38914
38924
  // })
38915
38925
  // })
38916
38926
  parsed.push({
38917
- [`${themeTypesKeys['grey-100'].cssVariable}-005`]: getHexColorFromOpacityPercentage(squidTheme['grey-100'], 0.05),
38927
+ [themeTypesKeys['grey-100-005'].cssVariable]: getHexColorFromOpacityPercentage(squidTheme['grey-100'], 0.05),
38928
+ });
38929
+ // color representing the blend of material-light and grey-900
38930
+ parsed.push({
38931
+ [themeTypesKeys['material-light-blend-grey-900'].cssVariable]: (_a = blendColors(squidTheme['material-light-thin'], squidTheme['grey-900'])) !== null && _a !== void 0 ? _a : '',
38918
38932
  });
38919
38933
  return parsed.reduce((a, v) => {
38920
38934
  const key = Object.keys(v)[0];
@@ -38936,6 +38950,46 @@ function getHexColorFromOpacityPercentage(color, opacity) {
38936
38950
  .toString(16)
38937
38951
  .padStart(2, '0')).toUpperCase();
38938
38952
  }
38953
+ function hexToRgb(hex) {
38954
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
38955
+ let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i;
38956
+ hex = hex.replace(shorthandRegex, function (m, r, g, b, a) {
38957
+ return r + r + g + g + b + b + (a ? a + a : '');
38958
+ });
38959
+ let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex);
38960
+ return result
38961
+ ? {
38962
+ r: parseInt(result[1], 16),
38963
+ g: parseInt(result[2], 16),
38964
+ b: parseInt(result[3], 16),
38965
+ a: result[4] ? parseInt(result[4], 16) / 255 : 1,
38966
+ }
38967
+ : null;
38968
+ }
38969
+ function rgbToHex(r, g, b) {
38970
+ return ('#' +
38971
+ [r, g, b]
38972
+ .map((x) => {
38973
+ const hex = x.toString(16);
38974
+ return hex.length === 1 ? '0' + hex : hex;
38975
+ })
38976
+ .join(''));
38977
+ }
38978
+ // Example usage:
38979
+ // let foregroundColor = '#FBFBFD1A'
38980
+ // let bgColor = '#17191C'
38981
+ // let resultingColor = blendColors(foregroundColor, bgColor)
38982
+ // console.log(resultingColor) // Output: ~#2f3033
38983
+ function blendColors(foreground, background) {
38984
+ let fg = hexToRgb(foreground);
38985
+ let bg = hexToRgb(background);
38986
+ if (!fg || !bg)
38987
+ return null;
38988
+ let r = Math.round(fg.r * fg.a + bg.r * (1 - fg.a));
38989
+ let g = Math.round(fg.g * fg.a + bg.g * (1 - fg.a));
38990
+ let b = Math.round(fg.b * fg.a + bg.b * (1 - fg.a));
38991
+ return rgbToHex(r, g, b);
38992
+ }
38939
38993
 
38940
38994
  function SquidConfigProvider({ theme = lightTheme, children, themeType = 'light', }) {
38941
38995
  const parsedStyle = parseSquidTheme(theme);
@@ -1,12 +1,11 @@
1
+ /// <reference types="react" />
1
2
  import { BoostMode } from '../../types/components';
2
3
  interface BoostButtonProps {
3
4
  boostMode: BoostMode;
4
5
  canToggleBoostMode?: boolean;
5
- onToggleBoostMode?: ({ boostMode }: {
6
- boostMode: BoostMode;
7
- }) => void;
8
6
  boostDisabledMessage?: string;
9
7
  tooltipDisplayDelayMs?: number;
8
+ boostIndicatorRef: React.RefObject<HTMLDivElement>;
10
9
  }
11
- export declare function BoostButton({ boostMode, onToggleBoostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, }: BoostButtonProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function BoostButton({ boostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, boostIndicatorRef, }: BoostButtonProps): import("react/jsx-runtime").JSX.Element;
12
11
  export {};
@@ -7,6 +7,8 @@ interface DetailsToolbarProps {
7
7
  }) => void;
8
8
  onInvertSwapButtonClick?: () => void;
9
9
  onFeeButtonClick?: () => void;
10
+ isFlipButtonDisabled?: boolean;
11
+ flipButtonDisabledMessage?: string;
10
12
  feeInUsd?: string;
11
13
  estimatedTime?: string;
12
14
  canToggleBoostMode?: boolean;
@@ -19,5 +21,5 @@ interface DetailsToolbarProps {
19
21
  };
20
22
  boostTooltipDisplayDelayMs?: number;
21
23
  }
22
- export declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, }: DetailsToolbarProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, isFlipButtonDisabled, flipButtonDisabledMessage, }: DetailsToolbarProps): import("react/jsx-runtime").JSX.Element;
23
25
  export {};
@@ -21,6 +21,7 @@ export declare const ANIMATION_DURATIONS: {
21
21
  CHANGE_SWAP_STEP: number;
22
22
  SHOW_MODAL: number;
23
23
  HIDE_MODAL: number;
24
+ BOOST_BUTTON: number;
24
25
  };
25
26
  export declare const ANIMATION_TIMINGS: {
26
27
  EXPAND_ROUTE: string;
@@ -36,3 +36,4 @@ export declare function getContrastColor({ r, g, b, }: {
36
36
  * @returns {string} The hexadecimal color with opacity.
37
37
  */
38
38
  export declare function getHexColorFromOpacityPercentage(color: string, opacity: number): string;
39
+ export declare function blendColors(foreground: string, background: string): string | null;
@@ -3,7 +3,8 @@ import { Boost } from '../../components/layout/Boost';
3
3
  declare const meta: Meta<typeof Boost>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof meta>;
6
- export declare const Default: Story;
6
+ export declare const Normal: Story;
7
7
  export declare const Boosted: Story;
8
- export declare const Disabled: Story;
8
+ export declare const NormalDisabled: Story;
9
+ export declare const BoostedDisabled: Story;
9
10
  export declare const DisabledWithDelayedTooltip: Story;
@@ -10,3 +10,4 @@ export declare const Error: Story;
10
10
  export declare const ErrorHelpButton: Story;
11
11
  export declare const BoostDisabled: Story;
12
12
  export declare const BoostDisabledWithDelayedTooltip: Story;
13
+ export declare const FlipButtonDisabled: Story;
@@ -23,6 +23,8 @@ export interface InternalSquidTheme {
23
23
  'material-dark-thin': string;
24
24
  'material-dark-average': string;
25
25
  'material-dark-thick': string;
26
+ 'grey-100-005': string;
27
+ 'material-light-blend-grey-900': string;
26
28
  }
27
29
  export type SquidTheme = {
28
30
  'content-100': string;
package/dist/esm/index.js CHANGED
@@ -2811,6 +2811,12 @@ const themeTypesKeys = {
2811
2811
  'status-partial': {
2812
2812
  cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}status-partial`,
2813
2813
  },
2814
+ 'grey-100-005': {
2815
+ cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}grey-100-005`,
2816
+ },
2817
+ 'material-light-blend-grey-900': {
2818
+ cssVariable: `${SQUID_THEME_CSS_VARIABLE_PREFIX}material-light-blend-grey-900`,
2819
+ },
2814
2820
  };
2815
2821
 
2816
2822
  function PlusIcon() {
@@ -2862,6 +2868,7 @@ const ANIMATION_DURATIONS = {
2862
2868
  CHANGE_SWAP_STEP: 300,
2863
2869
  SHOW_MODAL: 400,
2864
2870
  HIDE_MODAL: 400,
2871
+ BOOST_BUTTON: 500,
2865
2872
  };
2866
2873
  const ANIMATION_TIMINGS = {
2867
2874
  EXPAND_ROUTE: 'linear', //'cubic-bezier(.32, .72, 0, 1)',
@@ -3087,7 +3094,7 @@ const borderRadiusClassMap = {
3087
3094
  };
3088
3095
  function Menu(_a) {
3089
3096
  var { children, containerClassName, contentClassName, title, displayControls, rounded = 'lg', menuRef } = _a, props = __rest(_a, ["children", "containerClassName", "contentClassName", "title", "displayControls", "rounded", "menuRef"]);
3090
- return (jsx("div", Object.assign({}, props, { className: cn('tw-max-w-[320px]', containerClassName), ref: menuRef, children: jsxs("div", { className: cn('tw-relative tw-inline-flex tw-max-w-full tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-rounded-squid-m tw-bg-material-dark-thick tw-p-squid-s tw-text-center tw-text-material-light-thick tw-backdrop-blur/20 tw-backdrop-saturate-150 group-data-[squid-theme-type=dark]:tw-shadow-elevation-dark-2 group-data-[squid-theme-type=light]:tw-shadow-elevation-light-2', borderRadiusClassMap[rounded], contentClassName), children: [title ? (jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-self-stretch tw-py-squid-xxs tw-text-grey-100", children: jsx(BodyText, { size: "small", className: "tw-self-stretch !tw-leading-[10px]", children: title }) })) : null, typeof children === 'string' ? (jsx(CaptionText, { className: "tw-z-20 tw-self-stretch", children: children })) : (jsx("div", { className: "tw-z-20 tw-max-w-full tw-text-caption", children: children })), displayControls ? (jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-self-stretch tw-pt-squid-xs", children: jsx(Button, { size: "md", variant: "tertiary", label: "Learn more", className: "tw-self-stretch" }) })) : null, jsx("div", { className: cn('tw-absolute tw-z-10 tw-h-full tw-w-full tw-border tw-border-material-light-thin tw-bg-material-light-thin', borderRadiusClassMap[rounded]) })] }) })));
3097
+ return (jsx("div", Object.assign({}, props, { className: cn('tw-max-w-[320px]', containerClassName), ref: menuRef, children: jsxs("div", { className: cn('tw-relative tw-inline-flex tw-max-w-full tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-rounded-squid-m tw-bg-material-dark-thick tw-p-squid-xs tw-text-center tw-text-material-light-thick tw-backdrop-blur/20 tw-backdrop-saturate-150 group-data-[squid-theme-type=dark]:tw-shadow-elevation-dark-2 group-data-[squid-theme-type=light]:tw-shadow-elevation-light-2', borderRadiusClassMap[rounded], contentClassName), children: [title ? (jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-self-stretch tw-py-squid-xxs tw-text-grey-100", children: jsx(BodyText, { size: "small", className: "tw-self-stretch !tw-leading-[10px]", children: title }) })) : null, typeof children === 'string' ? (jsx(CaptionText, { className: "tw-z-20 tw-self-stretch !tw-leading-[10px]", children: children })) : (jsx("div", { className: "tw-z-20 tw-max-w-full tw-text-caption", children: children })), displayControls ? (jsx("div", { className: "tw-z-20 tw-flex tw-flex-col tw-items-center tw-justify-center tw-gap-squid-xs tw-self-stretch tw-pt-squid-xs", children: jsx(Button, { size: "md", variant: "tertiary", label: "Learn more", className: "tw-self-stretch" }) })) : null, jsx("div", { className: cn('tw-absolute tw-z-10 tw-h-full tw-w-full tw-border tw-border-material-light-thin tw-bg-material-light-thin', borderRadiusClassMap[rounded]) })] }) })));
3091
3098
  }
3092
3099
 
3093
3100
  const tooltipWidthClassMap = {
@@ -3113,28 +3120,13 @@ function Tooltip({ children, tooltipContent, tooltipWidth = 'container', thresho
3113
3120
  'tw-animate-hide peer-hover:tw-animate-display-delayed hover:tw-animate-display-delayed', tooltipWidthClassMap[tooltipWidth], tooltipThresholdClassMap[threshold], tooltipClassName), children: tooltipContent })) : null] }));
3114
3121
  }
3115
3122
 
3116
- const animationDuration = '500ms';
3117
- function BoostButton({ boostMode, onToggleBoostMode, canToggleBoostMode = true, boostDisabledMessage = 'Boost disabled', tooltipDisplayDelayMs = 0, }) {
3118
- const boostIndicatorRef = useRef(null);
3119
- function handleToggleBoostMode() {
3120
- if (!boostIndicatorRef.current || !canToggleBoostMode)
3121
- return;
3122
- // we don't want to trigger the animation when the component is mounted
3123
- // so we set the animation duration only when user clicks the button
3124
- boostIndicatorRef.current.style.setProperty(CSS_VARS.MOVE_WITH_SPRING_BOUNCE_DURATION, animationDuration);
3125
- if (boostIndicatorRef.current.dataset.boostMode === 'normal') {
3126
- boostIndicatorRef.current.dataset.boostMode = 'boost';
3127
- onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'boost' });
3128
- }
3129
- else {
3130
- boostIndicatorRef.current.dataset.boostMode = 'normal';
3131
- onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'normal' });
3132
- }
3133
- }
3134
- return (jsx(Tooltip, { tooltipWidth: "max", displayDelayMs: tooltipDisplayDelayMs, tooltipContent: canToggleBoostMode ? null : boostDisabledMessage, children: jsxs("button", { onClick: handleToggleBoostMode, disabled: !canToggleBoostMode, className: "tw-group tw-relative tw-flex tw-h-squid-xl tw-w-[140px] tw-flex-col tw-justify-between tw-overflow-hidden tw-bg-grey-900 tw-pb-squid-xxs tw-text-grey-300", children: [jsx("span", { className: "tw-via-grey-900/70 tw-absolute tw-left-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-r tw-from-grey-900 tw-to-transparent" }), jsx("span", { className: "tw-via-grey-900/70 tw-absolute tw-right-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-l tw-from-grey-900 tw-to-transparent" }), jsxs("div", { ref: boostIndicatorRef, "data-boost-mode": boostMode, className: "tw-group tw-peer tw-flex tw-h-full tw-w-full tw-items-center tw-justify-between tw-transition-transform group-disabled:tw-grayscale data-[boost-mode=boost]:tw-animate-move-to-left-with-spring-bounce data-[boost-mode=normal]:tw-animate-move-to-right-with-spring-bounce", children: [jsx("div", { className: "tw-w-1/2 tw-text-center group-disabled:tw-grayscale", children: jsx(BodyText, { size: "small", className: "tw-text-grey-300", children: "Normal" }) }), jsxs("div", { className: "tw-w-1/2 tw-text-center group-disabled:tw-grayscale", children: [jsx(BodyText, { size: "small", className: "tw-text-status-positive", children: "Boost" }), ' '] }), jsx("div", { className: "tw-absolute tw-bottom-0 tw-h-1.5 tw-w-[1.5px] tw-rounded-sm tw-bg-grey-500 tw-text-grey-500 group-data-[boost-mode=boost]:tw-left-[calc(50%-2px)] group-data-[boost-mode=normal]:tw-left-[calc(50%-6px)]", style: {
3123
+ function BoostButton({ boostMode, canToggleBoostMode = true, boostDisabledMessage = 'Boost disabled', tooltipDisplayDelayMs = 0, boostIndicatorRef, }) {
3124
+ return (jsx(Tooltip, { tooltipWidth: "max", displayDelayMs: tooltipDisplayDelayMs, tooltipContent: canToggleBoostMode ? null : boostDisabledMessage, children: jsxs("div", { className: "tw-relative tw-flex tw-h-squid-xl tw-w-[140px] tw-flex-col tw-justify-between tw-overflow-hidden tw-rounded-squid-m tw-pb-squid-xxs tw-text-grey-300 focus:tw-outline-none", children: [jsx("span", { className: cn('tw-absolute tw-left-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-r tw-from-grey-900 tw-to-transparent', canToggleBoostMode &&
3125
+ 'group-hover/boost-toggle:tw-from-material-light-blend-grey-900') }), jsx("span", { className: cn('tw-absolute tw-right-0 tw-top-0 tw-z-10 tw-h-full tw-w-8 tw-bg-gradient-to-l tw-from-grey-900 tw-to-transparent', canToggleBoostMode &&
3126
+ 'group-hover/boost-toggle:tw-from-material-light-blend-grey-900') }), jsxs("div", { ref: boostIndicatorRef, "data-boost-mode": boostMode, className: "tw-group tw-peer tw-flex tw-h-full tw-w-full tw-items-center tw-justify-between tw-transition-transform group-disabled/boost-toggle:tw-grayscale data-[boost-mode=boost]:tw-animate-move-to-left-with-spring-bounce data-[boost-mode=normal]:tw-animate-move-to-right-with-spring-bounce", children: [jsx("div", { className: "tw-w-1/2 tw-text-center group-disabled/boost-toggle:tw-grayscale", children: jsx(BodyText, { size: "small", className: "tw-text-grey-300", children: "Normal" }) }), jsxs("div", { className: "tw-w-1/2 tw-text-center group-disabled/boost-toggle:tw-grayscale", children: [jsx(BodyText, { size: "small", className: "tw-text-status-positive", children: "Boost" }), ' '] }), jsx("div", { className: "tw-absolute tw-bottom-0 tw-h-1.5 tw-w-[1.5px] tw-rounded-sm tw-bg-grey-500 tw-text-grey-500 group-data-[boost-mode=boost]:tw-left-[calc(50%-2px)] group-data-[boost-mode=normal]:tw-left-[calc(50%-6px)]", style: {
3135
3127
  boxShadow: generateMarkerLines(40),
3136
- } })] }), jsx("div", { className: cn('tw-absolute tw-bottom-0.5 tw-left-[calc(50%-1.5px)] tw-z-20 tw-h-[10px] tw-w-[3px] tw-rounded-sm tw-transition-colors group-disabled:tw-grayscale peer-data-[boost-mode=boost]:tw-bg-status-positive peer-data-[boost-mode=normal]:tw-bg-current'), style: {
3137
- transitionDuration: animationDuration,
3128
+ } })] }), jsx("div", { className: cn('tw-absolute tw-bottom-0.5 tw-left-[calc(50%-1.5px)] tw-z-20 tw-h-[10px] tw-w-[3px] tw-rounded-sm tw-transition-colors group-disabled/boost-toggle:tw-grayscale peer-data-[boost-mode=boost]:tw-bg-status-positive peer-data-[boost-mode=normal]:tw-bg-current'), style: {
3129
+ transitionDuration: `${ANIMATION_DURATIONS.BOOST_BUTTON}ms`,
3138
3130
  } })] }) }));
3139
3131
  }
3140
3132
  function generateMarkerLines(count) {
@@ -3168,9 +3160,25 @@ function SettingsButton({ label, isSelected = false, onClick, }) {
3168
3160
  }
3169
3161
 
3170
3162
  function Boost({ boostMode, onToggleBoostMode, estimatedTime, boostDisabledMessage, canToggleBoostMode = true, boostTooltipDisplayDelayMs = 0, }) {
3171
- return (jsxs("div", { className: "tw-flex tw-h-squid-xl tw-items-center tw-gap-x-squid-xxs tw-bg-grey-900 tw-pr-squid-xxs", children: [jsx(BoostButton, { boostMode: boostMode, boostDisabledMessage: boostDisabledMessage, canToggleBoostMode: canToggleBoostMode, onToggleBoostMode: onToggleBoostMode, tooltipDisplayDelayMs: boostTooltipDisplayDelayMs }), jsx(Chip, { label: estimatedTime, className: cn('tw-text-grey-900 tw-transition-colors', boostMode === 'normal' || !canToggleBoostMode
3172
- ? 'tw-bg-grey-300'
3173
- : 'tw-bg-status-positive') })] }));
3163
+ const boostIndicatorRef = useRef(null);
3164
+ function handleToggleBoostMode() {
3165
+ if (!boostIndicatorRef.current || !canToggleBoostMode)
3166
+ return;
3167
+ // we don't want to trigger the animation when the component is mounted
3168
+ // so we set the animation duration only when user clicks the button
3169
+ boostIndicatorRef.current.style.setProperty(CSS_VARS.MOVE_WITH_SPRING_BOUNCE_DURATION, `${ANIMATION_DURATIONS.BOOST_BUTTON}ms`);
3170
+ if (boostIndicatorRef.current.dataset.boostMode === 'normal') {
3171
+ boostIndicatorRef.current.dataset.boostMode = 'boost';
3172
+ onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'boost' });
3173
+ }
3174
+ else {
3175
+ boostIndicatorRef.current.dataset.boostMode = 'normal';
3176
+ onToggleBoostMode === null || onToggleBoostMode === void 0 ? void 0 : onToggleBoostMode({ boostMode: 'normal' });
3177
+ }
3178
+ }
3179
+ return (jsx("div", { className: "tw-bg-grey-900", children: jsxs("button", { onClick: handleToggleBoostMode, disabled: !canToggleBoostMode, className: cn('tw-group/boost-toggle tw-flex tw-h-squid-xl tw-items-center tw-gap-x-squid-xxs tw-rounded-squid-m tw-bg-grey-900 tw-pr-squid-xs', canToggleBoostMode && 'hover:tw-bg-material-light-thin'), children: [jsx(BoostButton, { boostIndicatorRef: boostIndicatorRef, boostMode: boostMode, boostDisabledMessage: boostDisabledMessage, canToggleBoostMode: canToggleBoostMode, tooltipDisplayDelayMs: boostTooltipDisplayDelayMs }), jsx(Chip, { label: estimatedTime, className: cn('tw-text-grey-900 tw-transition-colors', boostMode === 'normal' || !canToggleBoostMode
3180
+ ? 'tw-bg-grey-300'
3181
+ : 'tw-bg-status-positive') })] }) }));
3174
3182
  }
3175
3183
 
3176
3184
  function EmojiSadIcon({ className }) {
@@ -3190,7 +3198,7 @@ const detailStateClassMap = {
3190
3198
  error: 'tw-opacity-33 tw-pointer-events-none',
3191
3199
  full: '',
3192
3200
  };
3193
- function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs = 0, }) {
3201
+ function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs = 0, isFlipButtonDisabled, flipButtonDisabledMessage, }) {
3194
3202
  const state = useMemo(() => {
3195
3203
  if (errorMessage)
3196
3204
  return 'error';
@@ -3201,7 +3209,8 @@ function DetailsToolbar({ errorMessage, boostMode = 'normal', onToggleBoostMode,
3201
3209
  return 'full';
3202
3210
  }, [errorMessage, isLoading, isEmpty]);
3203
3211
  const detailClassName = cn('tw-w-[190px]', detailStateClassMap[state]);
3204
- return (jsx("aside", { className: cn('tw-flex tw-h-[50px] tw-w-[480px] tw-items-center tw-justify-around tw-border-t tw-border-t-material-light-thin tw-bg-grey-900 tw-py-squid-xxs tw-text-grey-500', state === 'error' ? 'tw-px-squid-l' : 'tw-px-squid-m'), children: state === 'error' && errorMessage ? (jsxs(Fragment, { children: [jsx(ErrorMessage, { message: errorMessage }), helpButton ? (jsx(Button, { onClick: helpButton.onClick, size: "md", variant: "tertiary", label: helpButton.label })) : null] })) : (jsxs(Fragment, { children: [jsx("div", { className: detailClassName, children: jsx(FeeButton, { feeInUsd: feeInUsd, onClick: onFeeButtonClick }) }), jsx("div", { className: "tw-flex tw-h-squid-xl tw-w-squid-xxl tw-items-center tw-justify-center", children: state === 'loading' ? (jsx(Loader, { size: "32" })) : (jsx(Button, { variant: "tertiary", size: "md", onClick: onInvertSwapButtonClick, className: "tw-group/arrow-button tw-border-transparent tw-bg-transparent", icon: jsx(ChevronLargeDownIcon, { className: "tw-transition-transform tw-duration-150 group-hover/arrow-button:tw-rotate-180" }) })) }), jsx("div", { className: detailClassName, children: jsx(Boost, { estimatedTime: estimatedTime !== null && estimatedTime !== void 0 ? estimatedTime : '0s', boostMode: boostMode, onToggleBoostMode: onToggleBoostMode, canToggleBoostMode: state === 'loading' ? false : canToggleBoostMode, boostDisabledMessage: boostDisabledMessage, boostTooltipDisplayDelayMs: boostTooltipDisplayDelayMs }) })] })) }));
3212
+ return (jsx("aside", { className: cn('tw-flex tw-h-[50px] tw-w-[480px] tw-items-center tw-justify-around tw-border-t tw-border-t-material-light-thin tw-bg-grey-900 tw-py-squid-xxs tw-text-grey-500', state === 'error' ? 'tw-px-squid-l' : 'tw-px-squid-m'), children: state === 'error' && errorMessage ? (jsxs(Fragment, { children: [jsx(ErrorMessage, { message: errorMessage }), helpButton ? (jsx(Button, { onClick: helpButton.onClick, size: "md", variant: "tertiary", label: helpButton.label })) : null] })) : (jsxs(Fragment, { children: [jsx("div", { className: detailClassName, children: jsx(FeeButton, { feeInUsd: feeInUsd, onClick: onFeeButtonClick }) }), jsx("div", { className: "tw-flex tw-h-squid-xl tw-w-squid-xxl tw-items-center tw-justify-center", children: state === 'loading' ? (jsx(Loader, { size: "32" })) : (jsx(Tooltip, { tooltipContent: isFlipButtonDisabled ? flipButtonDisabledMessage : undefined, tooltipWidth: "max", children: jsx("button", { disabled: isFlipButtonDisabled, onClick: onInvertSwapButtonClick, className: "tw-group/flip-button tw-flex tw-h-squid-xl tw-min-w-[60px] tw-items-center tw-justify-center tw-rounded-squid-m tw-bg-transparent tw-px-squid-xs tw-py-squid-xxs tw-text-grey-300 hover:tw-bg-material-light-thin disabled:tw-cursor-not-allowed", children: jsx(ChevronLargeDownIcon, { className: cn('tw-transition-transform tw-duration-150', !isFlipButtonDisabled &&
3213
+ 'group-hover/flip-button:tw-rotate-180') }) }) })) }), jsx("div", { className: detailClassName, children: jsx(Boost, { estimatedTime: estimatedTime !== null && estimatedTime !== void 0 ? estimatedTime : '0s', boostMode: boostMode, onToggleBoostMode: onToggleBoostMode, canToggleBoostMode: state === 'loading' ? false : canToggleBoostMode, boostDisabledMessage: boostDisabledMessage, boostTooltipDisplayDelayMs: boostTooltipDisplayDelayMs }) })] })) }));
3205
3214
  }
3206
3215
 
3207
3216
  function DropdownMenuItem({ label, imageUrl, icon, labelClassName, onClick, }) {
@@ -38855,6 +38864,7 @@ const themeKeysToReplace = [
38855
38864
  * @param style
38856
38865
  */
38857
38866
  const parseSquidTheme = (userTheme) => {
38867
+ var _a;
38858
38868
  if (!userTheme)
38859
38869
  return undefined;
38860
38870
  const squidTheme = Object.entries(userTheme).reduce((internalKeys, [userKey, userValue]) => {
@@ -38894,7 +38904,11 @@ const parseSquidTheme = (userTheme) => {
38894
38904
  // })
38895
38905
  // })
38896
38906
  parsed.push({
38897
- [`${themeTypesKeys['grey-100'].cssVariable}-005`]: getHexColorFromOpacityPercentage(squidTheme['grey-100'], 0.05),
38907
+ [themeTypesKeys['grey-100-005'].cssVariable]: getHexColorFromOpacityPercentage(squidTheme['grey-100'], 0.05),
38908
+ });
38909
+ // color representing the blend of material-light and grey-900
38910
+ parsed.push({
38911
+ [themeTypesKeys['material-light-blend-grey-900'].cssVariable]: (_a = blendColors(squidTheme['material-light-thin'], squidTheme['grey-900'])) !== null && _a !== void 0 ? _a : '',
38898
38912
  });
38899
38913
  return parsed.reduce((a, v) => {
38900
38914
  const key = Object.keys(v)[0];
@@ -38916,6 +38930,46 @@ function getHexColorFromOpacityPercentage(color, opacity) {
38916
38930
  .toString(16)
38917
38931
  .padStart(2, '0')).toUpperCase();
38918
38932
  }
38933
+ function hexToRgb(hex) {
38934
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
38935
+ let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i;
38936
+ hex = hex.replace(shorthandRegex, function (m, r, g, b, a) {
38937
+ return r + r + g + g + b + b + (a ? a + a : '');
38938
+ });
38939
+ let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex);
38940
+ return result
38941
+ ? {
38942
+ r: parseInt(result[1], 16),
38943
+ g: parseInt(result[2], 16),
38944
+ b: parseInt(result[3], 16),
38945
+ a: result[4] ? parseInt(result[4], 16) / 255 : 1,
38946
+ }
38947
+ : null;
38948
+ }
38949
+ function rgbToHex(r, g, b) {
38950
+ return ('#' +
38951
+ [r, g, b]
38952
+ .map((x) => {
38953
+ const hex = x.toString(16);
38954
+ return hex.length === 1 ? '0' + hex : hex;
38955
+ })
38956
+ .join(''));
38957
+ }
38958
+ // Example usage:
38959
+ // let foregroundColor = '#FBFBFD1A'
38960
+ // let bgColor = '#17191C'
38961
+ // let resultingColor = blendColors(foregroundColor, bgColor)
38962
+ // console.log(resultingColor) // Output: ~#2f3033
38963
+ function blendColors(foreground, background) {
38964
+ let fg = hexToRgb(foreground);
38965
+ let bg = hexToRgb(background);
38966
+ if (!fg || !bg)
38967
+ return null;
38968
+ let r = Math.round(fg.r * fg.a + bg.r * (1 - fg.a));
38969
+ let g = Math.round(fg.g * fg.a + bg.g * (1 - fg.a));
38970
+ let b = Math.round(fg.b * fg.a + bg.b * (1 - fg.a));
38971
+ return rgbToHex(r, g, b);
38972
+ }
38919
38973
 
38920
38974
  function SquidConfigProvider({ theme = lightTheme, children, themeType = 'light', }) {
38921
38975
  const parsedStyle = parseSquidTheme(theme);
@@ -1,12 +1,11 @@
1
+ /// <reference types="react" />
1
2
  import { BoostMode } from '../../types/components';
2
3
  interface BoostButtonProps {
3
4
  boostMode: BoostMode;
4
5
  canToggleBoostMode?: boolean;
5
- onToggleBoostMode?: ({ boostMode }: {
6
- boostMode: BoostMode;
7
- }) => void;
8
6
  boostDisabledMessage?: string;
9
7
  tooltipDisplayDelayMs?: number;
8
+ boostIndicatorRef: React.RefObject<HTMLDivElement>;
10
9
  }
11
- export declare function BoostButton({ boostMode, onToggleBoostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, }: BoostButtonProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function BoostButton({ boostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, boostIndicatorRef, }: BoostButtonProps): import("react/jsx-runtime").JSX.Element;
12
11
  export {};
@@ -7,6 +7,8 @@ interface DetailsToolbarProps {
7
7
  }) => void;
8
8
  onInvertSwapButtonClick?: () => void;
9
9
  onFeeButtonClick?: () => void;
10
+ isFlipButtonDisabled?: boolean;
11
+ flipButtonDisabledMessage?: string;
10
12
  feeInUsd?: string;
11
13
  estimatedTime?: string;
12
14
  canToggleBoostMode?: boolean;
@@ -19,5 +21,5 @@ interface DetailsToolbarProps {
19
21
  };
20
22
  boostTooltipDisplayDelayMs?: number;
21
23
  }
22
- export declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, }: DetailsToolbarProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, isFlipButtonDisabled, flipButtonDisabledMessage, }: DetailsToolbarProps): import("react/jsx-runtime").JSX.Element;
23
25
  export {};
@@ -21,6 +21,7 @@ export declare const ANIMATION_DURATIONS: {
21
21
  CHANGE_SWAP_STEP: number;
22
22
  SHOW_MODAL: number;
23
23
  HIDE_MODAL: number;
24
+ BOOST_BUTTON: number;
24
25
  };
25
26
  export declare const ANIMATION_TIMINGS: {
26
27
  EXPAND_ROUTE: string;
@@ -36,3 +36,4 @@ export declare function getContrastColor({ r, g, b, }: {
36
36
  * @returns {string} The hexadecimal color with opacity.
37
37
  */
38
38
  export declare function getHexColorFromOpacityPercentage(color: string, opacity: number): string;
39
+ export declare function blendColors(foreground: string, background: string): string | null;
@@ -3,7 +3,8 @@ import { Boost } from '../../components/layout/Boost';
3
3
  declare const meta: Meta<typeof Boost>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof meta>;
6
- export declare const Default: Story;
6
+ export declare const Normal: Story;
7
7
  export declare const Boosted: Story;
8
- export declare const Disabled: Story;
8
+ export declare const NormalDisabled: Story;
9
+ export declare const BoostedDisabled: Story;
9
10
  export declare const DisabledWithDelayedTooltip: Story;
@@ -10,3 +10,4 @@ export declare const Error: Story;
10
10
  export declare const ErrorHelpButton: Story;
11
11
  export declare const BoostDisabled: Story;
12
12
  export declare const BoostDisabledWithDelayedTooltip: Story;
13
+ export declare const FlipButtonDisabled: Story;
@@ -23,6 +23,8 @@ export interface InternalSquidTheme {
23
23
  'material-dark-thin': string;
24
24
  'material-dark-average': string;
25
25
  'material-dark-thick': string;
26
+ 'grey-100-005': string;
27
+ 'material-light-blend-grey-900': string;
26
28
  }
27
29
  export type SquidTheme = {
28
30
  'content-100': string;
package/dist/index.css CHANGED
@@ -2200,10 +2200,6 @@ video {
2200
2200
  padding-right: 0.625rem;
2201
2201
  }
2202
2202
 
2203
- .tw-pr-squid-xxs {
2204
- padding-right: 0.3125rem;
2205
- }
2206
-
2207
2203
  .tw-pt-\[5px\] {
2208
2204
  padding-top: 5px;
2209
2205
  }
@@ -2746,6 +2742,10 @@ input[type='number'] {
2746
2742
  outline-offset: 2px;
2747
2743
  }
2748
2744
 
2745
+ .disabled\:tw-cursor-not-allowed:disabled {
2746
+ cursor: not-allowed;
2747
+ }
2748
+
2749
2749
  .tw-group\/base-button:hover .group-hover\/base-button\:tw-block {
2750
2750
  display: block;
2751
2751
  }
@@ -2754,11 +2754,17 @@ input[type='number'] {
2754
2754
  display: none;
2755
2755
  }
2756
2756
 
2757
- .tw-group\/arrow-button:hover .group-hover\/arrow-button\:tw-rotate-180 {
2757
+ .tw-group\/flip-button:hover .group-hover\/flip-button\:tw-rotate-180 {
2758
2758
  --tw-rotate: 180deg;
2759
2759
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2760
2760
  }
2761
2761
 
2762
+ .tw-group\/boost-toggle:hover .group-hover\/boost-toggle\:tw-from-material-light-blend-grey-900 {
2763
+ --tw-gradient-from: var(--squid-theme-material-light-blend-grey-900) var(--tw-gradient-from-position);
2764
+ --tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
2765
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
2766
+ }
2767
+
2762
2768
  .tw-group\/swap-step-item-button:hover .group-hover\/swap-step-item-button\:tw-from-grey-700 {
2763
2769
  --tw-gradient-from: var(--squid-theme-grey-700) var(--tw-gradient-from-position);
2764
2770
  --tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
@@ -2781,7 +2787,7 @@ input[type='number'] {
2781
2787
  opacity: 1;
2782
2788
  }
2783
2789
 
2784
- .tw-group:disabled .group-disabled\:tw-grayscale {
2790
+ .tw-group\/boost-toggle:disabled .group-disabled\/boost-toggle\:tw-grayscale {
2785
2791
  --tw-grayscale: grayscale(100%);
2786
2792
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
2787
2793
  }
package/dist/index.d.ts CHANGED
@@ -79,13 +79,11 @@ type SwapStepItemStatus = 'executed' | 'progress' | 'pending';
79
79
  interface BoostButtonProps {
80
80
  boostMode: BoostMode;
81
81
  canToggleBoostMode?: boolean;
82
- onToggleBoostMode?: ({ boostMode }: {
83
- boostMode: BoostMode;
84
- }) => void;
85
82
  boostDisabledMessage?: string;
86
83
  tooltipDisplayDelayMs?: number;
84
+ boostIndicatorRef: React.RefObject<HTMLDivElement>;
87
85
  }
88
- declare function BoostButton({ boostMode, onToggleBoostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, }: BoostButtonProps): react_jsx_runtime.JSX.Element;
86
+ declare function BoostButton({ boostMode, canToggleBoostMode, boostDisabledMessage, tooltipDisplayDelayMs, boostIndicatorRef, }: BoostButtonProps): react_jsx_runtime.JSX.Element;
89
87
 
90
88
  interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
91
89
  label?: string;
@@ -189,6 +187,8 @@ interface DetailsToolbarProps {
189
187
  }) => void;
190
188
  onInvertSwapButtonClick?: () => void;
191
189
  onFeeButtonClick?: () => void;
190
+ isFlipButtonDisabled?: boolean;
191
+ flipButtonDisabledMessage?: string;
192
192
  feeInUsd?: string;
193
193
  estimatedTime?: string;
194
194
  canToggleBoostMode?: boolean;
@@ -201,7 +201,7 @@ interface DetailsToolbarProps {
201
201
  };
202
202
  boostTooltipDisplayDelayMs?: number;
203
203
  }
204
- declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, }: DetailsToolbarProps): react_jsx_runtime.JSX.Element;
204
+ declare function DetailsToolbar({ errorMessage, boostMode, onToggleBoostMode, onInvertSwapButtonClick, onFeeButtonClick, feeInUsd, estimatedTime, canToggleBoostMode, boostDisabledMessage, helpButton, isLoading, isEmpty, boostTooltipDisplayDelayMs, isFlipButtonDisabled, flipButtonDisabledMessage, }: DetailsToolbarProps): react_jsx_runtime.JSX.Element;
205
205
 
206
206
  interface DropdownMenuItemProps {
207
207
  label: string;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "git+https://github.com/0xsquid/squid-ui.git"
6
6
  },
7
7
  "description": "Squid's UI components",
8
- "version": "0.13.9",
8
+ "version": "0.13.10",
9
9
  "author": "",
10
10
  "license": "MIT",
11
11
  "resolutions": {
@@ -1,9 +0,0 @@
1
- import { Meta, StoryObj } from '@storybook/react';
2
- import { BoostButton } from '../../components/buttons/BoostButton';
3
- declare const meta: Meta<typeof BoostButton>;
4
- export default meta;
5
- type Story = StoryObj<typeof meta>;
6
- export declare const Normal: Story;
7
- export declare const Boost: Story;
8
- export declare const Disabled: Story;
9
- export declare const DisabledWithDelayedTooltip: Story;
@@ -1,9 +0,0 @@
1
- import { Meta, StoryObj } from '@storybook/react';
2
- import { BoostButton } from '../../components/buttons/BoostButton';
3
- declare const meta: Meta<typeof BoostButton>;
4
- export default meta;
5
- type Story = StoryObj<typeof meta>;
6
- export declare const Normal: Story;
7
- export declare const Boost: Story;
8
- export declare const Disabled: Story;
9
- export declare const DisabledWithDelayedTooltip: Story;