'use client'; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { spinButtonClassNames: function() { return spinButtonClassNames; }, useSpinButtonStyles_unstable: function() { return useSpinButtonStyles_unstable; } }); const _react = require("@griffel/react"); const _reacttheme = require("@fluentui/react-theme"); const spinButtonClassNames = { root: 'fui-SpinButton', input: 'fui-SpinButton__input', incrementButton: 'fui-SpinButton__incrementButton', decrementButton: 'fui-SpinButton__decrementButton' }; const spinButtonExtraClassNames = { buttonActive: 'fui-SpinButton__button_active' }; const fieldHeights = { small: '24px', medium: '32px' }; const useRootClassName = (0, _react.makeResetStyles)({ display: 'inline-grid', gridTemplateColumns: `1fr 24px`, gridTemplateRows: '1fr 1fr', columnGap: _reacttheme.tokens.spacingHorizontalXS, rowGap: 0, position: 'relative', isolation: 'isolate', verticalAlign: 'middle', backgroundColor: _reacttheme.tokens.colorNeutralBackground1, minHeight: fieldHeights.medium, padding: `0 0 0 ${_reacttheme.tokens.spacingHorizontalMNudge}`, borderRadius: _reacttheme.tokens.borderRadiusMedium, // Apply border styles on the ::before pseudo element. // We cannot use ::after since that is used for selection. // Using the pseudo element allows us to place the border // above content in the component which ensures the buttons // line up visually with the border as expected. Without this // there is a bit of a gap which can become very noticeable // at high zoom or when OS zoom levels are not divisible by 2 // (e.g., 150% on Windows in Firefox) // This is most noticeable on the "outline" appearance which is // also the default so it feels worth the extra ceremony to get right. '::before': { content: '""', boxSizing: 'border-box', position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, pointerEvents: 'none', zIndex: 10, border: `1px solid ${_reacttheme.tokens.colorNeutralStroke1}`, borderBottomColor: _reacttheme.tokens.colorNeutralStrokeAccessible, borderRadius: _reacttheme.tokens.borderRadiusMedium }, '::after': { boxSizing: 'border-box', content: '""', position: 'absolute', right: 0, bottom: 0, left: 0, zIndex: 20, // Maintaining the correct corner radius: // Use the whole border-radius as the height and only put radii on the bottom corners. // (Otherwise the radius would be automatically reduced to fit available space.) // max() ensures the focus border still shows up even if someone sets tokens.borderRadiusMedium to 0. height: `max(2px, ${_reacttheme.tokens.borderRadiusMedium})`, borderBottomLeftRadius: _reacttheme.tokens.borderRadiusMedium, borderBottomRightRadius: _reacttheme.tokens.borderRadiusMedium, // Flat 2px border: // By default borderBottom will cause little "horns" on the ends. The clipPath trims them off. // (This could be done without trimming using `background: linear-gradient(...)`, but using // borderBottom makes it easier for people to override the color if needed.) borderBottom: `2px solid ${_reacttheme.tokens.colorCompoundBrandStroke}`, clipPath: 'inset(calc(100% - 2px) 0 0 0)', // Animation for focus OUT transform: 'scaleX(0)', transitionProperty: 'transform', transitionDuration: _reacttheme.tokens.durationUltraFast, transitionDelay: _reacttheme.tokens.curveAccelerateMid, '@media screen and (prefers-reduced-motion: reduce)': { transitionDuration: '0.01ms', transitionDelay: '0.01ms' } }, ':focus-within::after': { // Animation for focus IN transform: 'scaleX(1)', transitionProperty: 'transform', transitionDuration: _reacttheme.tokens.durationNormal, transitionDelay: _reacttheme.tokens.curveDecelerateMid, '@media screen and (prefers-reduced-motion: reduce)': { transitionDuration: '0.01ms', transitionDelay: '0.01ms' } }, ':focus-within:active::after': { // This is if the user clicks the field again while it's already focused borderBottomColor: _reacttheme.tokens.colorCompoundBrandStrokePressed }, ':focus-within': { outline: '2px solid transparent' } }); const useRootStyles = (0, _react.makeStyles)({ small: { minHeight: fieldHeights.small, ..._reacttheme.typographyStyles.caption1, paddingLeft: _reacttheme.tokens.spacingHorizontalS }, medium: {}, outline: {}, outlineInteractive: { ':hover::before': { ..._react.shorthands.borderColor(_reacttheme.tokens.colorNeutralStroke1Hover), borderBottomColor: _reacttheme.tokens.colorNeutralStrokeAccessibleHover }, // DO NOT add a space between the selectors! It changes the behavior of make-styles. ':active,:focus-within': { '::before': { ..._react.shorthands.borderColor(_reacttheme.tokens.colorNeutralStroke1Pressed), borderBottomColor: _reacttheme.tokens.colorNeutralStrokeAccessiblePressed } } }, underline: { '::before': { ..._react.shorthands.borderWidth(0, 0, '1px', 0), borderRadius: _reacttheme.tokens.borderRadiusNone } }, underlineInteractive: { ':hover::before': { borderBottomColor: _reacttheme.tokens.colorNeutralStrokeAccessibleHover }, // DO NOT add a space between the selectors! It changes the behavior of make-styles. ':active,:focus-within': { '::before': { borderBottomColor: _reacttheme.tokens.colorNeutralStrokeAccessiblePressed } }, '::after': { borderRadius: _reacttheme.tokens.borderRadiusNone } }, filled: { '::before': { border: `1px solid ${_reacttheme.tokens.colorTransparentStroke}` } }, 'filled-darker': { backgroundColor: _reacttheme.tokens.colorNeutralBackground3 }, 'filled-lighter': { backgroundColor: _reacttheme.tokens.colorNeutralBackground1 }, filledInteractive: { // DO NOT add a space between the selectors! It changes the behavior of make-styles. ':hover,:focus-within': { '::before': { // also handles pressed border color (:active) ..._react.shorthands.borderColor(_reacttheme.tokens.colorTransparentStrokeInteractive) } } }, invalid: { ':not(:focus-within),:hover:not(:focus-within)': { '::before': { ..._react.shorthands.borderColor(_reacttheme.tokens.colorPaletteRedBorder2) } } }, disabled: { cursor: 'not-allowed', backgroundColor: _reacttheme.tokens.colorTransparentBackground, '::before': { ..._react.shorthands.borderColor(_reacttheme.tokens.colorNeutralStrokeDisabled), '@media (forced-colors: active)': { ..._react.shorthands.borderColor('GrayText') } } } }); const useInputClassName = (0, _react.makeResetStyles)({ gridColumnStart: '1', gridColumnEnd: '2', gridRowStart: '1', gridRowEnd: '3', outlineStyle: 'none', border: '0', padding: '0', color: _reacttheme.tokens.colorNeutralForeground1, // Use literal "transparent" (not from the theme) to always let the color from the root show through backgroundColor: 'transparent', fontFamily: 'inherit', fontSize: 'inherit', fontWeight: 'inherit', lineHeight: 'inherit', width: '100%', '::placeholder': { color: _reacttheme.tokens.colorNeutralForeground4, opacity: 1 } }); const useInputStyles = (0, _react.makeStyles)({ disabled: { color: _reacttheme.tokens.colorNeutralForegroundDisabled, cursor: 'not-allowed', backgroundColor: _reacttheme.tokens.colorTransparentBackground, '::placeholder': { color: _reacttheme.tokens.colorNeutralForegroundDisabled } } }); const useBaseButtonClassName = (0, _react.makeResetStyles)({ display: 'inline-flex', width: '24px', alignItems: 'center', justifyContent: 'center', border: '0', position: 'absolute', outlineStyle: 'none', height: '16px', // Use literal "transparent" (not from the theme) to always let the color from the root show through backgroundColor: 'transparent', color: _reacttheme.tokens.colorNeutralForeground3, // common button layout gridColumnStart: '2', borderRadius: '0', padding: '0 5px 0 5px', ':active': { outlineStyle: 'none' }, ':enabled': { ':hover': { cursor: 'pointer', color: _reacttheme.tokens.colorNeutralForeground3Hover, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundHover }, ':active': { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundPressed }, [`&.${spinButtonExtraClassNames.buttonActive}`]: { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundPressed } }, ':disabled': { cursor: 'not-allowed', color: _reacttheme.tokens.colorNeutralForegroundDisabled } }); const useButtonStyles = (0, _react.makeStyles)({ increment: { gridRowStart: '1', borderTopRightRadius: _reacttheme.tokens.borderRadiusMedium, paddingTop: '4px', paddingBottom: '1px' }, decrement: { gridRowStart: '2', borderBottomRightRadius: _reacttheme.tokens.borderRadiusMedium, paddingTop: '1px', paddingBottom: '4px' }, // Padding values numbers don't align with design specs // but visually the padding aligns. // The icons are set in a 16x16px square but the artwork is inset from that // so these padding values are computed by hand. // Additionally the design uses fractional values so these are // rounded to the nearest integer. incrementButtonSmall: { padding: '3px 6px 0px 4px', height: '12px' }, decrementButtonSmall: { padding: '0px 6px 3px 4px', height: '12px' }, outline: {}, underline: { backgroundColor: 'transparent', color: _reacttheme.tokens.colorNeutralForeground3, ':enabled': { ':hover': { color: _reacttheme.tokens.colorNeutralForeground3Hover, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundHover }, ':active': { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundPressed }, [`&.${spinButtonExtraClassNames.buttonActive}`]: { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorSubtleBackgroundPressed } }, ':disabled': { color: _reacttheme.tokens.colorNeutralForegroundDisabled } }, 'filled-darker': { backgroundColor: 'transparent', color: _reacttheme.tokens.colorNeutralForeground3, ':enabled': { ':hover': { color: _reacttheme.tokens.colorNeutralForeground3Hover, backgroundColor: _reacttheme.tokens.colorNeutralBackground3Hover }, ':active': { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorNeutralBackground3Pressed }, [`&.${spinButtonExtraClassNames.buttonActive}`]: { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorNeutralBackground3Pressed } }, ':disabled': { color: _reacttheme.tokens.colorNeutralForegroundDisabled } }, 'filled-lighter': { backgroundColor: 'transparent', color: _reacttheme.tokens.colorNeutralForeground3, ':enabled': { ':hover': { color: _reacttheme.tokens.colorNeutralForeground3Hover, backgroundColor: _reacttheme.tokens.colorNeutralBackground1Hover }, [`:active,&.${spinButtonExtraClassNames.buttonActive}`]: { color: _reacttheme.tokens.colorNeutralForeground3Pressed, backgroundColor: _reacttheme.tokens.colorNeutralBackground1Pressed } }, ':disabled': { color: _reacttheme.tokens.colorNeutralForegroundDisabled } } }); const useSpinButtonStyles_unstable = (state)=>{ 'use no memo'; const { appearance, spinState, size } = state; const disabled = state.input.disabled; const invalid = `${state.input['aria-invalid']}` === 'true'; const filled = appearance.startsWith('filled'); const rootStyles = useRootStyles(); const buttonStyles = useButtonStyles(); const inputStyles = useInputStyles(); state.root.className = (0, _react.mergeClasses)(spinButtonClassNames.root, useRootClassName(), rootStyles[size], rootStyles[appearance], filled && rootStyles.filled, !disabled && appearance === 'outline' && rootStyles.outlineInteractive, !disabled && appearance === 'underline' && rootStyles.underlineInteractive, !disabled && filled && rootStyles.filledInteractive, !disabled && invalid && rootStyles.invalid, disabled && rootStyles.disabled, state.root.className); state.incrementButton.className = (0, _react.mergeClasses)(spinButtonClassNames.incrementButton, spinState === 'up' && `${spinButtonExtraClassNames.buttonActive}`, useBaseButtonClassName(), buttonStyles.increment, buttonStyles[appearance], size === 'small' && buttonStyles.incrementButtonSmall, state.incrementButton.className); state.decrementButton.className = (0, _react.mergeClasses)(spinButtonClassNames.decrementButton, spinState === 'down' && `${spinButtonExtraClassNames.buttonActive}`, useBaseButtonClassName(), buttonStyles.decrement, buttonStyles[appearance], size === 'small' && buttonStyles.decrementButtonSmall, state.decrementButton.className); state.input.className = (0, _react.mergeClasses)(spinButtonClassNames.input, useInputClassName(), disabled && inputStyles.disabled, state.input.className); return state; };