@jetbrains/ring-ui 5.0.52 → 5.0.54
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/components/date-picker/months.js +3 -4
- package/components/editable-heading/editable-heading.d.ts +1 -1
- package/components/editable-heading/editable-heading.js +22 -13
- package/components/global/fuzzy-highlight.d.ts +6 -0
- package/components/global/fuzzy-highlight.js +24 -10
- package/components/header/services.js +2 -2
- package/components/shortcuts/shortcuts.js +5 -1
- package/dist/date-picker/date-picker.js +0 -1
- package/dist/date-picker/date-popup.js +1 -2
- package/dist/date-picker/months.js +4 -7
- package/dist/editable-heading/editable-heading.d.ts +1 -1
- package/dist/editable-heading/editable-heading.js +27 -16
- package/dist/global/fuzzy-highlight.d.ts +6 -0
- package/dist/global/fuzzy-highlight.js +33 -10
- package/dist/header/services.js +2 -2
- package/dist/shortcuts/shortcuts.js +6 -1
- package/package.json +2 -2
|
@@ -3,8 +3,6 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import addMonths from 'date-fns/addMonths';
|
|
4
4
|
import getDay from 'date-fns/getDay';
|
|
5
5
|
import getDaysInMonth from 'date-fns/getDaysInMonth';
|
|
6
|
-
import set from 'date-fns/set';
|
|
7
|
-
import startOfHour from 'date-fns/startOfHour';
|
|
8
6
|
import startOfMonth from 'date-fns/startOfMonth';
|
|
9
7
|
import subMonths from 'date-fns/subMonths';
|
|
10
8
|
import endOfMonth from 'date-fns/endOfMonth';
|
|
@@ -37,8 +35,9 @@ const scrollSchedule = scheduleRAF();
|
|
|
37
35
|
let dy = 0;
|
|
38
36
|
export default function Months(props) {
|
|
39
37
|
const { scrollDate } = props;
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
const monthDate = scrollDate instanceof Date ? scrollDate : new Date(scrollDate);
|
|
39
|
+
// Creating midnight of the first day of the month in UTC to prevent the impact of user timezone
|
|
40
|
+
const monthStart = new Date(Date.UTC(monthDate.getFullYear(), monthDate.getMonth(), 1));
|
|
42
41
|
let month = subMonths(monthStart, MONTHSBACK);
|
|
43
42
|
const months = [month];
|
|
44
43
|
for (let i = 0; i < MONTHSBACK * DOUBLE; i++) {
|
|
@@ -2,6 +2,7 @@ import React, { InputHTMLAttributes } from 'react';
|
|
|
2
2
|
import { Levels } from '../heading/heading';
|
|
3
3
|
import { Size } from '../input/input';
|
|
4
4
|
export { Levels };
|
|
5
|
+
export { Size };
|
|
5
6
|
export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'size'> & {
|
|
6
7
|
level?: Levels;
|
|
7
8
|
headingClassName?: string | null;
|
|
@@ -19,7 +20,6 @@ export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputEle
|
|
|
19
20
|
error?: string;
|
|
20
21
|
renderMenu?: () => React.ReactNode;
|
|
21
22
|
};
|
|
22
|
-
export { Size } from '../input/input';
|
|
23
23
|
export declare const EditableHeading: (props: EditableHeadingProps) => JSX.Element;
|
|
24
24
|
declare const _default: React.MemoExoticComponent<(props: EditableHeadingProps) => JSX.Element>;
|
|
25
25
|
export default _default;
|
|
@@ -8,12 +8,20 @@ import getUID from '../global/get-uid';
|
|
|
8
8
|
import Shortcuts from '../shortcuts/shortcuts';
|
|
9
9
|
import styles from './editable-heading.css';
|
|
10
10
|
export { Levels };
|
|
11
|
+
export { Size };
|
|
11
12
|
function noop() { }
|
|
12
|
-
const shortcutsScope = getUID('ring-editable-heading-');
|
|
13
|
-
export { Size } from '../input/input';
|
|
14
13
|
export const EditableHeading = (props) => {
|
|
15
|
-
const { level = Levels.H1, className, headingClassName, inputClassName, isEditing, isSavingPossible, isSaving
|
|
14
|
+
const { level = Levels.H1, className, headingClassName, inputClassName, children, isEditing = false, isSavingPossible = false, isSaving = false, embedded = false, size = Size.L, onEdit = noop, onSave = noop, onCancel = noop, autoFocus = true, 'data-test': dataTest, error, disabled, renderMenu = () => null, ...restProps } = props;
|
|
15
|
+
const [shortcutsScope] = React.useState(getUID('ring-editable-heading-'));
|
|
16
|
+
const [isInFocus, setIsInFocus] = React.useState(false);
|
|
16
17
|
const hasError = error !== undefined;
|
|
18
|
+
const isSaveDisabled = !isSavingPossible || !children || children.trim() === '' || hasError || isSaving;
|
|
19
|
+
const isCancelDisabled = isSaving;
|
|
20
|
+
const isShortcutsDisabled = !isInFocus || isSaving;
|
|
21
|
+
const shortcutsMap = React.useMemo(() => ({
|
|
22
|
+
enter: isSaveDisabled ? noop : onSave,
|
|
23
|
+
esc: isCancelDisabled ? noop : onCancel
|
|
24
|
+
}), [isSaveDisabled, isCancelDisabled, onSave, onCancel]);
|
|
17
25
|
const classes = classNames(styles.editableHeading, className, {
|
|
18
26
|
[styles.fullSize]: size === Size.FULL,
|
|
19
27
|
[styles.isEditing]: isEditing,
|
|
@@ -22,26 +30,27 @@ export const EditableHeading = (props) => {
|
|
|
22
30
|
});
|
|
23
31
|
const headingClasses = classNames(styles.heading, headingClassName);
|
|
24
32
|
const inputClasses = classNames('ring-js-shortcuts', styles.input, inputStyles[`size${size}`], styles[`level${level}`], inputClassName);
|
|
25
|
-
const
|
|
26
|
-
if (disabled
|
|
33
|
+
const onHeadingClick = React.useCallback(() => {
|
|
34
|
+
if (disabled) {
|
|
27
35
|
return undefined;
|
|
28
36
|
}
|
|
29
37
|
return onEdit();
|
|
30
38
|
}, [disabled, onEdit]);
|
|
31
|
-
const
|
|
32
|
-
|
|
39
|
+
const onInputFocus = React.useCallback(() => {
|
|
40
|
+
setIsInFocus(true);
|
|
41
|
+
}, []);
|
|
42
|
+
const onInputBlur = React.useCallback(() => {
|
|
43
|
+
setIsInFocus(false);
|
|
44
|
+
}, []);
|
|
33
45
|
return (<>
|
|
34
46
|
<div className={classes}>
|
|
35
47
|
{!disabled && isEditing
|
|
36
48
|
? (<>
|
|
37
|
-
<Shortcuts map={{
|
|
38
|
-
enter: () => !isSaveDisabled && onSave(),
|
|
39
|
-
esc: () => !isCancelDisabled && onCancel()
|
|
40
|
-
}} scope={shortcutsScope} disabled={isSaving}/>
|
|
49
|
+
<Shortcuts map={shortcutsMap} scope={shortcutsScope} disabled={isShortcutsDisabled}/>
|
|
41
50
|
|
|
42
|
-
<input className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} {...restProps}/>
|
|
51
|
+
<input className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} onFocus={onInputFocus} onBlur={onInputBlur} {...restProps}/>
|
|
43
52
|
</>)
|
|
44
|
-
: (<Heading className={headingClasses} level={level} onClick={
|
|
53
|
+
: (<Heading className={headingClasses} level={level} onClick={onHeadingClick} data-test={dataTest}>{children}</Heading>)}
|
|
45
54
|
|
|
46
55
|
{!isEditing && (renderMenu())}
|
|
47
56
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** https://github.com/bevacqua/fuzzysearch + highlighting with Markdown */
|
|
2
|
+
declare type Match = {
|
|
3
|
+
from: number;
|
|
4
|
+
to: number;
|
|
5
|
+
};
|
|
2
6
|
export default function fuzzyHighlight(needle: string, haystack: string, caseSensitive?: boolean): {
|
|
3
7
|
matched: boolean;
|
|
8
|
+
matches: Match[];
|
|
4
9
|
highlight: string;
|
|
5
10
|
};
|
|
11
|
+
export {};
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/** https://github.com/bevacqua/fuzzysearch + highlighting with Markdown */
|
|
2
|
-
const marker = '**';
|
|
3
2
|
export default function fuzzyHighlight(needle, haystack, caseSensitive = false) {
|
|
4
3
|
const ndl = caseSensitive ? needle : needle.toLowerCase();
|
|
5
4
|
const hstck = caseSensitive ? haystack : haystack.toLowerCase();
|
|
6
|
-
const result = (matched,
|
|
5
|
+
const result = (matched, matches = []) => {
|
|
6
|
+
let highlight = haystack;
|
|
7
|
+
if (matches.length > 0) {
|
|
8
|
+
highlight = '';
|
|
9
|
+
let prevMatch = { to: 0 };
|
|
10
|
+
for (const match of matches) {
|
|
11
|
+
highlight += `${haystack.slice(prevMatch.to, match.from)}**${haystack.slice(match.from, match.to)}**`;
|
|
12
|
+
prevMatch = match;
|
|
13
|
+
}
|
|
14
|
+
highlight += haystack.slice(prevMatch.to);
|
|
15
|
+
}
|
|
16
|
+
return ({ matched, matches, highlight });
|
|
17
|
+
};
|
|
7
18
|
const hlen = hstck.length;
|
|
8
19
|
const nlen = ndl.length;
|
|
9
20
|
if (nlen > hlen) {
|
|
@@ -11,11 +22,12 @@ export default function fuzzyHighlight(needle, haystack, caseSensitive = false)
|
|
|
11
22
|
}
|
|
12
23
|
if (nlen === hlen) {
|
|
13
24
|
const matched = ndl === hstck;
|
|
14
|
-
return result(matched, matched ?
|
|
25
|
+
return result(matched, matched ? [{ from: 0, to: haystack.length }] : []);
|
|
15
26
|
}
|
|
16
|
-
let highlight = '';
|
|
17
27
|
let on = false;
|
|
18
28
|
let j = 0;
|
|
29
|
+
const matches = [];
|
|
30
|
+
let from = 0;
|
|
19
31
|
/* eslint-disable no-labels */
|
|
20
32
|
outer: for (let i = 0; i < nlen; i++) {
|
|
21
33
|
const nch = ndl[i];
|
|
@@ -24,10 +36,13 @@ export default function fuzzyHighlight(needle, haystack, caseSensitive = false)
|
|
|
24
36
|
const match = hch === nch;
|
|
25
37
|
// Don't turn highlight on for space characters
|
|
26
38
|
const nextOn = match && /\S/.test(hch);
|
|
27
|
-
if (nextOn
|
|
28
|
-
|
|
39
|
+
if (nextOn && !on) {
|
|
40
|
+
from = j;
|
|
41
|
+
}
|
|
42
|
+
else if (!nextOn && on) {
|
|
43
|
+
matches.push({ from, to: j });
|
|
29
44
|
}
|
|
30
|
-
|
|
45
|
+
j++;
|
|
31
46
|
on = nextOn;
|
|
32
47
|
if (match) {
|
|
33
48
|
continue outer;
|
|
@@ -37,8 +52,7 @@ export default function fuzzyHighlight(needle, haystack, caseSensitive = false)
|
|
|
37
52
|
}
|
|
38
53
|
/* eslint-enable */
|
|
39
54
|
if (on) {
|
|
40
|
-
|
|
55
|
+
matches.push({ from, to: j });
|
|
41
56
|
}
|
|
42
|
-
|
|
43
|
-
return result(true, highlight);
|
|
57
|
+
return result(true, matches);
|
|
44
58
|
}
|
|
@@ -42,8 +42,8 @@ export default class Services extends PureComponent {
|
|
|
42
42
|
return (<TrayIcon {...props} loader={loading} active={loading} icon={servicesIcon} aria-label="Services"/>);
|
|
43
43
|
}
|
|
44
44
|
const sortedServices = [...services].sort(Services.sort);
|
|
45
|
-
const servicesWithIcons = sortedServices.filter(service => service.iconUrl);
|
|
46
|
-
const servicesWithOutIcons = sortedServices.filter(service => !service.iconUrl);
|
|
45
|
+
const servicesWithIcons = sortedServices.filter(service => service.iconUrl && service.homeUrl);
|
|
46
|
+
const servicesWithOutIcons = sortedServices.filter(service => !service.iconUrl && service.homeUrl);
|
|
47
47
|
const separatorIsRequired = servicesWithIcons.length !== 0 && servicesWithOutIcons.length !== 0;
|
|
48
48
|
return (<Dropdown {...props} anchor={makeAnchor(loading)} initShown={initShown}>
|
|
49
49
|
<Popup className={classNames(styles.services, { [darkStyles.dark]: theme === Theme.DARK })} top={-3}>
|
|
@@ -18,13 +18,17 @@ export default class Shortcuts extends PureComponent {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
componentDidUpdate(prevProps) {
|
|
21
|
-
const { disabled } = this.props;
|
|
21
|
+
const { disabled, map } = this.props;
|
|
22
22
|
if (!prevProps.disabled && disabled) {
|
|
23
23
|
this.turnShorcutsOff();
|
|
24
24
|
}
|
|
25
25
|
if (prevProps.disabled && !disabled) {
|
|
26
26
|
this.turnShorcutsOn();
|
|
27
27
|
}
|
|
28
|
+
if (prevProps.map !== map) {
|
|
29
|
+
this.turnShorcutsOff();
|
|
30
|
+
this.turnShorcutsOn();
|
|
31
|
+
}
|
|
28
32
|
}
|
|
29
33
|
componentWillUnmount() {
|
|
30
34
|
if (!this.props.disabled) {
|
|
@@ -35,8 +35,6 @@ import 'date-fns/add';
|
|
|
35
35
|
import 'date-fns/addMonths';
|
|
36
36
|
import 'date-fns/getDay';
|
|
37
37
|
import 'date-fns/getDaysInMonth';
|
|
38
|
-
import 'date-fns/set';
|
|
39
|
-
import 'date-fns/startOfHour';
|
|
40
38
|
import 'date-fns/startOfMonth';
|
|
41
39
|
import 'date-fns/subMonths';
|
|
42
40
|
import 'date-fns/endOfMonth';
|
|
@@ -51,6 +49,7 @@ import 'date-fns/getDate';
|
|
|
51
49
|
import 'date-fns/isToday';
|
|
52
50
|
import './month-names.js';
|
|
53
51
|
import 'date-fns/isThisMonth';
|
|
52
|
+
import 'date-fns/set';
|
|
54
53
|
import 'date-fns/startOfYear';
|
|
55
54
|
import './month-slider.js';
|
|
56
55
|
import 'date-fns/addYears';
|
|
@@ -4,8 +4,6 @@ import PropTypes from 'prop-types';
|
|
|
4
4
|
import addMonths from 'date-fns/addMonths';
|
|
5
5
|
import getDay from 'date-fns/getDay';
|
|
6
6
|
import getDaysInMonth from 'date-fns/getDaysInMonth';
|
|
7
|
-
import set from 'date-fns/set';
|
|
8
|
-
import startOfHour from 'date-fns/startOfHour';
|
|
9
7
|
import startOfMonth from 'date-fns/startOfMonth';
|
|
10
8
|
import subMonths from 'date-fns/subMonths';
|
|
11
9
|
import endOfMonth from 'date-fns/endOfMonth';
|
|
@@ -27,6 +25,7 @@ import 'date-fns/isSameDay';
|
|
|
27
25
|
import 'date-fns/isToday';
|
|
28
26
|
import 'date-fns/startOfDay';
|
|
29
27
|
import 'date-fns/isThisMonth';
|
|
28
|
+
import 'date-fns/set';
|
|
30
29
|
import 'date-fns/startOfYear';
|
|
31
30
|
import './month-slider.js';
|
|
32
31
|
import 'date-fns/addYears';
|
|
@@ -62,11 +61,9 @@ function Months(props) {
|
|
|
62
61
|
const {
|
|
63
62
|
scrollDate
|
|
64
63
|
} = props;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
hours: 1
|
|
69
|
-
}));
|
|
64
|
+
const monthDate = scrollDate instanceof Date ? scrollDate : new Date(scrollDate);
|
|
65
|
+
// Creating midnight of the first day of the month in UTC to prevent the impact of user timezone
|
|
66
|
+
const monthStart = new Date(Date.UTC(monthDate.getFullYear(), monthDate.getMonth(), 1));
|
|
70
67
|
let month = subMonths(monthStart, MONTHSBACK);
|
|
71
68
|
const months = [month];
|
|
72
69
|
for (let i = 0; i < MONTHSBACK * DOUBLE; i++) {
|
|
@@ -2,6 +2,7 @@ import React, { InputHTMLAttributes } from 'react';
|
|
|
2
2
|
import { Levels } from '../heading/heading';
|
|
3
3
|
import { Size } from '../input/input';
|
|
4
4
|
export { Levels };
|
|
5
|
+
export { Size };
|
|
5
6
|
export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'size'> & {
|
|
6
7
|
level?: Levels;
|
|
7
8
|
headingClassName?: string | null;
|
|
@@ -19,7 +20,6 @@ export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputEle
|
|
|
19
20
|
error?: string;
|
|
20
21
|
renderMenu?: () => React.ReactNode;
|
|
21
22
|
};
|
|
22
|
-
export { Size } from '../input/input';
|
|
23
23
|
export declare const EditableHeading: (props: EditableHeadingProps) => JSX.Element;
|
|
24
24
|
declare const _default: React.MemoExoticComponent<(props: EditableHeadingProps) => JSX.Element>;
|
|
25
25
|
export default _default;
|
|
@@ -33,20 +33,19 @@ import 'sniffr';
|
|
|
33
33
|
var modules_6e69b0fe = {"unit":"8px","editableHeading":"editableHeading_rui_0870","fullSize":"fullSize_rui_0870","isEditing":"isEditing_rui_0870","heading":"heading_rui_0870","disabled":"disabled_rui_0870","input":"input_rui_0870","error":"error_rui_0870","button":"button_rui_0870","errorText":"errorText_rui_0870","level1":"level1_rui_0870","level2":"level2_rui_0870","level3":"level3_rui_0870"};
|
|
34
34
|
|
|
35
35
|
function noop() {}
|
|
36
|
-
const shortcutsScope = getUID('ring-editable-heading-');
|
|
37
36
|
const EditableHeading = props => {
|
|
38
37
|
const {
|
|
39
38
|
level = Levels.H1,
|
|
40
39
|
className,
|
|
41
40
|
headingClassName,
|
|
42
41
|
inputClassName,
|
|
43
|
-
isEditing,
|
|
44
|
-
isSavingPossible,
|
|
45
|
-
isSaving,
|
|
46
42
|
children,
|
|
43
|
+
isEditing = false,
|
|
44
|
+
isSavingPossible = false,
|
|
45
|
+
isSaving = false,
|
|
47
46
|
embedded = false,
|
|
48
47
|
size = Size.L,
|
|
49
|
-
onEdit,
|
|
48
|
+
onEdit = noop,
|
|
50
49
|
onSave = noop,
|
|
51
50
|
onCancel = noop,
|
|
52
51
|
autoFocus = true,
|
|
@@ -56,7 +55,16 @@ const EditableHeading = props => {
|
|
|
56
55
|
renderMenu = () => null,
|
|
57
56
|
...restProps
|
|
58
57
|
} = props;
|
|
58
|
+
const [shortcutsScope] = React.useState(getUID('ring-editable-heading-'));
|
|
59
|
+
const [isInFocus, setIsInFocus] = React.useState(false);
|
|
59
60
|
const hasError = error !== undefined;
|
|
61
|
+
const isSaveDisabled = !isSavingPossible || !children || children.trim() === '' || hasError || isSaving;
|
|
62
|
+
const isCancelDisabled = isSaving;
|
|
63
|
+
const isShortcutsDisabled = !isInFocus || isSaving;
|
|
64
|
+
const shortcutsMap = React.useMemo(() => ({
|
|
65
|
+
enter: isSaveDisabled ? noop : onSave,
|
|
66
|
+
esc: isCancelDisabled ? noop : onCancel
|
|
67
|
+
}), [isSaveDisabled, isCancelDisabled, onSave, onCancel]);
|
|
60
68
|
const classes = classNames(modules_6e69b0fe.editableHeading, className, {
|
|
61
69
|
[modules_6e69b0fe.fullSize]: size === Size.FULL,
|
|
62
70
|
[modules_6e69b0fe.isEditing]: isEditing,
|
|
@@ -65,33 +73,36 @@ const EditableHeading = props => {
|
|
|
65
73
|
});
|
|
66
74
|
const headingClasses = classNames(modules_6e69b0fe.heading, headingClassName);
|
|
67
75
|
const inputClasses = classNames('ring-js-shortcuts', modules_6e69b0fe.input, modules_88cfaf40[`size${size}`], modules_6e69b0fe[`level${level}`], inputClassName);
|
|
68
|
-
const
|
|
69
|
-
if (disabled
|
|
76
|
+
const onHeadingClick = React.useCallback(() => {
|
|
77
|
+
if (disabled) {
|
|
70
78
|
return undefined;
|
|
71
79
|
}
|
|
72
80
|
return onEdit();
|
|
73
81
|
}, [disabled, onEdit]);
|
|
74
|
-
const
|
|
75
|
-
|
|
82
|
+
const onInputFocus = React.useCallback(() => {
|
|
83
|
+
setIsInFocus(true);
|
|
84
|
+
}, []);
|
|
85
|
+
const onInputBlur = React.useCallback(() => {
|
|
86
|
+
setIsInFocus(false);
|
|
87
|
+
}, []);
|
|
76
88
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
77
89
|
className: classes
|
|
78
90
|
}, !disabled && isEditing ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Shortcuts, {
|
|
79
|
-
map:
|
|
80
|
-
enter: () => !isSaveDisabled && onSave(),
|
|
81
|
-
esc: () => !isCancelDisabled && onCancel()
|
|
82
|
-
},
|
|
91
|
+
map: shortcutsMap,
|
|
83
92
|
scope: shortcutsScope,
|
|
84
|
-
disabled:
|
|
93
|
+
disabled: isShortcutsDisabled
|
|
85
94
|
}), /*#__PURE__*/React.createElement("input", _extends({
|
|
86
95
|
className: inputClasses,
|
|
87
96
|
value: children,
|
|
88
97
|
autoFocus: autoFocus,
|
|
89
98
|
"data-test": dataTest,
|
|
90
|
-
disabled: isSaving
|
|
99
|
+
disabled: isSaving,
|
|
100
|
+
onFocus: onInputFocus,
|
|
101
|
+
onBlur: onInputBlur
|
|
91
102
|
}, restProps))) : /*#__PURE__*/React.createElement(Heading, {
|
|
92
103
|
className: headingClasses,
|
|
93
104
|
level: level,
|
|
94
|
-
onClick:
|
|
105
|
+
onClick: onHeadingClick,
|
|
95
106
|
"data-test": dataTest
|
|
96
107
|
}, children), !isEditing && renderMenu(), isEditing && !embedded && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
97
108
|
className: modules_6e69b0fe.button,
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** https://github.com/bevacqua/fuzzysearch + highlighting with Markdown */
|
|
2
|
+
declare type Match = {
|
|
3
|
+
from: number;
|
|
4
|
+
to: number;
|
|
5
|
+
};
|
|
2
6
|
export default function fuzzyHighlight(needle: string, haystack: string, caseSensitive?: boolean): {
|
|
3
7
|
matched: boolean;
|
|
8
|
+
matches: Match[];
|
|
4
9
|
highlight: string;
|
|
5
10
|
};
|
|
11
|
+
export {};
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
/** https://github.com/bevacqua/fuzzysearch + highlighting with Markdown */
|
|
2
|
-
const marker = '**';
|
|
3
2
|
function fuzzyHighlight(needle, haystack) {
|
|
4
3
|
let caseSensitive = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
5
4
|
const ndl = caseSensitive ? needle : needle.toLowerCase();
|
|
6
5
|
const hstck = caseSensitive ? haystack : haystack.toLowerCase();
|
|
7
6
|
const result = function (matched) {
|
|
8
|
-
let
|
|
7
|
+
let matches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
8
|
+
let highlight = haystack;
|
|
9
|
+
if (matches.length > 0) {
|
|
10
|
+
highlight = '';
|
|
11
|
+
let prevMatch = {
|
|
12
|
+
to: 0
|
|
13
|
+
};
|
|
14
|
+
for (const match of matches) {
|
|
15
|
+
highlight += `${haystack.slice(prevMatch.to, match.from)}**${haystack.slice(match.from, match.to)}**`;
|
|
16
|
+
prevMatch = match;
|
|
17
|
+
}
|
|
18
|
+
highlight += haystack.slice(prevMatch.to);
|
|
19
|
+
}
|
|
9
20
|
return {
|
|
10
21
|
matched,
|
|
22
|
+
matches,
|
|
11
23
|
highlight
|
|
12
24
|
};
|
|
13
25
|
};
|
|
@@ -18,11 +30,15 @@ function fuzzyHighlight(needle, haystack) {
|
|
|
18
30
|
}
|
|
19
31
|
if (nlen === hlen) {
|
|
20
32
|
const matched = ndl === hstck;
|
|
21
|
-
return result(matched, matched ?
|
|
33
|
+
return result(matched, matched ? [{
|
|
34
|
+
from: 0,
|
|
35
|
+
to: haystack.length
|
|
36
|
+
}] : []);
|
|
22
37
|
}
|
|
23
|
-
let highlight = '';
|
|
24
38
|
let on = false;
|
|
25
39
|
let j = 0;
|
|
40
|
+
const matches = [];
|
|
41
|
+
let from = 0;
|
|
26
42
|
/* eslint-disable no-labels */
|
|
27
43
|
outer: for (let i = 0; i < nlen; i++) {
|
|
28
44
|
const nch = ndl[i];
|
|
@@ -31,10 +47,15 @@ function fuzzyHighlight(needle, haystack) {
|
|
|
31
47
|
const match = hch === nch;
|
|
32
48
|
// Don't turn highlight on for space characters
|
|
33
49
|
const nextOn = match && /\S/.test(hch);
|
|
34
|
-
if (nextOn
|
|
35
|
-
|
|
50
|
+
if (nextOn && !on) {
|
|
51
|
+
from = j;
|
|
52
|
+
} else if (!nextOn && on) {
|
|
53
|
+
matches.push({
|
|
54
|
+
from,
|
|
55
|
+
to: j
|
|
56
|
+
});
|
|
36
57
|
}
|
|
37
|
-
|
|
58
|
+
j++;
|
|
38
59
|
on = nextOn;
|
|
39
60
|
if (match) {
|
|
40
61
|
continue outer;
|
|
@@ -44,10 +65,12 @@ function fuzzyHighlight(needle, haystack) {
|
|
|
44
65
|
}
|
|
45
66
|
/* eslint-enable */
|
|
46
67
|
if (on) {
|
|
47
|
-
|
|
68
|
+
matches.push({
|
|
69
|
+
from,
|
|
70
|
+
to: j
|
|
71
|
+
});
|
|
48
72
|
}
|
|
49
|
-
|
|
50
|
-
return result(true, highlight);
|
|
73
|
+
return result(true, matches);
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
export { fuzzyHighlight as default };
|
package/dist/header/services.js
CHANGED
|
@@ -80,8 +80,8 @@ class Services extends PureComponent {
|
|
|
80
80
|
}));
|
|
81
81
|
}
|
|
82
82
|
const sortedServices = [...services].sort(Services.sort);
|
|
83
|
-
const servicesWithIcons = sortedServices.filter(service => service.iconUrl);
|
|
84
|
-
const servicesWithOutIcons = sortedServices.filter(service => !service.iconUrl);
|
|
83
|
+
const servicesWithIcons = sortedServices.filter(service => service.iconUrl && service.homeUrl);
|
|
84
|
+
const servicesWithOutIcons = sortedServices.filter(service => !service.iconUrl && service.homeUrl);
|
|
85
85
|
const separatorIsRequired = servicesWithIcons.length !== 0 && servicesWithOutIcons.length !== 0;
|
|
86
86
|
return /*#__PURE__*/React.createElement(Dropdown, _extends({}, props, {
|
|
87
87
|
anchor: makeAnchor(loading),
|
|
@@ -14,7 +14,8 @@ class Shortcuts extends PureComponent {
|
|
|
14
14
|
}
|
|
15
15
|
componentDidUpdate(prevProps) {
|
|
16
16
|
const {
|
|
17
|
-
disabled
|
|
17
|
+
disabled,
|
|
18
|
+
map
|
|
18
19
|
} = this.props;
|
|
19
20
|
if (!prevProps.disabled && disabled) {
|
|
20
21
|
this.turnShorcutsOff();
|
|
@@ -22,6 +23,10 @@ class Shortcuts extends PureComponent {
|
|
|
22
23
|
if (prevProps.disabled && !disabled) {
|
|
23
24
|
this.turnShorcutsOn();
|
|
24
25
|
}
|
|
26
|
+
if (prevProps.map !== map) {
|
|
27
|
+
this.turnShorcutsOff();
|
|
28
|
+
this.turnShorcutsOn();
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
31
|
componentWillUnmount() {
|
|
27
32
|
if (!this.props.disabled) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.54",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": "JetBrains",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -259,5 +259,5 @@
|
|
|
259
259
|
"node": ">=14.0",
|
|
260
260
|
"npm": ">=6.0.0"
|
|
261
261
|
},
|
|
262
|
-
"gitHead": "
|
|
262
|
+
"gitHead": "738bf4ba27a6a7ac082c070a845f7b992f87c350"
|
|
263
263
|
}
|