@mackin.com/styleguide 8.7.0 → 8.9.0

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.
Files changed (3) hide show
  1. package/index.d.ts +36 -4
  2. package/index.js +309 -236
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -212,15 +212,19 @@ interface FormProps extends BaseProps$3 {
212
212
  inline?: boolean;
213
213
  /** If true, preventDefault and stopPropagation will be applied prior to onSubmit being called. Defaults to true. */
214
214
  ajax?: boolean;
215
+ /** Removes the opinionated flex styling. 'inline' will be ignored. */
216
+ unstyled?: boolean;
215
217
  }
216
218
  /** Use this instead of <form> directly. If we need to fight Chrome's autofill, we can do so at a global level. */
217
- declare const Form: React.ForwardRefExoticComponent<Pick<FormProps, "inline" | "ajax" | "key" | "acceptCharset" | "action" | "autoComplete" | "encType" | "method" | "name" | "noValidate" | "target" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & React.RefAttributes<HTMLFormElement>>;
219
+ declare const Form: React.ForwardRefExoticComponent<Pick<FormProps, "inline" | "ajax" | "unstyled" | "key" | "acceptCharset" | "action" | "autoComplete" | "encType" | "method" | "name" | "noValidate" | "target" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & React.RefAttributes<HTMLFormElement>>;
220
+ /** @deprecated Just style normally using flex, grid, etc. */
218
221
  declare const FormFlexRow: (props: {
219
222
  children: React.ReactNode;
220
223
  className?: string;
221
224
  style?: React.CSSProperties;
222
225
  justifyContent?: "space-around" | "space-between" | "space-evenly" | "stretch" | "center" | "end" | "flex-end" | "flex-start" | "start";
223
226
  }) => JSX.Element;
