@mackin.com/styleguide 7.1.1 → 7.3.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.
- package/index.d.ts +39 -2
- package/index.js +108 -9
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -268,9 +268,11 @@ declare const Header: (props: {
|
|
|
268
268
|
toggleMenu?: () => void | undefined;
|
|
269
269
|
/** If true, will hide menu button on larger screens */
|
|
270
270
|
responsive?: boolean;
|
|
271
|
-
rightElements?: JSX.Element;
|
|
272
271
|
inline?: boolean;
|
|
273
272
|
className?: string;
|
|
273
|
+
leftElements?: JSX.Element;
|
|
274
|
+
rightElements?: JSX.Element;
|
|
275
|
+
/** Elements will appear in the center of the header and slightly below. */
|
|
274
276
|
centerOffsetElements?: JSX.Element;
|
|
275
277
|
noMenu?: boolean;
|
|
276
278
|
/** Will fill the title center aligned with wrapping. */
|
|
@@ -345,10 +347,14 @@ interface InputProps {
|
|
|
345
347
|
debounceMs?: number;
|
|
346
348
|
/** Defaults to 'off'. */
|
|
347
349
|
autoComplete?: string;
|
|
350
|
+
autoFocus?: boolean;
|
|
348
351
|
/** Called with debounce when the input changes. */
|
|
349
352
|
onChange?: (value: InputValue, name?: string) => void;
|
|
350
353
|
onFocus?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
351
354
|
onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
355
|
+
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
356
|
+
onKeyUp?: (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
357
|
+
onKeyPress?: (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
352
358
|
/** Defaults to 100. Ignored for type=number and type=date. */
|
|
353
359
|
maxLength?: number;
|
|
354
360
|
/** Ignored for type=textarea. */
|
|
@@ -685,6 +691,8 @@ interface MackinTheme {
|
|
|
685
691
|
fonts: {
|
|
686
692
|
family: string;
|
|
687
693
|
size: string;
|
|
694
|
+
sizeSmall: string;
|
|
695
|
+
sizeLarge: string;
|
|
688
696
|
headerFamily: string;
|
|
689
697
|
};
|
|
690
698
|
controls: {
|
|
@@ -901,4 +909,33 @@ declare const Backdrop: (p: {
|
|
|
901
909
|
|
|
902
910
|
declare const useMediaQuery: (query: string) => boolean;
|
|
903
911
|
|
|
904
|
-
|
|
912
|
+
interface AutoCompleteItem {
|
|
913
|
+
id: string | number;
|
|
914
|
+
name: string;
|
|
915
|
+
}
|
|
916
|
+
declare type AutocompleteValue = string | AutoCompleteItem;
|
|
917
|
+
interface AutocompleteProps {
|
|
918
|
+
value: AutocompleteValue | undefined;
|
|
919
|
+
round?: boolean;
|
|
920
|
+
rounded?: boolean;
|
|
921
|
+
rightControl?: JSX.Element;
|
|
922
|
+
placeholder?: string;
|
|
923
|
+
id?: string;
|
|
924
|
+
disabled?: boolean;
|
|
925
|
+
className?: string;
|
|
926
|
+
inputClassName?: string;
|
|
927
|
+
/** If not set, defaults to 100 */
|
|
928
|
+
maxLength?: number;
|
|
929
|
+
required?: boolean;
|
|
930
|
+
/** Limits what will be show in the autocomplete options. Default is 7. */
|
|
931
|
+
maxShownValues?: number;
|
|
932
|
+
/** The minimum characters before 'getOptions' is called. No default. */
|
|
933
|
+
minChars?: number;
|
|
934
|
+
onChange: (value: string) => void;
|
|
935
|
+
getOptions: (value: string) => Promise<AutocompleteValue[]>;
|
|
936
|
+
onPick: (value: AutocompleteValue) => void;
|
|
937
|
+
onKeyPress?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
938
|
+
}
|
|
939
|
+
declare const Autocomplete: (p: AutocompleteProps) => JSX.Element;
|
|
940
|
+
|
|
941
|
+
export { Alignment, Autocomplete, 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:
|
|
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
|
});
|
|
@@ -1636,7 +1637,6 @@ const FormColumnRow = (props) => {
|
|
|
1636
1637
|
}), props.className) }, props.children));
|
|
1637
1638
|
};
|
|
1638
1639
|
|
|
1639
|
-
//TB: have a sticky variant
|
|
1640
1640
|
const Header = (props) => {
|
|
1641
1641
|
const theme = useThemeSafely();
|
|
1642
1642
|
const bodyStyles = css.css `
|
|
@@ -1696,6 +1696,12 @@ const Header = (props) => {
|
|
|
1696
1696
|
grid-auto-flow: column;
|
|
1697
1697
|
align-items: center;
|
|
1698
1698
|
`;
|
|
1699
|
+
const leftElementStyles = props.leftElements && css.css({
|
|
1700
|
+
display: 'grid',
|
|
1701
|
+
gap: '0.5rem',
|
|
1702
|
+
gridAutoFlow: 'column',
|
|
1703
|
+
alignItems: 'center'
|
|
1704
|
+
});
|
|
1699
1705
|
const centerElementsStyles = props.centerOffsetElements && css.css `
|
|
1700
1706
|
position: absolute;
|
|
1701
1707
|
display: flex;
|
|
@@ -1721,6 +1727,7 @@ const Header = (props) => {
|
|
|
1721
1727
|
return (React__namespace.createElement("div", { className: css.cx('header', headerStyles, props.className) },
|
|
1722
1728
|
!props.noMenu && (React__namespace.createElement(Button, { variant: "icon", className: headerButtonStyles, onClick: toggleMenu },
|
|
1723
1729
|
React__namespace.createElement(Icon, { id: "menu" }))),
|
|
1730
|
+
props.leftElements && React__namespace.createElement("div", { className: leftElementStyles }, props.leftElements),
|
|
1724
1731
|
title,
|
|
1725
1732
|
props.rightElements && React__namespace.createElement("div", { className: rightElementStyles }, props.rightElements),
|
|
1726
1733
|
props.centerOffsetElements && (React__namespace.createElement("div", { className: centerElementsStyles },
|
|
@@ -2033,24 +2040,24 @@ const Input = React__namespace.forwardRef((props, ref) => {
|
|
|
2033
2040
|
};
|
|
2034
2041
|
}
|
|
2035
2042
|
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,
|
|
2043
|
+
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
2044
|
// set fixed default to defeat pasting stupid numbers
|
|
2038
|
-
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 });
|
|
2045
|
+
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
2046
|
}
|
|
2040
2047
|
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 });
|
|
2048
|
+
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
2049
|
}
|
|
2043
2050
|
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 `
|
|
2051
|
+
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
2052
|
${inputStyles}
|
|
2046
2053
|
max-width: 100%;
|
|
2047
2054
|
min-height: ${theme.controls.height};
|
|
2048
2055
|
padding-top: 0.75rem;
|
|
2049
|
-
height:auto;`, props.inputClassName), placeholder: props.placeholder, value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange });
|
|
2056
|
+
height:auto;`, props.inputClassName), placeholder: props.placeholder, value: localValue, onFocus: onFocus, onBlur: onBlur, onChange: localOnChange, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, onKeyPress: props.onKeyPress });
|
|
2050
2057
|
}
|
|
2051
2058
|
else {
|
|
2052
2059
|
// 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 });
|
|
2060
|
+
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
2061
|
}
|
|
2055
2062
|
const inputWrapperStyles = css.css `
|
|
2056
2063
|
width:100%;
|
|
@@ -3358,6 +3365,98 @@ const Backdrop = (props) => {
|
|
|
3358
3365
|
}, ref: backdrop, className: css.cx('backdrop', styles, props.className) }, props.children));
|
|
3359
3366
|
};
|
|
3360
3367
|
|
|
3368
|
+
const DEFAULT_MAX_SHOWN_VALUES = 7;
|
|
3369
|
+
const getAutocompleteValueText = (v) => {
|
|
3370
|
+
if (!v) {
|
|
3371
|
+
return '';
|
|
3372
|
+
}
|
|
3373
|
+
if (typeof v === 'string') {
|
|
3374
|
+
return v;
|
|
3375
|
+
}
|
|
3376
|
+
return v.name;
|
|
3377
|
+
};
|
|
3378
|
+
const getAutocompleteValueId = (v) => {
|
|
3379
|
+
if (typeof v === 'string') {
|
|
3380
|
+
return v;
|
|
3381
|
+
}
|
|
3382
|
+
return v.id;
|
|
3383
|
+
};
|
|
3384
|
+
const Autocomplete = (p) => {
|
|
3385
|
+
const element = React__namespace.useRef(null);
|
|
3386
|
+
const input = React__namespace.useRef(null);
|
|
3387
|
+
const [values, setValues] = React__namespace.useState([]);
|
|
3388
|
+
const showValues = React__namespace.useMemo(() => values.length > 0, [values]);
|
|
3389
|
+
const shownValues = React__namespace.useMemo(() => {
|
|
3390
|
+
var _a;
|
|
3391
|
+
return values.slice(0, (_a = p.maxShownValues) !== null && _a !== void 0 ? _a : DEFAULT_MAX_SHOWN_VALUES);
|
|
3392
|
+
}, [values]);
|
|
3393
|
+
const theme = useThemeSafely();
|
|
3394
|
+
const baseClass = css.css `
|
|
3395
|
+
label: Autocomplete;
|
|
3396
|
+
position: relative;
|
|
3397
|
+
width: 100%;
|
|
3398
|
+
`;
|
|
3399
|
+
const listClass = css.css `
|
|
3400
|
+
position: absolute;
|
|
3401
|
+
width: 100%;
|
|
3402
|
+
border: ${theme.controls.border};
|
|
3403
|
+
box-shadow: ${theme.controls.boxShadow};
|
|
3404
|
+
background-color: ${theme.colors.bg};
|
|
3405
|
+
margin-top: -4px !important;
|
|
3406
|
+
z-index: ${theme.zIndexes.backdrop};
|
|
3407
|
+
${p.round || p.rounded && `
|
|
3408
|
+
border-radius: ${theme.controls.roundedRadius};
|
|
3409
|
+
`}
|
|
3410
|
+
`;
|
|
3411
|
+
const inputClass = css.css `
|
|
3412
|
+
${showValues && `
|
|
3413
|
+
z-index: ${theme.zIndexes.backdrop};
|
|
3414
|
+
position: relative;
|
|
3415
|
+
`}
|
|
3416
|
+
`;
|
|
3417
|
+
return (React__namespace.createElement("div", { ref: element, className: css.cx(baseClass, 'autocomplete') },
|
|
3418
|
+
React__namespace.createElement(Backdrop, { onClick: () => setValues([]), show: showValues, allowScroll: true, transparent: true }),
|
|
3419
|
+
React__namespace.createElement(TabLocker, { disabled: !showValues, style: { position: 'relative' } },
|
|
3420
|
+
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 => {
|
|
3421
|
+
const value = v;
|
|
3422
|
+
p.onChange(value);
|
|
3423
|
+
if (!p.minChars || value.length >= p.minChars) {
|
|
3424
|
+
p.getOptions(value)
|
|
3425
|
+
.then(vals => {
|
|
3426
|
+
setValues(vals);
|
|
3427
|
+
}).catch(err => {
|
|
3428
|
+
// ignore it
|
|
3429
|
+
});
|
|
3430
|
+
}
|
|
3431
|
+
else {
|
|
3432
|
+
setValues([]);
|
|
3433
|
+
}
|
|
3434
|
+
}, onKeyPress: e => { var _a; return (_a = p.onKeyPress) === null || _a === void 0 ? void 0 : _a.call(p, e); } }),
|
|
3435
|
+
showValues && (React__namespace.createElement(List, { className: listClass },
|
|
3436
|
+
shownValues.map(value => {
|
|
3437
|
+
return (React__namespace.createElement(ListItem, { key: getAutocompleteValueId(value), variant: "full" },
|
|
3438
|
+
React__namespace.createElement(Button, { onClick: () => {
|
|
3439
|
+
p.onPick(value);
|
|
3440
|
+
setValues([]);
|
|
3441
|
+
setTimeout(() => {
|
|
3442
|
+
var _a;
|
|
3443
|
+
// we need to wait until the component is re-rendered.
|
|
3444
|
+
// outside changes to Inputs will be ignored if the component has focus.
|
|
3445
|
+
(_a = input.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
3446
|
+
}, 0);
|
|
3447
|
+
} },
|
|
3448
|
+
React__namespace.createElement(Text, { tag: "div", ellipsis: true, align: "left" }, getAutocompleteValueText(value)))));
|
|
3449
|
+
}),
|
|
3450
|
+
shownValues.length < values.length && (React__namespace.createElement(ListItem, null,
|
|
3451
|
+
React__namespace.createElement(Text, { tag: "div", italics: true, align: "center" },
|
|
3452
|
+
"Showing ",
|
|
3453
|
+
shownValues.length.toLocaleString(),
|
|
3454
|
+
" of ",
|
|
3455
|
+
values.length.toLocaleString(),
|
|
3456
|
+
" results."))))))));
|
|
3457
|
+
};
|
|
3458
|
+
|
|
3459
|
+
exports.Autocomplete = Autocomplete;
|
|
3361
3460
|
exports.Backdrop = Backdrop;
|
|
3362
3461
|
exports.Backdrop2 = Backdrop$1;
|
|
3363
3462
|
exports.BoundMemoryPager = BoundMemoryPager;
|