@mackin.com/styleguide 7.9.0 → 7.11.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 +15 -5
  2. package/index.js +60 -32
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -27,6 +27,8 @@ interface AutocompleteProps {
27
27
  /** The minimum characters before 'getOptions' is called. No default. */
28
28
  minChars?: number;
29
29
  inputAriaAttributes?: React.AriaAttributes;
30
+ /** Defaults to 0ms. */
31
+ getOptionsDebounceMs?: number;
30
32
  onChange: (value: string) => void;
31
33
  getOptions: (value: string) => Promise<AutocompleteValue[]>;
32
34
  onPick: (value: AutocompleteValue) => void;
@@ -202,17 +204,21 @@ interface FileUploaderProps {
202
204
  instructionMessage?: string;
203
205
  /** For additional info below the instructionMessage. */
204
206
  infoMessage?: string | JSX.Element;
207
+ /** If false, the 'infoMessage' will be hidden when a file is picked. Defaults to 'true' */
208
+ showInfoOnPick?: boolean;
209
+ disabled?: boolean;
205
210
  }
206
- declare const FileUploader: (p: FileUploaderProps) => JSX.Element;
211
+ declare const FileUploader: (p: FileUploaderProps) => JSX.Element;
212
+ declare const getFileSizeDisplay: (size: number) => string;
207
213
 
208
- declare type FormProps = React.ClassAttributes<HTMLFormElement> & React.FormHTMLAttributes<HTMLFormElement>;
209
- interface IProps extends FormProps {
214
+ declare type BaseProps = React.ClassAttributes<HTMLFormElement> & React.FormHTMLAttributes<HTMLFormElement>;
215
+ interface FormProps extends BaseProps {
210
216
  inline?: boolean;
211
217
  /** If true, preventDefault and stopPropagation will be applied prior to onSubmit being called. Defaults to true. */
212
218
  ajax?: boolean;
213
219
  }
214
220
  /** Use this instead of <form> directly. If we need to fight Chrome's autofill, we can do so at a global level. */
215
- declare const Form: React.ForwardRefExoticComponent<Pick<IProps, "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>>;
221
+ 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>>;
216
222
  declare const FormFlexRow: (props: {
217
223
  children: React.ReactNode;
218
224
  className?: string;
@@ -804,6 +810,10 @@ interface MackinTheme {
804
810
  desktop: string;
805
811
  tablet: string;
806
812
  };
813
+ mediaQueries: {
814
+ desktop: string;
815
+ tablet: string;
816
+ };
807
817
  }
808
818
  /** Call this on your theme after messing with the props. It will re-build things that depend on sizes and colors. */
809
819
  declare const calcDynamicThemeProps: <T extends MackinTheme>(theme: T) => void;
@@ -979,4 +989,4 @@ declare const WaitingIndicator: (p: {
979
989
  debug?: boolean;
980
990
  }) => JSX.Element;
981
991
 
982
- export { Alignment, Autocomplete, AutocompleteProps, AutocompleteValue, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DateInput, DateInputProps, DatePicker, DatePickerProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, GlobalStyles, Header, Highlight, ICONS, Icon, Image, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, List, ListItem, ListItemProps, ListProps, MackinTheme, Modal, Nav, NumberInput, NumberInputProps, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerProps, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextArea, TextAreaProps, TextInput, TextInputProps, TextProps, Th, ThSort, ThemeProvider, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, getCurrencyDisplay, mergeClassNames, useMediaQuery, useThemeSafely };
992
+ export { Alignment, Autocomplete, AutocompleteProps, AutocompleteValue, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DateInput, DateInputProps, DatePicker, DatePickerProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, FormProps, GlobalStyles, Header, Highlight, ICONS, Icon, Image, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, List, ListItem, ListItemProps, ListProps, MackinTheme, Modal, Nav, NumberInput, NumberInputProps, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerProps, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextArea, TextAreaProps, TextInput, TextInputProps, TextProps, Th, ThSort, ThemeProvider, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, getCurrencyDisplay, getFileSizeDisplay, mergeClassNames, useMediaQuery, useThemeSafely };
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
3
  var css = require('@emotion/css');
4
+ var lodash = require('lodash');
4
5
  var React = require('react');
5
6
  var nanoid = require('nanoid');
6
7
  var proRegularSvgIcons = require('@fortawesome/pro-regular-svg-icons');
@@ -8,7 +9,6 @@ var proSolidSvgIcons = require('@fortawesome/pro-solid-svg-icons');
8
9
  var proLightSvgIcons = require('@fortawesome/pro-light-svg-icons');
9
10
  var reactFontawesome = require('@fortawesome/react-fontawesome');
10
11
  var dateFns = require('date-fns');
11
- var lodash = require('lodash');
12
12
  var reactDom = require('react-dom');
13
13
  var reactTinyPopover = require('react-tiny-popover');
14
14
  var reactRouterDom = require('react-router-dom');
@@ -47,6 +47,8 @@ const calcDynamicThemeProps = (theme) => {
47
47
  theme.controls.focusOutlineShadow = `0px 0px 4px 2px ${theme.colors.focusOutline}`;
48
48
  theme.controls.focusOutlineRequiredShadow = `0px 0px 4px 2px ${theme.colors.focusOutlineRequired}`;
49
49
  theme.controls.dividerBorder = `2px solid ${theme.colors.divider}`;
50
+ theme.mediaQueries.desktop = `@media(min-width:${theme.breakpoints.desktop})`;
51
+ theme.mediaQueries.tablet = `@media(min-width:${theme.breakpoints.tablet})`;
50
52
  };
51
53
  const defaultTheme = {
52
54
  colors: {
@@ -135,6 +137,10 @@ const defaultTheme = {
135
137
  breakpoints: {
136
138
  desktop: '800px',
137
139
  tablet: '768px'
140
+ },
141
+ mediaQueries: {
142
+ desktop: '',
143
+ tablet: ''
138
144
  }
139
145
  };
140
146
  calcDynamicThemeProps(defaultTheme);
@@ -877,6 +883,7 @@ const getAutocompleteValueId = (v) => {
877
883
  };
878
884
  //TB: will need to use the new input
879
885
  const Autocomplete = (p) => {
886
+ var _a;
880
887
  const element = React__namespace.useRef(null);
881
888
  const input = React__namespace.useRef(null);
882
889
  const list = React__namespace.useRef(null);
@@ -886,6 +893,19 @@ const Autocomplete = (p) => {
886
893
  var _a;
887
894
  return values.slice(0, (_a = p.maxShownValues) !== null && _a !== void 0 ? _a : DEFAULT_MAX_SHOWN_VALUES);
888
895
  }, [values]);
896
+ const onChangeForOptions = React__namespace.useRef(lodash.debounce((value) => {
897
+ if (!p.minChars || value.length >= p.minChars) {
898
+ p.getOptions(value)
899
+ .then(vals => {
900
+ setValues(vals);
901
+ }).catch(err => {
902
+ // ignore it
903
+ });
904
+ }
905
+ else {
906
+ setValues([]);
907
+ }
908
+ }, (_a = p.getOptionsDebounceMs) !== null && _a !== void 0 ? _a : 0, { leading: true, trailing: true }));
889
909
  const theme = useThemeSafely();
890
910
  const baseClass = css.css `
891
911
  label: Autocomplete;
@@ -949,17 +969,7 @@ const Autocomplete = (p) => {
949
969
  React__namespace.createElement(Input, { inputAriaAttributes: p.inputAriaAttributes, ref: input, debounceMs: 0, type: "text", value: getAutocompleteValueText(p.value), round: p.round, rounded: p.rounded, rightControl: p.rightControl, placeholder: p.placeholder, id: p.id, disabled: p.disabled, className: p.className, inputClassName: css.cx(inputClass, p.inputClassName), maxLength: p.maxLength, required: p.required, onChange: v => {
950
970
  const value = v;
951
971
  p.onChange(value);
952
- if (!p.minChars || value.length >= p.minChars) {
953
- p.getOptions(value)
954
- .then(vals => {
955
- setValues(vals);
956
- }).catch(err => {
957
- // ignore it
958
- });
959
- }
960
- else {
961
- setValues([]);
962
- }
972
+ onChangeForOptions.current(value);
963
973
  }, onKeyDown: e => {
964
974
  var _a, _b;
965
975
  if (showValues) {
@@ -1727,7 +1737,7 @@ const hoverClass = css.css({
1727
1737
  backgroundColor: 'rgba(0,0,0,0.25) !important'
1728
1738
  });
1729
1739
  const FileUploader = (p) => {
1730
- var _a, _b, _c, _d, _e, _f, _g;
1740
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1731
1741
  const [message, setMessage] = React.useState(undefined);
1732
1742
  const [canUpload, setCanUpload] = React.useState(false);
1733
1743
  const [uploading, setUploading] = React.useState(false);
@@ -1743,7 +1753,7 @@ const FileUploader = (p) => {
1743
1753
  filesDisplay = (_b = p.instructionMessage) !== null && _b !== void 0 ? _b : `Click or drag and drop files.`;
1744
1754
  }
1745
1755
  else {
1746
- filesDisplay = `${files.length.toLocaleString()} file${files.length > 1 ? 's' : ''} selected (${getSizeString(totalFileSize)}): ${files.files.map(f => f.name).join(', ')}`;
1756
+ filesDisplay = `${files.length.toLocaleString()} file${files.length > 1 ? 's' : ''} selected (${getFileSizeDisplay(totalFileSize)}): ${files.files.map(f => f.name).join(', ')}`;
1747
1757
  }
1748
1758
  }
1749
1759
  const setAllFiles = (inputFiles) => {
@@ -1765,8 +1775,9 @@ const FileUploader = (p) => {
1765
1775
  maxBytes: p.maxBytes
1766
1776
  });
1767
1777
  };
1778
+ const showInfoOnPick = (_c = p.showInfoOnPick) !== null && _c !== void 0 ? _c : true;
1768
1779
  let infoMessage;
1769
- if (p.infoMessage) {
1780
+ if (p.infoMessage && (!files || showInfoOnPick)) {
1770
1781
  if (typeof p.infoMessage === 'string') {
1771
1782
  infoMessage = React__default['default'].createElement(Text, { noPad: true }, p.infoMessage);
1772
1783
  }
@@ -1783,6 +1794,8 @@ const FileUploader = (p) => {
1783
1794
  padding: '1rem',
1784
1795
  overflow: 'hidden',
1785
1796
  backgroundColor: theme.colors.lightBg,
1797
+ }, p.disabled && {
1798
+ opacity: theme.controls.disabledOpacity
1786
1799
  }), onDragOver: e => {
1787
1800
  var _a, _b;
1788
1801
  e.preventDefault();
@@ -1816,7 +1829,7 @@ const FileUploader = (p) => {
1816
1829
  setCanUpload(false);
1817
1830
  });
1818
1831
  } },
1819
- React__default['default'].createElement("input", { ref: input, className: css.css({
1832
+ React__default['default'].createElement("input", { disabled: p.disabled, ref: input, className: css.css({
1820
1833
  position: 'absolute',
1821
1834
  top: -50,
1822
1835
  left: 0,
@@ -1825,6 +1838,8 @@ const FileUploader = (p) => {
1825
1838
  width: '100%',
1826
1839
  cursor: 'pointer',
1827
1840
  opacity: 0
1841
+ }, p.disabled && {
1842
+ cursor: 'not-allowed'
1828
1843
  }), type: "file", multiple: p.multiple, accept: p.accept, onChange: e => {
1829
1844
  try {
1830
1845
  if (!e.target.files) {
@@ -1847,26 +1862,28 @@ const FileUploader = (p) => {
1847
1862
  zIndex: !!(files === null || files === void 0 ? void 0 : files.length) ? 1 : undefined
1848
1863
  }) },
1849
1864
  !(files === null || files === void 0 ? void 0 : files.length) && React__default['default'].createElement(Icon, { style: { fontSize: '2rem' }, id: "upload" }),
1850
- React__default['default'].createElement(Text, { align: "center", noPad: true, spacedOut: true },
1865
+ React__default['default'].createElement(Text, { align: "center", noPad: true, spacedOut: true, className: css.css({
1866
+ width: '100%'
1867
+ }) },
1851
1868
  filesDisplay,
1852
1869
  !!(files === null || files === void 0 ? void 0 : files.length) && (React__default['default'].createElement(Button, { onClick: e => {
1853
1870
  e.stopPropagation();
1854
1871
  onFilesChange(undefined);
1855
1872
  }, className: css.css({ marginLeft: '1rem', color: theme.colors.negative }), rightIcon: React__default['default'].createElement(Icon, { id: "clear" }), variant: "inlineLink" }, "Clear"))),
1856
1873
  infoMessage,
1857
- !!(files === null || files === void 0 ? void 0 : files.invalidFiles.length) && (React__default['default'].createElement(InfoPanel, { variant: "error" },
1874
+ !!(files === null || files === void 0 ? void 0 : files.invalidFiles.length) && (React__default['default'].createElement(InfoPanel, { variant: "error", className: css.css({ width: '100%' }) },
1858
1875
  "Invalid files: ",
1859
1876
  files.invalidFiles.map(f => f.name).join(', '),
1860
1877
  ".")),
1861
- (files === null || files === void 0 ? void 0 : files.overMaxBytes) && (React__default['default'].createElement(InfoPanel, { variant: "error" },
1878
+ (files === null || files === void 0 ? void 0 : files.overMaxBytes) && (React__default['default'].createElement(InfoPanel, { variant: "error", className: css.css({ width: '100%' }) },
1862
1879
  "Max file size exceeded (",
1863
- getSizeString((_c = p.maxBytes) !== null && _c !== void 0 ? _c : 0),
1880
+ getFileSizeDisplay((_d = p.maxBytes) !== null && _d !== void 0 ? _d : 0),
1864
1881
  ").")))),
1865
1882
  canUpload && !(files === null || files === void 0 ? void 0 : files.hasErrors) && (React__default['default'].createElement(Button, { className: css.css({
1866
- width: (_d = p.buttonWidth) !== null && _d !== void 0 ? _d : '10rem',
1883
+ width: (_e = p.buttonWidth) !== null && _e !== void 0 ? _e : '10rem',
1867
1884
  zIndex: 1,
1868
- }), waiting: uploading, type: "submit", variant: (_e = p.buttonVariant) !== null && _e !== void 0 ? _e : 'primary' }, (_f = p.buttonText) !== null && _f !== void 0 ? _f : 'Upload')),
1869
- message === 'success' && (React__default['default'].createElement(UploadInfoPanel, { variant: "positive", message: (_g = p.successMessage) !== null && _g !== void 0 ? _g : 'Upload successful.', onClear: () => setMessage(undefined) })),
1885
+ }), waiting: uploading, type: "submit", variant: (_f = p.buttonVariant) !== null && _f !== void 0 ? _f : 'primary' }, (_g = p.buttonText) !== null && _g !== void 0 ? _g : 'Upload')),
1886
+ message === 'success' && (React__default['default'].createElement(UploadInfoPanel, { variant: "positive", message: (_h = p.successMessage) !== null && _h !== void 0 ? _h : 'Upload successful.', onClear: () => setMessage(undefined) })),
1870
1887
  message === 'failure' && (React__default['default'].createElement(UploadInfoPanel, { variant: "error", message: fullFailureMessage, onClear: () => setMessage(undefined) }))));
1871
1888
  };
1872
1889
  const UploadInfoPanel = (p) => {
@@ -1880,18 +1897,28 @@ const UploadInfoPanel = (p) => {
1880
1897
  p.onClear();
1881
1898
  }, rightIcon: React__default['default'].createElement(Icon, { id: "clear" }), variant: "inlineLink" }, "Clear")));
1882
1899
  };
1883
- const bytesInMb = 1048576;
1884
- const bytesInKb = 1024;
1885
- const getSizeString = (size) => {
1886
- if (size < bytesInKb) {
1887
- return size.toLocaleString() + ' B';
1888
- }
1889
- else if (size < bytesInMb) {
1890
- return (size / bytesInKb).toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + ' KB';
1900
+ // OMG this is dumb. We're sticking with decimals for ease of use.
1901
+ // https://stackoverflow.com/questions/40949135/gigabyte-or-gibibyte-1000-or-1024
1902
+ const getFileSizeDisplay = (size) => {
1903
+ let value = 0;
1904
+ let suffix = '';
1905
+ if (size >= 1000000000) {
1906
+ value = size / 1000000000;
1907
+ suffix = 'GB';
1908
+ }
1909
+ else if (size >= 1000000) {
1910
+ value = size / 1000000;
1911
+ suffix = 'MB';
1912
+ }
1913
+ else if (size >= 1000) {
1914
+ value = size / 1000;
1915
+ suffix = 'KB';
1891
1916
  }
1892
1917
  else {
1893
- return (size / bytesInMb).toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + ' MB';
1918
+ value = size;
1919
+ suffix = 'B';
1894
1920
  }
1921
+ return value.toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + ` ${suffix}`;
1895
1922
  };
1896
1923
 
1897
1924
  /** @deprecated This will not work correctly with emotion/css. Use 'cx' for adding multiple class names together. */
@@ -3859,6 +3886,7 @@ exports.WaitingIndicator = WaitingIndicator;
3859
3886
  exports.calcDynamicThemeProps = calcDynamicThemeProps;
3860
3887
  exports.defaultTheme = defaultTheme;
3861
3888
  exports.getCurrencyDisplay = getCurrencyDisplay;
3889
+ exports.getFileSizeDisplay = getFileSizeDisplay;
3862
3890
  exports.mergeClassNames = mergeClassNames;
3863
3891
  exports.useMediaQuery = useMediaQuery;
3864
3892
  exports.useThemeSafely = useThemeSafely;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mackin.com/styleguide",
3
- "version": "7.9.0",
3
+ "version": "7.11.0",
4
4
  "description": "",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",