@mackin.com/styleguide 7.2.0 → 7.4.1

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 +39 -3
  2. package/index.js +111 -10
  3. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -247,9 +247,11 @@ declare const ErrorModal: (props: {
247
247
  declare type FormProps = React.ClassAttributes<HTMLFormElement> & React.FormHTMLAttributes<HTMLFormElement>;
248
248
  interface IProps extends FormProps {
249
249
  inline?: boolean;
250
+ /** If true, preventDefault and stopPropagation will be applied prior to onSubmit being called. Defaults to true. */
251
+ ajax?: boolean;
250
252
  }
251
253
  /** Use this instead of <form> directly. If we need to fight Chrome's autofill, we can do so at a global level. */
252
- declare const Form: React.ForwardRefExoticComponent<Pick<IProps, "inline" | "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<any>>;
254
+ 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<any>>;
253
255
  declare const FormFlexRow: (props: {
254
256
  children: React.ReactNode;
255
257
  className?: string;
@@ -268,9 +270,11 @@ declare const Header: (props: {
268
270
  toggleMenu?: () => void | undefined;
269
271
  /** If true, will hide menu button on larger screens */
270
272
  responsive?: boolean;
271
- rightElements?: JSX.Element;
272
273
  inline?: boolean;
273
274
  className?: string;
275
+ leftElements?: JSX.Element;
276
+ rightElements?: JSX.Element;
277
+ /** Elements will appear in the center of the header and slightly below. */
274
278
  centerOffsetElements?: JSX.Element;
275
279
  noMenu?: boolean;
276
280
  /** Will fill the title center aligned with wrapping. */
@@ -345,6 +349,7 @@ interface InputProps {
345
349
  debounceMs?: number;
346
350
  /** Defaults to 'off'. */
347
351
  autoComplete?: string;
352
+ autoFocus?: boolean;
348
353
  /** Called with debounce when the input changes. */
349
354
  onChange?: (value: InputValue, name?: string) => void;
350
355
  onFocus?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
@@ -688,6 +693,8 @@ interface MackinTheme {
688
693
  fonts: {
689
694
  family: string;
690
695
  size: string;
696
+ sizeSmall: string;
697
+ sizeLarge: string;
691
698
  headerFamily: string;
692
699
  };
693
700
  controls: {
@@ -904,4 +911,33 @@ declare const Backdrop: (p: {
904
911
 
905
912
  declare const useMediaQuery: (query: string) => boolean;
906
913
 
907
- export { Alignment, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DatePicker, DatePickerProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, GlobalStyles, Header, Highlight, ICONS, Icon, Image, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, List, ListItem, MackinTheme, Modal, Nav, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerProps, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextProps, Th, ThSort, ThemeProvider, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, getCurrencyDisplay, mergeClassNames, useMediaQuery, useThemeSafely };
914
+ interface AutoCompleteItem {
915
+ id: string | number;
916
+ name: string;
917
+ }
918
+ declare type AutocompleteValue = string | AutoCompleteItem;
919
+ interface AutocompleteProps {
920
+ value: AutocompleteValue | undefined;
921
+ round?: boolean;
922
+ rounded?: boolean;
923
+ rightControl?: JSX.Element;
924
+ placeholder?: string;
925
+ id?: string;
926
+ disabled?: boolean;
927
+ className?: string;
928
+ inputClassName?: string;
929
+ /** If not set, defaults to 100 */
930
+ maxLength?: number;
931
+ required?: boolean;
932
+ /** Limits what will be show in the autocomplete options. Default is 7. */
933
+ maxShownValues?: number;
934
+ /** The minimum characters before 'getOptions' is called. No default. */
935
+ minChars?: number;
936
+ onChange: (value: string) => void;
937
+ getOptions: (value: string) => Promise<AutocompleteValue[]>;
938
+ onPick: (value: AutocompleteValue) => void;
939
+ onKeyPress?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
940
+ }
941
+ declare const Autocomplete: (p: AutocompleteProps) => JSX.Element;
942
+
943
+ export { Alignment, Autocomplete, AutocompleteValue, Backdrop$1 as Backdrop, Backdrop as Backdrop2, BoundMemoryPager, BoundStaticPager, Button, ButtonProps, Calendar, CalendarProps, Checkbox, CheckboxProps, ConfirmModal, ConfirmModalProps, CopyButton, DatePicker, DatePickerProps, Divider, ErrorModal, FileUploader, Form, FormColumnRow, FormFlexRow, GlobalStyles, Header, Highlight, ICONS, Icon, Image, InfoPanel, InfoTip, InfoTipProps, Input, InputProps, ItemPager, Label, LabelProps, List, ListItem, MackinTheme, Modal, Nav, OmniLink, OmniLinkProps, PagedResult, Pager, PagerProps, Picker, PickerProps, Popover, ProgressBar, ProgressBarProps, SearchBox, SearchBoxProps, Slider, TabHeader, TabHeaderProps, TabLocker, Table, Td, TdCurrency, TdNumber, Text, TextProps, Th, ThSort, ThemeProvider, ToggleButton, ToggleButtonGroup, ToggleButtonGroupProps, ToggleButtonProps, TogglePasswordInput, Tr, WaitingIndicator, calcDynamicThemeProps, defaultTheme, getCurrencyDisplay, mergeClassNames, useMediaQuery, useThemeSafely };
package/index.js CHANGED
@@ -108,6 +108,8 @@ const defaultTheme = {
108
108
  fonts: {
109
109
  family: 'Arial, Helvetica, sans-serif',
110
110
  size: '16px',
111
+ sizeSmall: '0.7rem',
112
+ sizeLarge: '1.3rem',
111
113
  headerFamily: 'Arial, Helvetica, sans-serif',
112
114
  },
113
115
  controls: {
@@ -567,7 +569,7 @@ const Text = (props) => {
567
569
  const styles = css.css({
568
570
  userSelect: 'text',
569
571
  label: 'Text'
570
- }, tagStyles[tagChoice], alignStyles[(_a = props.align) !== null && _a !== void 0 ? _a : 'left'], props.smaller && { fontSize: '0.7rem' }, props.larger && { fontSize: '1.3rem' }, props.italics && { fontStyle: 'italic' }, props.ellipsis && {
572
+ }, tagStyles[tagChoice], alignStyles[(_a = props.align) !== null && _a !== void 0 ? _a : 'left'], props.smaller && { fontSize: theme.fonts.sizeSmall }, props.larger && { fontSize: theme.fonts.sizeLarge }, props.italics && { fontStyle: 'italic' }, props.ellipsis && {
571
573
  overflow: 'hidden',
572
574
  whiteSpace: 'nowrap',
573
575
  textOverflow: 'ellipsis'
@@ -800,7 +802,6 @@ const Pager = (props) => {
800
802
  display: block;
801
803
  }
802
804
  `;
803
- //TB: check this after fixing buttons
804
805
  const buttonStyles = css.css({
805
806
  backgroundColor: 'transparent'
806
807
  });
@@ -1603,7 +1604,7 @@ const ErrorModal = (props) => {
1603
1604
 
1604
1605
  /** Use this instead of <form> directly. If we need to fight Chrome's autofill, we can do so at a global level. */
1605
1606
  const Form = React__namespace.forwardRef((props, ref) => {
1606
- const { inline, children, onSubmit, className } = props, rest = __rest(props, ["inline", "children", "onSubmit", "className"]);
1607
+ const { inline, children, onSubmit, className, ajax } = props, rest = __rest(props, ["inline", "children", "onSubmit", "className", "ajax"]);
1607
1608
  const theme = useThemeSafely();
1608
1609
  return (React__namespace.createElement("form", Object.assign({}, rest, { ref: ref, className: css.cx('form', css.css({
1609
1610
  display: 'flex',
@@ -1611,8 +1612,10 @@ const Form = React__namespace.forwardRef((props, ref) => {
1611
1612
  alignItems: props.inline ? 'flex-end' : 'normal',
1612
1613
  gap: theme.controls.gap
1613
1614
  }), props.className), onSubmit: e => {
1614
- e.preventDefault();
1615
- e.stopPropagation();
1615
+ if (ajax !== false) {
1616
+ e.preventDefault();
1617
+ e.stopPropagation();
1618
+ }
1616
1619
  if (onSubmit) {
1617
1620
  onSubmit(e);
1618
1621
  }
@@ -1636,7 +1639,6 @@ const FormColumnRow = (props) => {
1636
1639
  }), props.className) }, props.children));
1637
1640
  };
1638
1641
 
1639
- //TB: have a sticky variant
1640
1642
  const Header = (props) => {
1641
1643
  const theme = useThemeSafely();
1642
1644
  const bodyStyles = css.css `
@@ -1696,6 +1698,12 @@ const Header = (props) => {
1696
1698
  grid-auto-flow: column;
1697
1699
  align-items: center;
1698
1700
  `;
1701
+ const leftElementStyles = props.leftElements && css.css({
1702
+ display: 'grid',
1703
+ gap: '0.5rem',
1704
+ gridAutoFlow: 'column',
1705
+ alignItems: 'center'
1706
+ });
1699
1707
  const centerElementsStyles = props.centerOffsetElements && css.css `
1700
1708
  position: absolute;
1701
1709
  display: flex;
@@ -1721,6 +1729,7 @@ const Header = (props) => {
1721
1729
  return (React__namespace.createElement("div", { className: css.cx('header', headerStyles, props.className) },
1722
1730
  !props.noMenu && (React__namespace.createElement(Button, { variant: "icon", className: headerButtonStyles, onClick: toggleMenu },
1723
1731
  React__namespace.createElement(Icon, { id: "menu" }))),
1732
+ props.leftElements && React__namespace.createElement("div", { className: leftElementStyles }, props.leftElements),
1724
1733
  title,
1725
1734
  props.rightElements && React__namespace.createElement("div", { className: rightElementStyles }, props.rightElements),
1726
1735
  props.centerOffsetElements && (React__namespace.createElement("div", { className: centerElementsStyles },
@@ -2033,15 +2042,15 @@ const Input = React__namespace.forwardRef((props, ref) => {
2033
2042
  };
2034
2043
  }
2035
2044
  if (props.type === 'number') {
2036
- inputElement = React__namespace.createElement("input", { ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly,
2045
+ inputElement = React__namespace.createElement("input", { autoFocus: props.autoFocus, ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly,
2037
2046
  // set fixed default to defeat pasting stupid numbers
2038
2047
  maxLength: 50, min: props.min, max: props.max, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(inputStyles, props.inputClassName), placeholder: props.placeholder, type: "number", value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
2039
2048
  }
2040
2049
  else if (props.type === 'date') {
2041
- inputElement = React__namespace.createElement("input", { ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: 10, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(inputStyles, props.inputClassName), placeholder: props.placeholder, type: "text", value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
2050
+ inputElement = React__namespace.createElement("input", { autoFocus: props.autoFocus, ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: 10, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(inputStyles, props.inputClassName), placeholder: props.placeholder, type: "text", value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
2042
2051
  }
2043
2052
  else if (props.type === 'textarea') {
2044
- inputElement = React__namespace.createElement("textarea", { ref: ref, name: props.name, style: props.style, rows: props.rows || 10, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: props.maxLength || DEFAULT_MAX_LENGTH, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(css.css `
2053
+ inputElement = React__namespace.createElement("textarea", { autoFocus: props.autoFocus, ref: ref, name: props.name, style: props.style, rows: props.rows || 10, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: props.maxLength || DEFAULT_MAX_LENGTH, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(css.css `
2045
2054
  ${inputStyles}
2046
2055
  max-width: 100%;
2047
2056
  min-height: ${theme.controls.height};
@@ -2050,7 +2059,7 @@ const Input = React__namespace.forwardRef((props, ref) => {
2050
2059
  }
2051
2060
  else {
2052
2061
  // text, password, email, and url
2053
- inputElement = React__namespace.createElement("input", { ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: props.maxLength || DEFAULT_MAX_LENGTH, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(inputStyles, props.inputClassName), placeholder: props.placeholder, type: props.type, value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
2062
+ inputElement = React__namespace.createElement("input", { autoFocus: props.autoFocus, ref: ref, name: props.name, pattern: props.pattern, style: props.style, autoComplete: autoComplete, tabIndex: props.readOnly ? -1 : undefined, readOnly: props.readOnly, maxLength: props.maxLength || DEFAULT_MAX_LENGTH, required: props.required, disabled: props.disabled, id: props.id, className: css.cx(inputStyles, props.inputClassName), placeholder: props.placeholder, type: props.type, value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
2054
2063
  }
2055
2064
  const inputWrapperStyles = css.css `
2056
2065
  width:100%;
@@ -3358,6 +3367,98 @@ const Backdrop = (props) => {
3358
3367
  }, ref: backdrop, className: css.cx('backdrop', styles, props.className) }, props.children));
3359
3368
  };
3360
3369
 
3370
+ const DEFAULT_MAX_SHOWN_VALUES = 7;
3371
+ const getAutocompleteValueText = (v) => {
3372
+ if (!v) {
3373
+ return '';
3374
+ }
3375
+ if (typeof v === 'string') {
3376
+ return v;
3377
+ }
3378
+ return v.name;
3379
+ };
3380
+ const getAutocompleteValueId = (v) => {
3381
+ if (typeof v === 'string') {
3382
+ return v;
3383
+ }
3384
+ return v.id;
3385
+ };
3386
+ const Autocomplete = (p) => {
3387
+ const element = React__namespace.useRef(null);
3388
+ const input = React__namespace.useRef(null);
3389
+ const [values, setValues] = React__namespace.useState([]);
3390
+ const showValues = React__namespace.useMemo(() => values.length > 0, [values]);
3391
+ const shownValues = React__namespace.useMemo(() => {
3392
+ var _a;
3393
+ return values.slice(0, (_a = p.maxShownValues) !== null && _a !== void 0 ? _a : DEFAULT_MAX_SHOWN_VALUES);
3394
+ }, [values]);
3395
+ const theme = useThemeSafely();
3396
+ const baseClass = css.css `
3397
+ label: Autocomplete;
3398
+ position: relative;
3399
+ width: 100%;
3400
+ `;
3401
+ const listClass = css.css `
3402
+ position: absolute;
3403
+ width: 100%;
3404
+ border: ${theme.controls.border};
3405
+ box-shadow: ${theme.controls.boxShadow};
3406
+ background-color: ${theme.colors.bg};
3407
+ margin-top: -4px !important;
3408
+ z-index: ${theme.zIndexes.backdrop};
3409
+ ${p.round || p.rounded && `
3410
+ border-radius: ${theme.controls.roundedRadius};
3411
+ `}
3412
+ `;
3413
+ const inputClass = css.css `
3414
+ ${showValues && `
3415
+ z-index: ${theme.zIndexes.backdrop};
3416
+ position: relative;
3417
+ `}
3418
+ `;
3419
+ return (React__namespace.createElement("div", { ref: element, className: css.cx(baseClass, 'autocomplete') },
3420
+ React__namespace.createElement(Backdrop, { onClick: () => setValues([]), show: showValues, allowScroll: true, transparent: true }),
3421
+ React__namespace.createElement(TabLocker, { disabled: !showValues, style: { position: 'relative' } },
3422
+ React__namespace.createElement(Input, { 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 => {
3423
+ const value = v;
3424
+ p.onChange(value);
3425
+ if (!p.minChars || value.length >= p.minChars) {
3426
+ p.getOptions(value)
3427
+ .then(vals => {
3428
+ setValues(vals);
3429
+ }).catch(err => {
3430
+ // ignore it
3431
+ });
3432
+ }
3433
+ else {
3434
+ setValues([]);
3435
+ }
3436
+ }, onKeyPress: e => { var _a; return (_a = p.onKeyPress) === null || _a === void 0 ? void 0 : _a.call(p, e); } }),
3437
+ showValues && (React__namespace.createElement(List, { className: listClass },
3438
+ shownValues.map(value => {
3439
+ return (React__namespace.createElement(ListItem, { key: getAutocompleteValueId(value), variant: "full" },
3440
+ React__namespace.createElement(Button, { onClick: () => {
3441
+ p.onPick(value);
3442
+ setValues([]);
3443
+ setTimeout(() => {
3444
+ var _a;
3445
+ // we need to wait until the component is re-rendered.
3446
+ // outside changes to Inputs will be ignored if the component has focus.
3447
+ (_a = input.current) === null || _a === void 0 ? void 0 : _a.focus();
3448
+ }, 0);
3449
+ } },
3450
+ React__namespace.createElement(Text, { tag: "div", ellipsis: true, align: "left" }, getAutocompleteValueText(value)))));
3451
+ }),
3452
+ shownValues.length < values.length && (React__namespace.createElement(ListItem, null,
3453
+ React__namespace.createElement(Text, { tag: "div", italics: true, align: "center" },
3454
+ "Showing ",
3455
+ shownValues.length.toLocaleString(),
3456
+ " of ",
3457
+ values.length.toLocaleString(),
3458
+ " results."))))))));
3459
+ };
3460
+
3461
+ exports.Autocomplete = Autocomplete;
3361
3462
  exports.Backdrop = Backdrop;
3362
3463
  exports.Backdrop2 = Backdrop$1;
3363
3464
  exports.BoundMemoryPager = BoundMemoryPager;
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@mackin.com/styleguide",
3
- "version": "7.2.0",
3
+ "version": "7.4.1",
4
4
  "description": "",
5
5
  "main": "./index.js",
6
- "types": "./index.d.ts",
6
+ "types": "./index.d.ts",
7
7
  "scripts": {},
8
8
  "author": "Mackin",
9
9
  "license": "ISC",