Skip to content
Merged
5 changes: 5 additions & 0 deletions changelogs/upcoming/7496.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Updated `EuiHighlight` to accept an array of `search` strings, which allows highlighting multiple, separate words within its children. This new type and behavior *only* works if `highlightAll` is also set to true.

**Bug fixes**

- Fixed `EuiHighlight` to not parse `search` strings as regexes
33 changes: 20 additions & 13 deletions scripts/eslint-plugin/forward_ref_display_name.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce display name to forwardRef components',
description:
'Enforce display name on components wrapped in forwardRef & memo',
},
},
create: function(context) {
const forwardRefUsages = [];
create: function (context) {
const usagesToCheck = [];
const displayNameUsages = [];
return {
VariableDeclarator(node) {
Expand All @@ -16,14 +17,20 @@ module.exports = {
node.init.callee.type === 'MemberExpression'
) {
if (
node.init.callee.property &&
node.init.callee.property.name === 'forwardRef'
node.init.callee.property?.name === 'forwardRef' ||
node.init.callee.property?.name === 'memo'
) {
forwardRefUsages.push(node.id);
usagesToCheck.push({
id: node.id,
type: node.init.callee.property.name,
});
}
}
if (node.init.callee && node.init.callee.name === 'forwardRef') {
forwardRefUsages.push(node.id);
if (
node.init.callee?.name === 'forwardRef' ||
node.init.callee?.name === 'memo'
) {
usagesToCheck.push({ id: node.id, type: node.init.callee.name });
}
}
},
Expand All @@ -38,19 +45,19 @@ module.exports = {
}
},
'Program:exit'() {
forwardRefUsages.forEach(identifier => {
if (!isDisplayNameUsed(identifier)) {
usagesToCheck.forEach(({ id, type }) => {
if (!isDisplayNameUsed(id)) {
context.report({
node: identifier,
message: 'Forward ref components must use a display name',
node: id,
message: `Components wrapped in React.${type} must set a manual displayName`,
});
}
});
},
};
function isDisplayNameUsed(identifier) {
const node = displayNameUsages.find(
displayName => displayName.name === identifier.name
(displayName) => displayName.name === identifier.name
);
return !!node;
}
Expand Down
15 changes: 14 additions & 1 deletion scripts/eslint-plugin/forward_ref_display_name.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const ruleTester = new RuleTester({
const valid = [
`const Component = React.forwardRef<ref>(() => {})
Component.displayName = "EuiBadgeGroup"
`,
`const Component = React.memo(() => {})
Component.displayName = "EuiHighlight"
`,
];

Expand All @@ -16,7 +19,17 @@ const invalid = [
code: 'const Component = React.forwardRef<ref>(() => {})',
errors: [
{
message: 'Forward ref components must use a display name',
message:
'Components wrapped in React.forwardRef must set a manual displayName',
},
],
},
{
code: 'const Component = React.memo(() => {})',
errors: [
{
message:
'Components wrapped in React.memo must set a manual displayName',
},
],
},
Expand Down
45 changes: 0 additions & 45 deletions src-docs/src/views/highlight_and_mark/highlight.js

This file was deleted.

64 changes: 64 additions & 0 deletions src-docs/src/views/highlight_and_mark/highlight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState, useMemo } from 'react';

import {
EuiHighlight,
EuiFieldSearch,
EuiFormRow,
EuiSpacer,
EuiSwitch,
EuiFlexGroup,
} from '../../../../src/components';

export default () => {
const [searchInput, setSearchInput] = useState('jumped over');
const [isHighlightAll, setHighlightAll] = useState(false);
const [searchMultiple, setSearchMultiple] = useState(false);
const [caseSensitive, setCaseSensitive] = useState(false);

const searchValues = useMemo(() => {
return searchMultiple && isHighlightAll
? searchInput.split(' ')
: searchInput;
}, [searchMultiple, searchInput, isHighlightAll]);

return (
<>
<EuiFlexGroup>
<EuiSwitch
label="Case sensitive"
checked={caseSensitive}
onChange={(e) => setCaseSensitive(e.target.checked)}
/>
<EuiSwitch
label="Highlight all"
checked={isHighlightAll}
onChange={(e) => setHighlightAll(e.target.checked)}
/>
{isHighlightAll && (
<EuiSwitch
label="Search for an array of separate words"
checked={searchMultiple}
onChange={(e) => setSearchMultiple(e.target.checked)}
/>
)}
</EuiFlexGroup>
<EuiSpacer size="xl" />

<EuiFormRow label="Enter text to highlight substrings within a string">
<EuiFieldSearch
value={searchInput}
onChange={(e) => setSearchInput(e.target.value)}
/>
</EuiFormRow>
<EuiSpacer size="m" />

<EuiHighlight
strict={caseSensitive}
highlightAll={isHighlightAll}
search={searchValues}
>
The quick brown fox jumped over the lazy dog
</EuiHighlight>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { Fragment } from 'react';
import React from 'react';

import { EuiMark } from '../../../../src/components';

export default () => {
return (
<Fragment>
<>
The quick brown fox <EuiMark>jumped over</EuiMark> the lazy dog
</Fragment>
</>
);
};
6 changes: 5 additions & 1 deletion src-docs/src/views/highlight_and_mark/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ export const highlightConfig = () => {
value: 'The quick brown fox jumped over the lazy dog',
};

propsToUse.search.value = 'quick';
propsToUse.search = {
...propsToUse.search,
type: PropTypes.String,
value: 'quick',
};

return {
config: {
Expand Down
1 change: 1 addition & 0 deletions src/components/datagrid/body/cell/data_grid_cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ const EuiDataGridCellContent: FunctionComponent<
);
}
);
EuiDataGridCellContent.displayName = 'EuiDataGridCellContent';

export class EuiDataGridCell extends Component<
EuiDataGridCellProps,
Expand Down
80 changes: 6 additions & 74 deletions src/components/highlight/__snapshots__/highlight.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,84 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiHighlight behavior loose matching matches strings with different casing 1`] = `
<span>
different
<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
case
</mark>
match
</span>
`;

exports[`EuiHighlight behavior matching applies to all matches 1`] = `
<span>
<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
match
</mark>

<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
match
</mark>

<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
match
</mark>
</span>
`;

exports[`EuiHighlight behavior matching hasScreenReaderHelpText can be false 1`] = `
<span>
<mark
class="euiMark emotion-euiMark"
>
match
</mark>

<mark
class="euiMark emotion-euiMark"
>
match
</mark>

<mark
class="euiMark emotion-euiMark"
>
match
</mark>
</span>
`;

exports[`EuiHighlight behavior matching only applies to first match 1`] = `
<span>
<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
match
</mark>
match match
</span>
`;

exports[`EuiHighlight behavior strict matching doesn't match strings with different casing 1`] = `
<span>
different case match
</span>
`;

exports[`EuiHighlight is rendered 1`] = `
<span
aria-label="aria-label"
class="testClass1 testClass2 emotion-euiTestCss"
data-test-subj="test subject string"
>
value
<mark
class="euiMark emotion-euiMark-hasScreenReaderHelpText"
>
va
</mark>
lue
</span>
`;
Loading