227
+ /** @deprecated Just style normally using flex, grid, etc. */
224
228
  declare const FormColumnRow: (props: {
225
229
  children: React.ReactNode;
226
230
  cols: number;
@@ -461,6 +465,8 @@ interface ModalProps {
461
465
  __debug?: boolean;
462
466
  onClick?: () => void;
463
467
  }
468
+ /** Add to fixed positioned elements so their contents do not jump around when scrolling is disabled. */
469
+ declare const modalScrollFixClassName = "modal-scroll-fix";
464
470
  declare const Modal: (p: ModalProps) => React__default.ReactPortal | null;
465
471
 
466
472
  declare const Nav: (props: {
@@ -656,7 +662,7 @@ declare type PickerOption<T> = T | {
656
662
  id: T;
657
663
  name?: string;
658
664
  };
659
- interface SelectProps extends Omit<React.DetailedHTMLProps<React.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, 'value' | 'options'> {
665
+ interface SelectProps extends Omit<React.DetailedHTMLProps<React.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, 'value' | 'options' | 'string'> {
660
666
  }
661
667
  interface PickerProps<T extends PickerValue> extends SelectProps {
662
668
  value: T;
@@ -666,6 +672,12 @@ interface PickerProps<T extends PickerValue> extends SelectProps {
666
672
  round?: boolean;
667
673
  /** If true, bottom padding will be added to account for other inputs having space for error messages. */
668
674
  controlAlign?: boolean;
675
+ /** This will be applied to the select element. */
676
+ className?: string;
677
+ /** Applies to the outer wrapper which contains the select and other elements. */
678
+ wrapperClassName?: string;
679
+ /** Applies to the custom down arrow. */
680
+ iconClassName?: string;
669
681
  }
670
682
  declare const Picker: <T extends PickerValue>(props: PickerProps<T>) => JSX.Element;
671
683
 
@@ -709,7 +721,6 @@ interface SearchBoxProps {
709
721
  id?: string;
710
722
  placeholder?: string;
711
723
  round?: boolean;
712
- onSubmit?: () => Promise<void>;
713
724
  /** Defaults to 250ms */
714
725
  debounceMs?: number;
715
726
  autoFocus?: boolean;
@@ -717,6 +728,10 @@ interface SearchBoxProps {
717
728
  className?: string;
718
729
  buttonClassName?: string;
719
730
  inputClassName?: string;
731
+ /** This will be ignored if 'noForm' is true. */
732
+ onSubmit?: () => Promise<void>;
733
+ /** If true, the controls will not be wrapped in a Form component. In addition, 'onSubmit' will be ignored. */
734
+ noForm?: string;
720
735
  }
721
736
  declare const SearchBox: (props: SearchBoxProps) => JSX.Element;
722
737
 
@@ -731,7 +746,9 @@ interface MackinTheme {
731
746
  primary2: string;
732
747
  primary2Font: string;
733
748
  secondary: string;
749
+ /** @deprecated Bad name. Use 'secondaryFont'. */
734
750
  secondary2Font: string;
751
+ secondaryFont: string;
735
752
  info: string;
736
753
  infoFont: string;
737
754
  warning: string;
@@ -784,7 +801,10 @@ interface MackinTheme {
784
801
  height: string;
785
802
  heightSmall: string;
786
803
  boxShadow: string;
804
+ /** For controls with a background color. */
787
805
  hoverBrightness: string;
806
+ /** For controls without a background color. */
807
+ hoverBackground: string;
788
808
  transitionDuration: string;
789
809
  transitionEasing: string;
790
810
  transition: string;
@@ -862,6 +882,18 @@ interface SliderProps<T extends SliderValue> {
862
882
  renderValue?: (value: number) => string;
863
883
  /** Used with renderValue for the custom element width. Defaults to theme.controls.height * 2. */
864
884
  renderValueWidth?: string;
885
+ /** Styles of the overall slider. */
886
+ className?: string;
887
+ /** Styles for the slider handles. */
888
+ handleClassName?: string;
889
+ /** Styles for the first handle. */
890
+ handle1ClassName?: string;
891
+ /** Styles for the second handle. Ignored if the value is not an array. */
892
+ handle2ClassName?: string;
893
+ /** Styles of the track. */
894
+ trackClassName?: string;
895
+ /** Styles applied to the track between two handlers. Ignored if the value is not an array. */
896
+ innerTrackClassName?: string;
865
897
  }
866
898
  declare const Slider: <T extends SliderValue>(p: SliderProps<T>) => JSX.Element;
867
899
 
@@ -1107,4 +1139,4 @@ interface TabContainerProps {
1107
1139
  }
1108
1140
  declare const TabContainer: (p: TabContainerProps) => JSX.Element;
1109
1141
 
1110
- export { Accordian, AccordianProps, Alignment, Autocomplete, AutocompleteProps, AutocompleteValue, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DateInput, DateInputProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, FormProps, GlobalStyles, Header, Highlight, ICONS, Icon, Image, ImageProps, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, Link, LinkProps, List, ListItem, ListItemProps, ListProps, MackinTheme, Modal, ModalProps, Nav, NormalizeCss, NumberInput, NumberInputProps, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerOption, PickerProps, PickerValue, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabContainer, TabContainerProps, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextArea, TextAreaProps, TextInput, TextInputProps, TextProps, Th, ThSort, ThemeProvider, ThemeRenderer, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, enumToEntities, getCurrencyDisplay, getFileSizeDisplay, useAccordianState, useBooleanChanged, useIgnoreMount, useMediaQuery, useScrollbarSize, useThemeSafely, useWaiting };
1142
+ export { Accordian, AccordianProps, Alignment, Autocomplete, AutocompleteProps, AutocompleteValue, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DateInput, DateInputProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, FormProps, GlobalStyles, Header, Highlight, ICONS, Icon, Image, ImageProps, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, Link, LinkProps, List, ListItem, ListItemProps, ListProps, MackinTheme, Modal, ModalProps, Nav, NormalizeCss, NumberInput, NumberInputProps, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerOption, PickerProps, PickerValue, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabContainer, TabContainerProps, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextArea, TextAreaProps, TextInput, TextInputProps, TextProps, Th, ThSort, ThemeProvider, ThemeRenderer, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, enumToEntities, getCurrencyDisplay, getFileSizeDisplay, modalScrollFixClassName, useAccordianState, useBooleanChanged, useIgnoreMount, useMediaQuery, useScrollbarSize, useThemeSafely, useWaiting };
package/index.js CHANGED
@@ -128,6 +128,7 @@ const defaultTheme = {
128
128
  primary2: '#007bff',
129
129
  primary2Font: 'rgba(255, 255, 255, 0.9)',
130
130
  secondary: '#9e9e9e',
131
+ secondaryFont: 'rgba(255, 255, 255, 0.9)',
131
132
  secondary2Font: 'rgba(255, 255, 255, 0.9)',
132
133
  info: '#7851a9',
133
134
  infoFont: 'rgba(255, 255, 255, 0.9)',
@@ -182,7 +183,8 @@ const defaultTheme = {
182
183
  boxShadow: '2px 2px 4px rgba(0, 0, 0, 0.25)',
183
184
  headerBoxShadow: '0px 2px 12px 6px rgba(0, 0, 0, 0.2)',
184
185
  buttonBoxShadow: '2px 2px 4px rgba(0, 0, 0, 0.25)',
185
- hoverBrightness: 'brightness(0.75)',
186
+ hoverBrightness: 'brightness(0.8)',
187
+ hoverBackground: 'rgba(0, 0, 0, 0.1)',
186
188
  transitionDuration: '0.25s',
187
189
  transitionEasing: 'ease-in-out',
188
190
  transition: '',
@@ -282,6 +284,13 @@ const Text = (props) => {
282
284
  if (props.leftPad) {
283
285
  style.paddingLeft = props.leftPad;
284
286
  }
287
+ let fontWeight;
288
+ if (props.bold) {
289
+ fontWeight = 'bold';
290
+ }
291
+ else if (props.bold === false) {
292
+ fontWeight = 'normal';
293
+ }
285
294
  const styles = css.css(getTagStyles(theme, tagChoice), {
286
295
  userSelect: 'text',
287
296
  label: 'Text',
@@ -295,7 +304,7 @@ const Text = (props) => {
295
304
  overflow: 'hidden',
296
305
  textOverflow: 'ellipsis',
297
306
  display: '-webkit-box'
298
- }, props.spacedOut && { lineHeight: '1.5rem' }, props.bold && { fontWeight: 'bold' }, props.noPad && { margin: 0, padding: 0 }, headerRegex.test((_b = props.tag) !== null && _b !== void 0 ? _b : '') && {
307
+ }, props.spacedOut && { lineHeight: '1.5rem' }, { fontWeight }, props.noPad && { margin: 0, padding: 0 }, headerRegex.test((_b = props.tag) !== null && _b !== void 0 ? _b : '') && {
299
308
  fontFamily: theme.fonts.headerFamily
300
309
  });
301
310
  return React__namespace.createElement(tagChoice, {
@@ -304,6 +313,7 @@ const Text = (props) => {
304
313
  }, props.children);
305
314
  };
306
315
 
316
+ //TB: FUTURE de-dup these styles. create individual styles and compose them manually.
307
317
  const Button = React__namespace.forwardRef((props, ref) => {
308
318
  var _a;
309
319
  const { variant, round, rightIcon, leftIcon, iconBlock, small, readOnly, waiting, enforceMinWidth, controlAlign } = props, nativeProps = __rest(props, ["variant", "round", "rightIcon", "leftIcon", "iconBlock", "small", "readOnly", "waiting", "enforceMinWidth", "controlAlign"]);
@@ -368,6 +378,9 @@ const Button = React__namespace.forwardRef((props, ref) => {
368
378
  justify-content: center;
369
379
  align-items: center;
370
380
  background-color: transparent;
381
+ &:hover:not(:disabled) {
382
+ background-color: ${theme.controls.hoverBackground};
383
+ }
371
384
  ${props.small && `
372
385
  width: ${theme.controls.heightSmall};
373
386
  min-width: ${theme.controls.heightSmall};
@@ -380,6 +393,9 @@ const Button = React__namespace.forwardRef((props, ref) => {
380
393
  box-shadow: none;
381
394
  border: none;
382
395
  background-color: transparent;
396
+ &:hover:not(:disabled) {
397
+ background-color: ${theme.controls.hoverBackground};
398
+ }
383
399
  `}
384
400
  ${(props.variant === 'text') && `
385
401
  background-color: transparent;
@@ -496,7 +512,6 @@ const Button = React__namespace.forwardRef((props, ref) => {
496
512
  if (props.controlAlign) {
497
513
  return (React__namespace.createElement("span", { className: css.css({
498
514
  display: 'inline-block',
499
- width: '100%',
500
515
  paddingBottom: theme.controls.inputErrorMinHeight
501
516
  }) }, content));
502
517
  }
@@ -1154,6 +1169,240 @@ const Backdrop$1 = (props) => {
1154
1169
  }, ref: backdrop, className: css.cx('backdrop', styles, props.className) }, props.children));
1155
1170
  };
1156
1171
 
1172
+ /** useEffect but it will only fire when the actual truthiness of the value changes.
1173
+ * Use for comparing previous states to next states without all the bullshit around useEffect and component mounting.
1174
+ */
1175
+ const useBooleanChanged = (effect, dep) => {
1176
+ /*
1177
+ Why?
1178
+ useEffect with a dependency array will fire once on mount even though the dependency list doesn't change.
1179
+ Components like Modal need to communicate when their show status changes.
1180
+ useIgnoreMount is not enough because it only ignores the first render and is therefore a kludge.
1181
+ This is what we want regardless of mount status:
1182
+ true > false = Change
1183
+ false > true = Change
1184
+ true > true = No Change
1185
+ false > false = No Change
1186
+ undefined > false = No Change
1187
+ undefined > true = Change
1188
+ */
1189
+ const lastValue = React.useRef(undefined);
1190
+ React.useEffect(() => {
1191
+ //console.log('[useBooleanChanged] useEffect called with', dep, 'was', lastValue.current ?? 'undefined')
1192
+ if (!!lastValue.current !== !!dep) {
1193
+ const previous = lastValue.current;
1194
+ lastValue.current = dep;
1195
+ effect(!!lastValue.current, !!previous);
1196
+ //console.log('[useBooleanChanged] change called')
1197
+ }
1198
+ }, [dep]);
1199
+ };
1200
+
1201
+ const useLogger = (componentName, enabled) => {
1202
+ return (...messages) => {
1203
+ if (enabled) {
1204
+ // tslint:disable-next-line
1205
+ console.log(`[${componentName}]`, ...messages);
1206
+ }
1207
+ };
1208
+ };
1209
+
1210
+ // Taken from: https://github.com/react-bootstrap/dom-helpers/blob/master/src/scrollbarSize.ts
1211
+ const canUseDom = !!(typeof window !== 'undefined' &&
1212
+ window.document &&
1213
+ window.document.createElement);
1214
+ let size;
1215
+ /** Tells you actual width of the scroll bar. This can vary by browser. */
1216
+ const useScrollbarSize = (recalc) => {
1217
+ if ((!size && size !== 0) || recalc) {
1218
+ if (canUseDom) {
1219
+ const scrollDiv = document.createElement('div');
1220
+ scrollDiv.style.position = 'absolute';
1221
+ scrollDiv.style.top = '-9999px';
1222
+ scrollDiv.style.width = '50px';
1223
+ scrollDiv.style.height = '50px';
1224
+ scrollDiv.style.overflow = 'scroll';
1225
+ document.body.appendChild(scrollDiv);
1226
+ size = scrollDiv.offsetWidth - scrollDiv.clientWidth;
1227
+ document.body.removeChild(scrollDiv);
1228
+ }
1229
+ }
1230
+ return size;
1231
+ };
1232
+
1233
+ /** Add to fixed positioned elements so their contents do not jump around when scrolling is disabled. */
1234
+ const modalScrollFixClassName = 'modal-scroll-fix';
1235
+ const Modal = (p) => {
1236
+ var _a, _b, _c, _d;
1237
+ const backdrop = React.useContext(BackdropContext);
1238
+ const mouseDownElement = React.useRef(undefined);
1239
+ const theme = useThemeSafely();
1240
+ const hasHeader = p.closeButton || p.heading;
1241
+ const contentRef = React__default['default'].useRef(null);
1242
+ const log = useLogger((_a = p.id) !== null && _a !== void 0 ? _a : 'Modal', (_b = p.__debug) !== null && _b !== void 0 ? _b : false);
1243
+ const showing = React.useRef(p.show);
1244
+ const bodyStyles = React.useRef('');
1245
+ const fixedElementStyles = React.useRef('');
1246
+ const addScrollStyles = () => {
1247
+ var _a, _b, _c, _d;
1248
+ if (!bodyStyles.current) {
1249
+ bodyStyles.current = css.css({
1250
+ label: 'ModalBodyOverrides_' + ((_b = (_a = p.id) === null || _a === void 0 ? void 0 : _a.replace(/\s+/, '')) !== null && _b !== void 0 ? _b : nanoid.nanoid()),
1251
+ overflow: 'hidden',
1252
+ paddingRight: `${useScrollbarSize()}px`
1253
+ });
1254
+ log('creating singleton bodyStyles', bodyStyles.current);
1255
+ }
1256
+ if (!fixedElementStyles.current) {
1257
+ fixedElementStyles.current = css.css({
1258
+ label: 'ModalElementOverrides_' + ((_d = (_c = p.id) === null || _c === void 0 ? void 0 : _c.replace(/\s+/, '')) !== null && _d !== void 0 ? _d : nanoid.nanoid()),
1259
+ paddingRight: `${useScrollbarSize()}px`
1260
+ });
1261
+ }
1262
+ document.body.classList.add(bodyStyles.current);
1263
+ Array.from(document.querySelectorAll(`.${modalScrollFixClassName}`)).forEach(e => {
1264
+ e.classList.add(fixedElementStyles.current);
1265
+ });
1266
+ };
1267
+ const tryRemoveScrollStyles = () => {
1268
+ if (bodyStyles.current) {
1269
+ log('removing singleton', bodyStyles.current);
1270
+ document.body.classList.remove(bodyStyles.current);
1271
+ }
1272
+ if (fixedElementStyles.current) {
1273
+ Array.from(document.querySelectorAll(`.${modalScrollFixClassName}`)).forEach(e => {
1274
+ e.classList.remove(fixedElementStyles.current);
1275
+ });
1276
+ }
1277
+ };
1278
+ React.useEffect(() => {
1279
+ log('mounted');
1280
+ return () => {
1281
+ var _a;
1282
+ if (showing.current) {
1283
+ log(`un-mount in progress and this modal is showing. decrement the backdrop and try to remove singleton body styles.`);
1284
+ backdrop.setShow(false, (_a = p.id) !== null && _a !== void 0 ? _a : 'Modal');
1285
+ log('backdrop.setShow', false);
1286
+ tryRemoveScrollStyles();
1287
+ }
1288
+ else {
1289
+ log(`un-mount in progress but this modal is not showing. do nothing with the backdrop.`);
1290
+ }
1291
+ log('un-mounted');
1292
+ };
1293
+ }, []);
1294
+ useBooleanChanged((show, previousShow) => {
1295
+ var _a;
1296
+ log('show changed', `${previousShow !== null && previousShow !== void 0 ? previousShow : 'undefined'} > ${show}`);
1297
+ backdrop.setShow(show, (_a = p.id) !== null && _a !== void 0 ? _a : 'Modal');
1298
+ showing.current = show;
1299
+ log('backdrop.setShow', show);
1300
+ if (show) {
1301
+ log('this modal is showing. adding singleton bodyStyles', bodyStyles.current);
1302
+ addScrollStyles();
1303
+ }
1304
+ else {
1305
+ log('this modal is hiding. try removing singleton bodyStyles');
1306
+ tryRemoveScrollStyles();
1307
+ }
1308
+ }, p.show);
1309
+ React__default['default'].useLayoutEffect(() => {
1310
+ var _a;
1311
+ if (p.show === true) {
1312
+ const focusSelector = (_a = p.focusSelector) !== null && _a !== void 0 ? _a : '.modalCloseButton';
1313
+ // still need to wait for the next tick so the children are all rendered.
1314
+ setTimeout(() => {
1315
+ var _a;
1316
+ const element = (_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusSelector);
1317
+ element === null || element === void 0 ? void 0 : element.focus();
1318
+ log('set focus', focusSelector);
1319
+ });
1320
+ }
1321
+ }, [p.show]);
1322
+ const modalBodyStyles = css.css({
1323
+ maxHeight: p.scrollable ? undefined : '99vh',
1324
+ overflow: 'hidden',
1325
+ zIndex: theme.zIndexes.modal,
1326
+ cursor: 'default',
1327
+ margin: '1rem',
1328
+ backgroundColor: p.noBackground ? undefined : theme.colors.modalBg,
1329
+ border: p.noBackground ? undefined : theme.controls.border,
1330
+ boxShadow: p.noBackground ? undefined : theme.controls.boxShadow,
1331
+ maxWidth: (_c = p.maxWidth) !== null && _c !== void 0 ? _c : theme.breakpoints.tablet,
1332
+ minWidth: (_d = p.minWidth) !== null && _d !== void 0 ? _d : (hasHeader ? '250px' : undefined),
1333
+ opacity: p.show ? 1 : 0,
1334
+ fontSize: theme.fonts.size,
1335
+ fontFamily: theme.fonts.family,
1336
+ fontWeight: 'normal',
1337
+ '&:focus': {
1338
+ outline: 'none'
1339
+ }
1340
+ });
1341
+ const modalHeaderStyles = css.cx(css.css({
1342
+ display: 'flex',
1343
+ justifyContent: 'space-between',
1344
+ alignItems: 'center',
1345
+ backgroundColor: theme.colors.header,
1346
+ padding: '1rem',
1347
+ color: theme.colors.headerFont
1348
+ }), p.headerClassName);
1349
+ const modalContainerStyles = css.css([{
1350
+ position: 'fixed',
1351
+ height: '100%',
1352
+ width: '100%',
1353
+ backgroundColor: "transparent",
1354
+ display: 'flex',
1355
+ justifyContent: 'center',
1356
+ alignItems: 'center',
1357
+ cursor: p.onClick ? 'pointer' : 'default'
1358
+ }, p.scrollable && {
1359
+ overflowY: 'auto',
1360
+ overflowX: 'hidden',
1361
+ alignItems: 'flex-start'
1362
+ }]);
1363
+ if (p.show) {
1364
+ const backdropContainer = document.getElementById(backdrop.portalId);
1365
+ if (backdropContainer) {
1366
+ return reactDom.createPortal((React__default['default'].createElement("div", { onClick: e => {
1367
+ e.stopPropagation();
1368
+ if (!mouseDownElement.current) {
1369
+ if (p.onClick) {
1370
+ log('backdropContainer onClick');
1371
+ p.onClick();
1372
+ }
1373
+ }
1374
+ mouseDownElement.current = undefined;
1375
+ }, className: css.cx('modalContainer', modalContainerStyles) },
1376
+ React__default['default'].createElement("div", { id: p.id, ref: contentRef, onClick: e => e.stopPropagation(), onMouseDown: e => {
1377
+ mouseDownElement.current = e.target;
1378
+ e.stopPropagation();
1379
+ }, onMouseUp: e => {
1380
+ mouseDownElement.current = undefined;
1381
+ /*
1382
+ MouseDown and MouseUp stopPropagation was added to fix bugs while clicking within the modal.
1383
+ At least in the case of MouseUp, this breaks sliders and the handle grab logic appears to live on window.
1384
+ Turning this off now. Should not cause any issues for MouseUp unlike MouseDown.
1385
+ */
1386
+ // e.stopPropagation()
1387
+ }, className: css.cx('modalBody', modalBodyStyles, p.className) },
1388
+ React__default['default'].createElement(TabLocker, null,
1389
+ hasHeader && (React__default['default'].createElement("header", { className: css.cx('modalHeader', modalHeaderStyles) },
1390
+ p.heading ? React__default['default'].createElement(Text, { className: css.css({
1391
+ margin: 0,
1392
+ flexGrow: 1
1393
+ }), tag: "h1", bold: true }, p.heading) : React__default['default'].createElement("span", null),
1394
+ p.closeButton && p.onClick ? React__default['default'].createElement(Button, { className: css.cx('modalCloseButton', css.css({
1395
+ color: theme.colors.headerFont,
1396
+ marginLeft: '1rem',
1397
+ backgroundColor: 'transparent'
1398
+ })), variant: "icon", onClick: p.onClick },
1399
+ React__default['default'].createElement(Icon, { id: "close" })) : React__default['default'].createElement("span", null))),
1400
+ p.children)))), backdropContainer);
1401
+ }
1402
+ }
1403
+ return null;
1404
+ };
1405
+
1157
1406
  /** useEffect but ignores the first call on component mount. */
1158
1407
  const useIgnoreMount = (effect, deps) => {
1159
1408
  const mounted = React__default['default'].useRef(false);
@@ -1167,15 +1416,6 @@ const useIgnoreMount = (effect, deps) => {
1167
1416
  }, deps);
1168
1417
  };
1169
1418
 
1170
- const useLogger = (componentName, enabled) => {
1171
- return (...messages) => {
1172
- if (enabled) {
1173
- // tslint:disable-next-line
1174
- console.log(`[${componentName}]`, ...messages);
1175
- }
1176
- };
1177
- };
1178
-
1179
1419
  const portalId = 'backdrop';
1180
1420
  const BackdropContext = React__default['default'].createContext({
1181
1421
  showing: false,
@@ -1222,7 +1462,7 @@ const BackdropContextProvider = (p) => {
1222
1462
  }
1223
1463
  } },
1224
1464
  p.children,
1225
- p.__debug && (React__default['default'].createElement("p", { className: css.css({
1465
+ p.__debug && (React__default['default'].createElement("p", { className: css.cx(modalScrollFixClassName, css.css({
1226
1466
  position: 'fixed',
1227
1467
  top: 0, right: 0,
1228
1468
  backgroundColor: '#ff00004f',
@@ -1230,7 +1470,7 @@ const BackdropContextProvider = (p) => {
1230
1470
  padding: '0.5rem',
1231
1471
  margin: 0,
1232
1472
  zIndex: 9999
1233
- }) },
1473
+ })) },
1234
1474
  "Backdrop showCount: ",
1235
1475
  showCount))));
1236
1476
  };
@@ -1445,210 +1685,6 @@ const Checkbox = (props) => {
1445
1685
  props.children)));
1446
1686
  };
1447
1687
 
1448
- /** useEffect but it will only fire when the actual truthiness of the value changes.
1449
- * Use for comparing previous states to next states without all the bullshit around useEffect and component mounting.
1450
- */
1451
- const useBooleanChanged = (effect, dep) => {
1452
- /*
1453
- Why?
1454
- useEffect with a dependency array will fire once on mount even though the dependency list doesn't change.
1455
- Components like Modal need to communicate when their show status changes.
1456
- useIgnoreMount is not enough because it only ignores the first render and is therefore a kludge.
1457
- This is what we want regardless of mount status:
1458
- true > false = Change
1459
- false > true = Change
1460
- true > true = No Change
1461
- false > false = No Change
1462
- undefined > false = No Change
1463
- undefined > true = Change
1464
- */
1465
- const lastValue = React.useRef(undefined);
1466
- React.useEffect(() => {
1467
- //console.log('[useBooleanChanged] useEffect called with', dep, 'was', lastValue.current ?? 'undefined')
1468
- if (!!lastValue.current !== !!dep) {
1469
- const previous = lastValue.current;
1470
- lastValue.current = dep;
1471
- effect(!!lastValue.current, !!previous);
1472
- //console.log('[useBooleanChanged] change called')
1473
- }
1474
- }, [dep]);
1475
- };
1476
-
1477
- // Taken from: https://github.com/react-bootstrap/dom-helpers/blob/master/src/scrollbarSize.ts
1478
- const canUseDom = !!(typeof window !== 'undefined' &&
1479
- window.document &&
1480
- window.document.createElement);
1481
- let size;
1482
- /** Tells you actual width of the scroll bar. This can vary by browser. */
1483
- const useScrollbarSize = (recalc) => {
1484
- if ((!size && size !== 0) || recalc) {
1485
- if (canUseDom) {
1486
- const scrollDiv = document.createElement('div');
1487
- scrollDiv.style.position = 'absolute';
1488
- scrollDiv.style.top = '-9999px';
1489
- scrollDiv.style.width = '50px';
1490
- scrollDiv.style.height = '50px';
1491
- scrollDiv.style.overflow = 'scroll';
1492
- document.body.appendChild(scrollDiv);
1493
- size = scrollDiv.offsetWidth - scrollDiv.clientWidth;
1494
- document.body.removeChild(scrollDiv);
1495
- }
1496
- }
1497
- return size;
1498
- };
1499
-
1500
- const Modal = (p) => {
1501
- var _a, _b, _c, _d;
1502
- const backdrop = React.useContext(BackdropContext);
1503
- const mouseDownElement = React.useRef(undefined);
1504
- const theme = useThemeSafely();
1505
- const hasHeader = p.closeButton || p.heading;
1506
- const contentRef = React__default['default'].useRef(null);
1507
- const log = useLogger((_a = p.id) !== null && _a !== void 0 ? _a : 'Modal', (_b = p.__debug) !== null && _b !== void 0 ? _b : false);
1508
- const showing = React.useRef(p.show);
1509
- const bodyStyles = React.useRef('');
1510
- const tryRemoveBodyStyles = () => {
1511
- if (bodyStyles.current) {
1512
- log('removing singleton', bodyStyles.current);
1513
- document.body.classList.remove(bodyStyles.current);
1514
- }
1515
- };
1516
- React.useEffect(() => {
1517
- log('mounted');
1518
- return () => {
1519
- var _a;
1520
- if (showing.current) {
1521
- log(`un-mount in progress and this modal is showing. decrement the backdrop and try to remove singleton body styles.`);
1522
- backdrop.setShow(false, (_a = p.id) !== null && _a !== void 0 ? _a : 'Modal');
1523
- log('backdrop.setShow', false);
1524
- tryRemoveBodyStyles();
1525
- }
1526
- else {
1527
- log(`un-mount in progress but this modal is not showing. do nothing with the backdrop.`);
1528
- }
1529
- log('un-mounted');
1530
- };
1531
- }, []);
1532
- useBooleanChanged((show, previousShow) => {
1533
- var _a, _b, _c;
1534
- log('show changed', `${previousShow !== null && previousShow !== void 0 ? previousShow : 'undefined'} > ${show}`);
1535
- backdrop.setShow(show, (_a = p.id) !== null && _a !== void 0 ? _a : 'Modal');
1536
- showing.current = show;
1537
- log('backdrop.setShow', show);
1538
- if (!bodyStyles.current) {
1539
- bodyStyles.current = css.css({
1540
- label: 'ModalBodyOverrides_' + ((_c = (_b = p.id) === null || _b === void 0 ? void 0 : _b.replace(/\s+/, '')) !== null && _c !== void 0 ? _c : nanoid.nanoid()),
1541
- overflow: 'hidden',
1542
- paddingRight: `${useScrollbarSize()}px`
1543
- });
1544
- log('creating singleton bodyStyles', bodyStyles.current);
1545
- }
1546
- if (show) {
1547
- log('this modal is showing. adding singleton bodyStyles', bodyStyles.current);
1548
- document.body.classList.add(bodyStyles.current);
1549
- }
1550
- else {
1551
- log('this modal is hiding. try removing singleton bodyStyles');
1552
- tryRemoveBodyStyles();
1553
- }
1554
- }, p.show);
1555
- React__default['default'].useLayoutEffect(() => {
1556
- var _a;
1557
- if (p.show === true) {
1558
- const focusSelector = (_a = p.focusSelector) !== null && _a !== void 0 ? _a : '.modalCloseButton';
1559
- // still need to wait for the next tick so the children are all rendered.
1560
- setTimeout(() => {
1561
- var _a;
1562
- const element = (_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusSelector);
1563
- element === null || element === void 0 ? void 0 : element.focus();
1564
- log('set focus', focusSelector);
1565
- });
1566
- }
1567
- }, [p.show]);
1568
- const modalBodyStyles = css.css({
1569
- maxHeight: p.scrollable ? undefined : '99vh',
1570
- overflow: 'hidden',
1571
- zIndex: theme.zIndexes.modal,
1572
- cursor: 'default',
1573
- margin: '1rem',
1574
- backgroundColor: p.noBackground ? undefined : theme.colors.modalBg,
1575
- border: p.noBackground ? undefined : theme.controls.border,
1576
- boxShadow: p.noBackground ? undefined : theme.controls.boxShadow,
1577
- maxWidth: (_c = p.maxWidth) !== null && _c !== void 0 ? _c : theme.breakpoints.tablet,
1578
- minWidth: (_d = p.minWidth) !== null && _d !== void 0 ? _d : (hasHeader ? '250px' : undefined),
1579
- opacity: p.show ? 1 : 0,
1580
- fontSize: theme.fonts.size,
1581
- fontFamily: theme.fonts.family,
1582
- fontWeight: 'normal',
1583
- '&:focus': {
1584
- outline: 'none'
1585
- }
1586
- });
1587
- const modalHeaderStyles = css.cx(css.css({
1588
- display: 'flex',
1589
- justifyContent: 'space-between',
1590
- alignItems: 'center',
1591
- backgroundColor: theme.colors.header,
1592
- padding: '1rem',
1593
- color: theme.colors.headerFont
1594
- }), p.headerClassName);
1595
- const modalContainerStyles = css.css([{
1596
- position: 'fixed',
1597
- height: '100%',
1598
- width: '100%',
1599
- backgroundColor: "transparent",
1600
- display: 'flex',
1601
- justifyContent: 'center',
1602
- alignItems: 'center',
1603
- cursor: p.onClick ? 'pointer' : 'default'
1604
- }, p.scrollable && {
1605
- overflowY: 'auto',
1606
- overflowX: 'hidden',
1607
- alignItems: 'flex-start'
1608
- }]);
1609
- if (p.show) {
1610
- const backdropContainer = document.getElementById(backdrop.portalId);
1611
- if (backdropContainer) {
1612
- return reactDom.createPortal((React__default['default'].createElement("div", { onClick: e => {
1613
- e.stopPropagation();
1614
- if (!mouseDownElement.current) {
1615
- if (p.onClick) {
1616
- log('backdropContainer onClick');
1617
- p.onClick();
1618
- }
1619
- }
1620
- mouseDownElement.current = undefined;
1621
- }, className: css.cx('modalContainer', modalContainerStyles) },
1622
- React__default['default'].createElement("div", { id: p.id, ref: contentRef, onClick: e => e.stopPropagation(), onMouseDown: e => {
1623
- mouseDownElement.current = e.target;
1624
- e.stopPropagation();
1625
- }, onMouseUp: e => {
1626
- mouseDownElement.current = undefined;
1627
- /*
1628
- MouseDown and MouseUp stopPropagation was added to fix bugs while clicking within the modal.
1629
- At least in the case of MouseUp, this breaks sliders and the handle grab logic appears to live on window.
1630
- Turning this off now. Should not cause any issues for MouseUp unlike MouseDown.
1631
- */
1632
- // e.stopPropagation()
1633
- }, className: css.cx('modalBody', modalBodyStyles, p.className) },
1634
- React__default['default'].createElement(TabLocker, null,
1635
- hasHeader && (React__default['default'].createElement("header", { className: css.cx('modalHeader', modalHeaderStyles) },
1636
- p.heading ? React__default['default'].createElement(Text, { className: css.css({
1637
- margin: 0,
1638
- flexGrow: 1
1639
- }), tag: "h1", bold: true }, p.heading) : React__default['default'].createElement("span", null),
1640
- p.closeButton && p.onClick ? React__default['default'].createElement(Button, { className: css.cx('modalCloseButton', css.css({
1641
- color: theme.colors.headerFont,
1642
- marginLeft: '1rem',
1643
- backgroundColor: 'transparent'
1644
- })), variant: "icon", onClick: p.onClick },
1645
- React__default['default'].createElement(Icon, { id: "close" })) : React__default['default'].createElement("span", null))),
1646
- p.children)))), backdropContainer);
1647
- }
1648
- }
1649
- return null;
1650
- };
1651
-
1652
1688
  const ConfirmModal = (props) => {
1653
1689
  const theme = useThemeSafely();
1654
1690
  const modalStyle = css.css `
@@ -1717,14 +1753,19 @@ const ErrorModal = (props) => {
1717
1753
 
1718
1754
  /** Use this instead of <form> directly. If we need to fight Chrome's autofill, we can do so at a global level. */
1719
1755
  const Form = React__namespace.forwardRef((props, ref) => {
1720
- const { inline, children, onSubmit, className, ajax } = props, rest = __rest(props, ["inline", "children", "onSubmit", "className", "ajax"]);
1756
+ const { inline, children, onSubmit, className, ajax, unstyled } = props, rest = __rest(props, ["inline", "children", "onSubmit", "className", "ajax", "unstyled"]);
1721
1757
  const theme = useThemeSafely();
1722
- return (React__namespace.createElement("form", Object.assign({}, rest, { ref: ref, className: css.cx('form', css.css({
1758
+ let defaultStyle;
1759
+ if (!props.unstyled) {
1760
+ defaultStyle = css.css({
1761
+ label: 'Form',
1723
1762
  display: 'flex',
1724
1763
  flexDirection: props.inline ? 'row' : 'column',
1725
1764
  alignItems: props.inline ? 'flex-end' : 'normal',
1726
1765
  gap: theme.controls.gap
1727
- }), props.className), onSubmit: e => {
1766
+ });
1767
+ }
1768
+ return (React__namespace.createElement("form", Object.assign({}, rest, { ref: ref, className: css.cx('form', defaultStyle, props.className), onSubmit: e => {
1728
1769
  if (ajax !== false) {
1729
1770
  e.preventDefault();
1730
1771
  e.stopPropagation();
@@ -1734,6 +1775,7 @@ const Form = React__namespace.forwardRef((props, ref) => {
1734
1775
  }
1735
1776
  } }), children));
1736
1777
  });
1778
+ /** @deprecated Just style normally using flex, grid, etc. */
1737
1779
  const FormFlexRow = (props) => {
1738
1780
  var _a;
1739
1781
  const theme = useThemeSafely();
@@ -1743,6 +1785,7 @@ const FormFlexRow = (props) => {
1743
1785
  justifyContent: (_a = props.justifyContent) !== null && _a !== void 0 ? _a : 'normal'
1744
1786
  }), props.className) }, props.children));
1745
1787
  };
1788
+ /** @deprecated Just style normally using flex, grid, etc. */
1746
1789
  const FormColumnRow = (props) => {
1747
1790
  const theme = useThemeSafely();
1748
1791
  return (React__namespace.createElement("div", { style: props.style, className: css.cx('formColumnRow', css.css({
@@ -2260,6 +2303,7 @@ const BaseInput = React__namespace.forwardRef((props, ref) => {
2260
2303
  const theme = useThemeSafely();
2261
2304
  const { rightControl, round, wrapperClassName, showErrorDisplay } = props, nativeProps = __rest(props, ["rightControl", "round", "wrapperClassName", "showErrorDisplay"]);
2262
2305
  const inputStyles = css.css({
2306
+ backgroundColor: theme.colors.bg,
2263
2307
  fontFamily: theme.fonts.family,
2264
2308
  fontSize: theme.fonts.size,
2265
2309
  width: '100%',
@@ -2326,7 +2370,8 @@ const BaseInput = React__namespace.forwardRef((props, ref) => {
2326
2370
  `}
2327
2371
  `;
2328
2372
  return (React__namespace.createElement("div", { className: css.css({
2329
- width: '100%'
2373
+ width: '100%',
2374
+ label: 'BaseInput'
2330
2375
  }) },
2331
2376
  React__namespace.createElement("div", { className: css.cx('input', inputWrapperStyles, wrapperClassName) },
2332
2377
  inputElement,
@@ -2840,7 +2885,7 @@ const Label = (props) => {
2840
2885
  * https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
2841
2886
  */
2842
2887
  const useMediaQuery = (query) => {
2843
- const [matches, setMatches] = React.useState(false);
2888
+ const [matches, setMatches] = React.useState(window.matchMedia(query).matches);
2844
2889
  React.useEffect(() => {
2845
2890
  const media = window.matchMedia(query);
2846
2891
  if (media.matches !== matches) {
@@ -2976,6 +3021,7 @@ const LinkContent = (props) => {
2976
3021
  }) }, props.rightIcon)));
2977
3022
  };
2978
3023
 
3024
+ //TB: FUTURE de-dup these styles. create individual styles and compose them manually.
2979
3025
  const generateLinkStyles = (props, theme) => {
2980
3026
  var _a, _b, _c, _d, _e;
2981
3027
  const linkStyles = css.css `
@@ -3027,9 +3073,15 @@ const generateLinkStyles = (props, theme) => {
3027
3073
  `}
3028
3074
  ${props.variant === 'button' && `
3029
3075
  text-align: center;
3076
+ &:hover {
3077
+ background-color: ${theme.controls.hoverBackground};
3078
+ }
3030
3079
  `}
3031
3080
  ${props.variant === 'circle' && `
3032
3081
  text-align: center;
3082
+ &:hover {
3083
+ background-color: ${theme.controls.hoverBackground};
3084
+ }
3033
3085
  width: ${theme.controls.height};
3034
3086
  border-radius: 100%;
3035
3087
  display: flex;
@@ -3103,6 +3155,9 @@ const generateLinkStyles = (props, theme) => {
3103
3155
  ${props.variant === 'label' && `
3104
3156
  box-shadow: none;
3105
3157
  border: none;
3158
+ &:hover {
3159
+ background-color: ${theme.controls.hoverBackground};
3160
+ }
3106
3161
  `}
3107
3162
  ${props.variant === 'text' && `
3108
3163
  font-weight: normal;
@@ -3119,6 +3174,9 @@ const generateLinkStyles = (props, theme) => {
3119
3174
  font-size: 1.6rem;
3120
3175
  padding-left: 0;
3121
3176
  padding-right: 0;
3177
+ &:hover {
3178
+ background-color: ${theme.controls.hoverBackground};
3179
+ }
3122
3180
  `}
3123
3181
  ${props.block && `
3124
3182
  display: block;
@@ -3256,20 +3314,21 @@ const Picker = (props) => {
3256
3314
  }
3257
3315
  return React__namespace.createElement("option", { key: val, value: val }, label);
3258
3316
  })));
3259
- return (React__namespace.createElement("span", { className: css.css({
3317
+ return (React__namespace.createElement("span", { className: css.cx(css.css({
3260
3318
  label: 'PickerWrapper',
3261
3319
  position: 'relative',
3262
3320
  display: 'inline-block',
3263
3321
  width: '100%',
3264
3322
  paddingBottom: props.controlAlign ? theme.controls.inputErrorMinHeight : undefined
3265
- }) },
3323
+ }), props.wrapperClassName) },
3266
3324
  select,
3267
- !props.readOnly && (React__namespace.createElement(Icon, { id: "sortDesc", className: css.css({
3325
+ !props.readOnly && (React__namespace.createElement(Icon, { id: "sortDesc", className: css.cx(css.css({
3268
3326
  position: 'absolute',
3269
3327
  right: `calc(${theme.controls.padding} + ${props.round ? roundPxPadding : '0px'})`,
3270
- height: theme.controls.height,
3271
- pointerEvents: 'none'
3272
- }) }))));
3328
+ height: '100%',
3329
+ pointerEvents: 'none',
3330
+ color: theme.colors.font
3331
+ }), props.iconClassName) }))));
3273
3332
  };
3274
3333
 
3275
3334
  const Pager = (props) => {
@@ -3778,8 +3837,12 @@ const SearchBox = (props) => {
3778
3837
  }), props.buttonClassName), variant: "icon", small: true },
3779
3838
  React__namespace.createElement(Icon, { id: waiting ? 'waiting' : 'search', spin: waiting })));
3780
3839
  //TB: FUTURE replace with new inputs
3781
- return (React__namespace.createElement(Form, { role: "search", className: css.cx('searchBox', props.className), onSubmit: onSubmit },
3782
- React__namespace.createElement(Input, { inputClassName: props.inputClassName, autoFocus: props.autoFocus, id: props.id, debounceMs: props.debounceMs, disabled: waiting, type: "text", value: props.value, placeholder: props.placeholder, round: props.round, onChange: props.onChange, rightControl: submitButton })));
3840
+ const input = (React__namespace.createElement(Input, { inputClassName: props.inputClassName, autoFocus: props.autoFocus, id: props.id, debounceMs: props.debounceMs, disabled: waiting, type: "text", value: props.value, placeholder: props.placeholder, round: props.round, onChange: props.onChange, rightControl: submitButton }));
3841
+ const wrapperClassName = css.cx('searchBox', props.className);
3842
+ if (!props.noForm) {
3843
+ return (React__namespace.createElement(Form, { role: "search", className: wrapperClassName, onSubmit: onSubmit }, input));
3844
+ }
3845
+ return (React__namespace.createElement("div", { className: wrapperClassName }, input));
3783
3846
  };
3784
3847
 
3785
3848
  const GlobalStyles = (p) => {
@@ -3815,10 +3878,11 @@ const Slider = (p) => {
3815
3878
  const currentValue = React.useRef(p.value);
3816
3879
  const sliderContainer = React.useRef(null);
3817
3880
  const height = p.showValue ? `calc(${theme.controls.height} + 1.5rem)` : theme.controls.height;
3818
- return (React__default['default'].createElement("div", { ref: sliderContainer, className: css.css({
3881
+ return (React__default['default'].createElement("div", { ref: sliderContainer, className: css.cx(css.css({
3882
+ label: 'Slider',
3819
3883
  width: '100%',
3820
3884
  height,
3821
- }) },
3885
+ }), p.className) },
3822
3886
  React__default['default'].createElement(ReactSlider__default['default'], { step: p.step, min: p.min, max: p.max, value: p.value, onAfterChange: (value, index) => {
3823
3887
  p.onChange(value);
3824
3888
  }, onChange: p.onUpdate || p.showValue ? (value, index) => {
@@ -3831,15 +3895,22 @@ const Slider = (p) => {
3831
3895
  display: 'flex',
3832
3896
  alignItems: 'center',
3833
3897
  height: theme.controls.height
3834
- })) }, rest),
3898
+ }), p.trackClassName) }, rest),
3835
3899
  React__default['default'].createElement("div", { className: css.css({
3836
3900
  backgroundColor: theme.colors.secondary,
3837
3901
  height: `calc(${theme.controls.height} / 4)`,
3838
3902
  borderRadius: theme.controls.roundRadius,
3839
3903
  width: '100%'
3840
- }) }));
3904
+ }, p.innerTrackClassName && rest.key === 'track-1' && Array.isArray(p.value) ? p.innerTrackClassName : undefined) }));
3841
3905
  }, renderThumb: (props, state) => {
3842
3906
  const { className } = props, rest = __rest(props, ["className"]);
3907
+ let specificThumbStyles;
3908
+ if (p.handle1ClassName && props.key === 'thumb-0') {
3909
+ specificThumbStyles = p.handle1ClassName;
3910
+ }
3911
+ else if (p.handle2ClassName && props.key === 'thumb-1') {
3912
+ specificThumbStyles = p.handle2ClassName;
3913
+ }
3843
3914
  return (React__default['default'].createElement("div", Object.assign({ className: css.cx(className, css.css({
3844
3915
  width: theme.controls.height,
3845
3916
  height: theme.controls.height,
@@ -3860,7 +3931,7 @@ const Slider = (p) => {
3860
3931
  '&:hover': {
3861
3932
  filter: theme.controls.hoverBrightness
3862
3933
  }
3863
- })) }, rest), p.showValue && (React__default['default'].createElement(HandleText, { index: state.index, parentElement: sliderContainer.current, value: Array.isArray(currentValue.current) ? currentValue.current[state.index] : currentValue.current, renderValue: p.renderValue, renderValueWidth: p.renderValueWidth }))));
3934
+ }), specificThumbStyles, p.handleClassName) }, rest), p.showValue && (React__default['default'].createElement(HandleText, { index: state.index, parentElement: sliderContainer.current, value: Array.isArray(currentValue.current) ? currentValue.current[state.index] : currentValue.current, renderValue: p.renderValue, renderValueWidth: p.renderValueWidth }))));
3864
3935
  } })));
3865
3936
  };
3866
3937
  const rectsCollideX = (r1, r2) => {
@@ -4150,6 +4221,7 @@ const TextArea = React__namespace.forwardRef((props, ref) => {
4150
4221
  updateErrorMessage();
4151
4222
  }, [props.value]);
4152
4223
  const styles = css.css({
4224
+ backgroundColor: theme.colors.bg,
4153
4225
  maxWidth: '100%',
4154
4226
  minHeight: theme.controls.height,
4155
4227
  fontFamily: theme.fonts.family,
@@ -4830,6 +4902,7 @@ exports.defaultTheme = defaultTheme;
4830
4902
  exports.enumToEntities = enumToEntities;
4831
4903
  exports.getCurrencyDisplay = getCurrencyDisplay;
4832
4904
  exports.getFileSizeDisplay = getFileSizeDisplay;
4905
+ exports.modalScrollFixClassName = modalScrollFixClassName;
4833
4906
  exports.useAccordianState = useAccordianState;
4834
4907
  exports.useBooleanChanged = useBooleanChanged;
4835
4908
  exports.useIgnoreMount = useIgnoreMount;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mackin.com/styleguide",
3
- "version": "8.7.0",
3
+ "version": "8.9.0",
4
4
  "description": "",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",