@teambit/react.ui.component-highlighter 0.0.479 → 0.0.483
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/component-highlighter/hover-highlighter/hover-highlighter.spec.tsx +38 -11
- package/component-highlighter/hover-highlighter/hover-highlighter.tsx +18 -15
- package/component-highlighter.docs.md +34 -7
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.d.ts +3 -1
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.js +6 -9
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.js.map +1 -1
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.spec.js +30 -12
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.spec.js.map +1 -1
- package/dist/component-highlighter.docs.md +34 -7
- package/dist/element-highlighter/element-highlighter.compositions.d.ts +9 -3
- package/dist/element-highlighter/element-highlighter.compositions.js +21 -16
- package/dist/element-highlighter/element-highlighter.compositions.js.map +1 -1
- package/dist/element-highlighter/element-highlighter.d.ts +3 -1
- package/dist/element-highlighter/element-highlighter.js +3 -3
- package/dist/element-highlighter/element-highlighter.js.map +1 -1
- package/dist/element-highlighter/element-highlighter.module.scss +7 -0
- package/dist/frame/frame.d.ts +3 -2
- package/dist/frame/frame.js +3 -18
- package/dist/frame/frame.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/label/label.d.ts +3 -1
- package/dist/label/label.js +4 -7
- package/dist/label/label.js.map +1 -1
- package/dist/multi-highlighter/index.d.ts +2 -0
- package/dist/multi-highlighter/index.js +6 -0
- package/dist/multi-highlighter/index.js.map +1 -0
- package/dist/multi-highlighter/multi-highlighter.composition.d.ts +2 -0
- package/dist/multi-highlighter/multi-highlighter.composition.js +36 -0
- package/dist/multi-highlighter/multi-highlighter.composition.js.map +1 -0
- package/dist/multi-highlighter/multi-highlighter.d.ts +15 -0
- package/dist/multi-highlighter/multi-highlighter.js +84 -0
- package/dist/multi-highlighter/multi-highlighter.js.map +1 -0
- package/dist/multi-highlighter/multi-highlighter.spec.d.ts +1 -0
- package/dist/multi-highlighter/multi-highlighter.spec.js +22 -0
- package/dist/multi-highlighter/multi-highlighter.spec.js.map +1 -0
- package/dist/use-animation-frame.d.ts +1 -0
- package/dist/use-animation-frame.js +23 -0
- package/dist/use-animation-frame.js.map +1 -0
- package/element-highlighter/element-highlighter.compositions.tsx +37 -22
- package/element-highlighter/element-highlighter.module.scss +7 -0
- package/element-highlighter/element-highlighter.tsx +14 -2
- package/frame/frame.tsx +6 -21
- package/index.ts +9 -1
- package/label/label.tsx +14 -12
- package/multi-highlighter/index.ts +2 -0
- package/multi-highlighter/multi-highlighter.composition.tsx +41 -0
- package/multi-highlighter/multi-highlighter.spec.tsx +22 -0
- package/multi-highlighter/multi-highlighter.tsx +85 -0
- package/package-tar/teambit-react.ui.component-highlighter-0.0.483.tgz +0 -0
- package/package.json +12 -11
- package/use-animation-frame.tsx +20 -0
- package/component-highlighter/bit-react-component.ts +0 -5
- package/dist/component-highlighter/bit-react-component.d.ts +0 -2
- package/dist/component-highlighter/bit-react-component.js +0 -8
- package/dist/component-highlighter/bit-react-component.js.map +0 -1
- package/package-tar/teambit-react.ui.component-highlighter-0.0.479.tgz +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { act } from 'react-dom/test-utils';
|
|
3
3
|
import { render, fireEvent, waitForElementToBeRemoved } from '@testing-library/react';
|
|
4
|
-
import { ComponentMeta, componentMetaField } from '@teambit/react.
|
|
4
|
+
import { ComponentMeta, componentMetaField } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
5
5
|
|
|
6
6
|
import { HoverHighlighter } from './hover-highlighter';
|
|
7
7
|
|
|
8
|
-
const debounceTime =
|
|
8
|
+
const debounceTime = 2;
|
|
9
9
|
|
|
10
10
|
function ButtonComponent({ children }: { children: ReactNode }) {
|
|
11
11
|
return <button>{children}</button>;
|
|
@@ -30,24 +30,23 @@ it('should show bubble when hovering on element with bit id', async () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
const highlightBubble = await findByText('input/button');
|
|
33
|
-
expect(highlightBubble).
|
|
33
|
+
expect(highlightBubble).toBeInstanceOf(HTMLElement);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('should hide the highlight when hovering out', async () => {
|
|
36
|
+
it('should hide the highlight when hovering out of the element', async () => {
|
|
37
37
|
const { getByText, findByText, queryByText } = render(
|
|
38
38
|
<HoverHighlighter debounceSelection={debounceTime}>
|
|
39
39
|
<ButtonComponent>hover here</ButtonComponent>
|
|
40
40
|
</HoverHighlighter>
|
|
41
41
|
);
|
|
42
42
|
const rendered = getByText('hover here');
|
|
43
|
-
expect(rendered).toBeTruthy();
|
|
44
43
|
|
|
45
44
|
act(() => {
|
|
46
45
|
fireEvent.mouseOver(rendered);
|
|
47
46
|
});
|
|
48
47
|
|
|
49
48
|
const highlightBubble = await findByText('input/button');
|
|
50
|
-
expect(highlightBubble).
|
|
49
|
+
expect(highlightBubble).toBeInstanceOf(HTMLElement);
|
|
51
50
|
|
|
52
51
|
act(() => {
|
|
53
52
|
fireEvent.mouseOut(rendered);
|
|
@@ -55,14 +54,13 @@ it('should hide the highlight when hovering out', async () => {
|
|
|
55
54
|
await waitForElementToBeRemoved(() => queryByText('input/button'));
|
|
56
55
|
});
|
|
57
56
|
|
|
58
|
-
it('should keep the highlighter when hovering on it (even when moving out of the component zone', async () => {
|
|
57
|
+
it('should keep the highlighter, when hovering on it (even when moving out of the component zone)', async () => {
|
|
59
58
|
const { getByText, findByText } = render(
|
|
60
59
|
<HoverHighlighter debounceSelection={debounceTime}>
|
|
61
60
|
<ButtonComponent>hover here</ButtonComponent>
|
|
62
61
|
</HoverHighlighter>
|
|
63
62
|
);
|
|
64
63
|
const rendered = getByText('hover here');
|
|
65
|
-
expect(rendered).toBeTruthy();
|
|
66
64
|
|
|
67
65
|
act(() => {
|
|
68
66
|
// hover on target element:
|
|
@@ -70,19 +68,48 @@ it('should keep the highlighter when hovering on it (even when moving out of the
|
|
|
70
68
|
});
|
|
71
69
|
|
|
72
70
|
const highlightBubble = await findByText('input/button');
|
|
73
|
-
expect(highlightBubble).toBeTruthy();
|
|
74
71
|
|
|
75
72
|
await act(async () => {
|
|
76
73
|
// move mouse out of target element, "towards" the highlighter bubble
|
|
74
|
+
// this should trigger hiding
|
|
77
75
|
fireEvent.mouseOut(rendered);
|
|
78
76
|
|
|
79
77
|
// move mouse into the highlighter bubble
|
|
80
78
|
fireEvent.mouseEnter(highlightBubble);
|
|
81
79
|
// allow react to update state during the act()
|
|
82
|
-
// and before
|
|
80
|
+
// and before verifying highlighter remains
|
|
83
81
|
await new Promise((resolve) => setTimeout(resolve, debounceTime + 10));
|
|
84
82
|
});
|
|
85
83
|
|
|
86
84
|
// highlighter should still focus the target button
|
|
87
|
-
expect(await findByText('input/button')).
|
|
85
|
+
expect(await findByText('input/button')).toBeInstanceOf(HTMLElement);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should hide the highlighter when moving the mouse away of it', async () => {
|
|
89
|
+
const { getByText, queryByText, findByText } = render(
|
|
90
|
+
<HoverHighlighter debounceSelection={debounceTime}>
|
|
91
|
+
<ButtonComponent>hover here</ButtonComponent>
|
|
92
|
+
</HoverHighlighter>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const rendered = getByText('hover here');
|
|
96
|
+
|
|
97
|
+
// hover on target element:
|
|
98
|
+
await act(async () => {
|
|
99
|
+
fireEvent.mouseOver(rendered);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const highlightBubble = await findByText('input/button');
|
|
103
|
+
|
|
104
|
+
await act(async () => {
|
|
105
|
+
// hover on highlighter
|
|
106
|
+
fireEvent.mouseEnter(highlightBubble);
|
|
107
|
+
// leave the highlighter
|
|
108
|
+
fireEvent.mouseOut(highlightBubble);
|
|
109
|
+
await new Promise((resolve) => setTimeout(resolve, debounceTime + 10));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// highlighter sometimes disappears before this check,
|
|
113
|
+
// so not using waitForElementToBeRemoved, and using setTimeout instead
|
|
114
|
+
expect(queryByText('input/button')).toBeNull();
|
|
88
115
|
});
|
|
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
|
|
3
3
|
import { useDebouncedCallback } from 'use-debounce';
|
|
4
4
|
import { domToReact, toRootElement } from '@teambit/react.modules.dom-to-react';
|
|
5
5
|
import { HoverSelector } from '@teambit/react.ui.hover-selector';
|
|
6
|
-
import { hasComponentMeta } from '
|
|
6
|
+
import { hasComponentMeta } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
7
7
|
|
|
8
8
|
import styles from './hover-highlighter.module.scss';
|
|
9
9
|
import { excludeHighlighterSelector } from '../../ignore-highlighter';
|
|
@@ -23,6 +23,8 @@ export interface HoverHighlighterProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
23
23
|
* @default 80ms
|
|
24
24
|
*/
|
|
25
25
|
debounceSelection?: number;
|
|
26
|
+
/** continually update frame position to match moving elements */
|
|
27
|
+
watchMotion?: boolean;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
/** automatically highlight components on hover */
|
|
@@ -33,6 +35,7 @@ export function HoverHighlighter({
|
|
|
33
35
|
highlightStyle,
|
|
34
36
|
placement,
|
|
35
37
|
debounceSelection = 80,
|
|
38
|
+
watchMotion = true,
|
|
36
39
|
...rest
|
|
37
40
|
}: HoverHighlighterProps) {
|
|
38
41
|
const [target, setTarget] = useState<HighlightTarget | undefined>();
|
|
@@ -69,28 +72,28 @@ export function HoverHighlighter({
|
|
|
69
72
|
}, [disabled]);
|
|
70
73
|
|
|
71
74
|
return (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
<HoverSelector
|
|
76
|
+
{...rest}
|
|
77
|
+
className={classnames(styles.highlighter, !disabled && styles.active)}
|
|
78
|
+
onElementChange={handleElement}
|
|
79
|
+
disabled={disabled}
|
|
80
|
+
data-nullify-component-highlight
|
|
81
|
+
>
|
|
82
|
+
{children}
|
|
83
|
+
{/*
|
|
84
|
+
* keep the highlighter inside of the hover selector, or it could disappear when switching between elements
|
|
85
|
+
* the excludeHighlighterAtt will ensure it doesn't turn into a recursion.
|
|
86
|
+
*/}
|
|
82
87
|
{target && (
|
|
83
88
|
<ElementHighlighter
|
|
84
89
|
target={target}
|
|
85
90
|
classes={classes}
|
|
86
91
|
style={highlightStyle}
|
|
87
92
|
placement={placement}
|
|
88
|
-
|
|
89
|
-
// it will be ignored thanks to the excludeHighlighter attribute.
|
|
90
|
-
onMouseEnter={handleElement.cancel}
|
|
93
|
+
watchMotion={watchMotion}
|
|
91
94
|
/>
|
|
92
95
|
)}
|
|
93
|
-
|
|
96
|
+
</HoverSelector>
|
|
94
97
|
);
|
|
95
98
|
}
|
|
96
99
|
|
|
@@ -16,7 +16,7 @@ Simplest way to use the component is by wrapping your code with `HoverHighlighte
|
|
|
16
16
|
It will automatically detect components from DOM elements, just by hovering on them.
|
|
17
17
|
|
|
18
18
|
```tsx
|
|
19
|
-
import {
|
|
19
|
+
import { HoverHighlighter } from '@teambit/react.ui.component-highlighter';
|
|
20
20
|
|
|
21
21
|
function App() {
|
|
22
22
|
return (
|
|
@@ -33,9 +33,7 @@ You can also use it manually, to have more control:
|
|
|
33
33
|
```tsx
|
|
34
34
|
const [element, setElement] = useState<HTMLElement | undefined>(undefined);
|
|
35
35
|
|
|
36
|
-
useEffect(() => setElement(
|
|
37
|
-
document.getElementById('to-highlight')
|
|
38
|
-
), [targetRef.current]);
|
|
36
|
+
useEffect(() => setElement(document.getElementById('to-highlight')), [targetRef.current]);
|
|
39
37
|
|
|
40
38
|
const target = targetElement && {
|
|
41
39
|
element: targetElement,
|
|
@@ -55,22 +53,24 @@ return (
|
|
|
55
53
|
```
|
|
56
54
|
|
|
57
55
|
## How does it work?
|
|
56
|
+
|
|
58
57
|
The manual highlighter works by positioning elements (a frame and a label) to a target element. It uses [PopperJS](https://popper.js.org/) to correctly align them to the element.
|
|
59
58
|
|
|
60
59
|
The automatic highlighter then adds an event listener for hover events, which automatically tracks mouse movements and finds the most relevant React component using [DOM-to-react](https://bit.dev/teambit/react/modules/dom-to-react). It bubbles up the DOM until it finds a component with bit metadata.
|
|
61
60
|
|
|
62
61
|
Where does the metadata come from? The highlighter assumes the code has been transpiled by Bit's [custom babel plugin](https://bit.dev/teambit/react/babel/bit-react-transformer). The plugin looks for React components (i.e. functions or classes), and attaches a metadata object to them.
|
|
62
|
+
|
|
63
63
|
> The `Bit React Transformer` babel plugin is already running in the Preview during `bit start`.
|
|
64
|
-
It only effects the browser bundle, and not the dists.
|
|
64
|
+
> It only effects the browser bundle, and not the dists.
|
|
65
65
|
|
|
66
66
|
The result looks like this:
|
|
67
67
|
|
|
68
68
|
```tsx
|
|
69
69
|
var __bit_component = {
|
|
70
70
|
id: 'teambit.base-ui/button@1.0.0',
|
|
71
|
-
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
71
|
+
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
72
72
|
exported: true,
|
|
73
|
-
}
|
|
73
|
+
};
|
|
74
74
|
|
|
75
75
|
export function Button() {
|
|
76
76
|
return <div>click me!</div>;
|
|
@@ -80,9 +80,36 @@ export function Button() {
|
|
|
80
80
|
Button.__bit_component = __bit_component;
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
### Debounce
|
|
84
|
+
|
|
85
|
+
Normally, moving quickly between elements could produce a jitter effect, where the highlighter "jumps" between elements, making interaction difficult.
|
|
86
|
+
A debounce mitigates this by batching re-targets and smooths out the experience.
|
|
87
|
+
First time selection will always happen immediately, for a snappy experience.
|
|
88
|
+
|
|
89
|
+
You can control the debounce rate with the `debounceSelection` prop. (default - `80ms`)
|
|
90
|
+
|
|
91
|
+
## Multi highlighter
|
|
92
|
+
|
|
93
|
+
This component is similar to the Hover Highlighter, but provides automatic highlighting to all components nested inside it.
|
|
94
|
+
|
|
95
|
+
Simply wrap your code like so, and see the highlighting in action:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { MultiHighlighter } from '@teambit/react.ui.component-highlighter';
|
|
99
|
+
|
|
100
|
+
// ...
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<MultiHighlighter>
|
|
104
|
+
<App />
|
|
105
|
+
</MultiHighlighter>
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
83
109
|
## Customization
|
|
84
110
|
|
|
85
111
|
Use these CSS variables to edit the highlighter color
|
|
112
|
+
|
|
86
113
|
```css
|
|
87
114
|
--bit-highlighter-color: #eebcc9;
|
|
88
115
|
--bit-highlighter-color-hover: #f6dae2;
|
|
@@ -14,6 +14,8 @@ export interface HoverHighlighterProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
14
14
|
* @default 80ms
|
|
15
15
|
*/
|
|
16
16
|
debounceSelection?: number;
|
|
17
|
+
/** continually update frame position to match moving elements */
|
|
18
|
+
watchMotion?: boolean;
|
|
17
19
|
}
|
|
18
20
|
/** automatically highlight components on hover */
|
|
19
|
-
export declare function HoverHighlighter({ children, disabled, classes, highlightStyle, placement, debounceSelection, ...rest }: HoverHighlighterProps): JSX.Element;
|
|
21
|
+
export declare function HoverHighlighter({ children, disabled, classes, highlightStyle, placement, debounceSelection, watchMotion, ...rest }: HoverHighlighterProps): JSX.Element;
|
|
@@ -39,13 +39,13 @@ const classnames_1 = __importDefault(require("classnames"));
|
|
|
39
39
|
const use_debounce_1 = require("use-debounce");
|
|
40
40
|
const react_modules_dom_to_react_1 = require("@teambit/react.modules.dom-to-react");
|
|
41
41
|
const react_ui_hover_selector_1 = require("@teambit/react.ui.hover-selector");
|
|
42
|
-
const
|
|
42
|
+
const react_ui_highlighter_component_metadata_bit_component_meta_1 = require("@teambit/react.ui.highlighter.component-metadata.bit-component-meta");
|
|
43
43
|
const hover_highlighter_module_scss_1 = __importDefault(require("./hover-highlighter.module.scss"));
|
|
44
44
|
const ignore_highlighter_1 = require("../../ignore-highlighter");
|
|
45
45
|
const element_highlighter_1 = require("../../element-highlighter");
|
|
46
46
|
/** automatically highlight components on hover */
|
|
47
47
|
function HoverHighlighter(_a) {
|
|
48
|
-
var { children, disabled, classes, highlightStyle, placement, debounceSelection = 80 } = _a, rest = __rest(_a, ["children", "disabled", "classes", "highlightStyle", "placement", "debounceSelection"]);
|
|
48
|
+
var { children, disabled, classes, highlightStyle, placement, debounceSelection = 80, watchMotion = true } = _a, rest = __rest(_a, ["children", "disabled", "classes", "highlightStyle", "placement", "debounceSelection", "watchMotion"]);
|
|
49
49
|
const [target, setTarget] = (0, react_1.useState)();
|
|
50
50
|
const _handleElement = (0, react_1.useCallback)((element) => {
|
|
51
51
|
// clear highlighter at the edges:
|
|
@@ -74,12 +74,9 @@ function HoverHighlighter(_a) {
|
|
|
74
74
|
setTarget(undefined);
|
|
75
75
|
}
|
|
76
76
|
}, [disabled]);
|
|
77
|
-
return (react_1.default.createElement(
|
|
78
|
-
|
|
79
|
-
target && (react_1.default.createElement(element_highlighter_1.ElementHighlighter, { target: target, classes: classes, style: highlightStyle, placement: placement,
|
|
80
|
-
// could also achieve this by moving the ElementHighlighter into HoverSelector.
|
|
81
|
-
// it will be ignored thanks to the excludeHighlighter attribute.
|
|
82
|
-
onMouseEnter: handleElement.cancel }))));
|
|
77
|
+
return (react_1.default.createElement(react_ui_hover_selector_1.HoverSelector, Object.assign({}, rest, { className: (0, classnames_1.default)(hover_highlighter_module_scss_1.default.highlighter, !disabled && hover_highlighter_module_scss_1.default.active), onElementChange: handleElement, disabled: disabled, "data-nullify-component-highlight": true }),
|
|
78
|
+
children,
|
|
79
|
+
target && (react_1.default.createElement(element_highlighter_1.ElementHighlighter, { target: target, classes: classes, style: highlightStyle, placement: placement, watchMotion: watchMotion }))));
|
|
83
80
|
}
|
|
84
81
|
exports.HoverHighlighter = HoverHighlighter;
|
|
85
82
|
/** go up the dom tree until reaching a react bit component */
|
|
@@ -89,7 +86,7 @@ function bubbleToBitComponent(element, filter) {
|
|
|
89
86
|
if (!current || (filter === null || filter === void 0 ? void 0 : filter(current)) === false)
|
|
90
87
|
return undefined;
|
|
91
88
|
const component = (0, react_modules_dom_to_react_1.domToReact)(current);
|
|
92
|
-
if ((0,
|
|
89
|
+
if ((0, react_ui_highlighter_component_metadata_bit_component_meta_1.hasComponentMeta)(component)) {
|
|
93
90
|
const meta = component.__bit_component;
|
|
94
91
|
return {
|
|
95
92
|
element: current,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-highlighter.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA+E;AAC/E,4DAAoC;AACpC,+CAAoD;AACpD,oFAAgF;AAChF,8EAAiE;AACjE,
|
|
1
|
+
{"version":3,"file":"hover-highlighter.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,13 +15,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const react_1 = __importDefault(require("react"));
|
|
16
16
|
const test_utils_1 = require("react-dom/test-utils");
|
|
17
17
|
const react_2 = require("@testing-library/react");
|
|
18
|
-
const
|
|
18
|
+
const react_ui_highlighter_component_metadata_bit_component_meta_1 = require("@teambit/react.ui.highlighter.component-metadata.bit-component-meta");
|
|
19
19
|
const hover_highlighter_1 = require("./hover-highlighter");
|
|
20
|
-
const debounceTime =
|
|
20
|
+
const debounceTime = 2;
|
|
21
21
|
function ButtonComponent({ children }) {
|
|
22
22
|
return react_1.default.createElement("button", null, children);
|
|
23
23
|
}
|
|
24
|
-
ButtonComponent[
|
|
24
|
+
ButtonComponent[react_ui_highlighter_component_metadata_bit_component_meta_1.componentMetaField] = {
|
|
25
25
|
// could use a non-bit-id to render the "default" bubble
|
|
26
26
|
id: 'teambit.base-ui/input/button',
|
|
27
27
|
};
|
|
@@ -34,44 +34,62 @@ it('should show bubble when hovering on element with bit id', () => __awaiter(vo
|
|
|
34
34
|
react_2.fireEvent.mouseOver(rendered);
|
|
35
35
|
});
|
|
36
36
|
const highlightBubble = yield findByText('input/button');
|
|
37
|
-
expect(highlightBubble).
|
|
37
|
+
expect(highlightBubble).toBeInstanceOf(HTMLElement);
|
|
38
38
|
}));
|
|
39
|
-
it('should hide the highlight when hovering out', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
it('should hide the highlight when hovering out of the element', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
40
|
const { getByText, findByText, queryByText } = (0, react_2.render)(react_1.default.createElement(hover_highlighter_1.HoverHighlighter, { debounceSelection: debounceTime },
|
|
41
41
|
react_1.default.createElement(ButtonComponent, null, "hover here")));
|
|
42
42
|
const rendered = getByText('hover here');
|
|
43
|
-
expect(rendered).toBeTruthy();
|
|
44
43
|
(0, test_utils_1.act)(() => {
|
|
45
44
|
react_2.fireEvent.mouseOver(rendered);
|
|
46
45
|
});
|
|
47
46
|
const highlightBubble = yield findByText('input/button');
|
|
48
|
-
expect(highlightBubble).
|
|
47
|
+
expect(highlightBubble).toBeInstanceOf(HTMLElement);
|
|
49
48
|
(0, test_utils_1.act)(() => {
|
|
50
49
|
react_2.fireEvent.mouseOut(rendered);
|
|
51
50
|
});
|
|
52
51
|
yield (0, react_2.waitForElementToBeRemoved)(() => queryByText('input/button'));
|
|
53
52
|
}));
|
|
54
|
-
it('should keep the highlighter when hovering on it (even when moving out of the component zone', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
it('should keep the highlighter, when hovering on it (even when moving out of the component zone)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
54
|
const { getByText, findByText } = (0, react_2.render)(react_1.default.createElement(hover_highlighter_1.HoverHighlighter, { debounceSelection: debounceTime },
|
|
56
55
|
react_1.default.createElement(ButtonComponent, null, "hover here")));
|
|
57
56
|
const rendered = getByText('hover here');
|
|
58
|
-
expect(rendered).toBeTruthy();
|
|
59
57
|
(0, test_utils_1.act)(() => {
|
|
60
58
|
// hover on target element:
|
|
61
59
|
react_2.fireEvent.mouseOver(rendered);
|
|
62
60
|
});
|
|
63
61
|
const highlightBubble = yield findByText('input/button');
|
|
64
|
-
expect(highlightBubble).toBeTruthy();
|
|
65
62
|
yield (0, test_utils_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
63
|
// move mouse out of target element, "towards" the highlighter bubble
|
|
64
|
+
// this should trigger hiding
|
|
67
65
|
react_2.fireEvent.mouseOut(rendered);
|
|
68
66
|
// move mouse into the highlighter bubble
|
|
69
67
|
react_2.fireEvent.mouseEnter(highlightBubble);
|
|
70
68
|
// allow react to update state during the act()
|
|
71
|
-
// and before
|
|
69
|
+
// and before verifying highlighter remains
|
|
72
70
|
yield new Promise((resolve) => setTimeout(resolve, debounceTime + 10));
|
|
73
71
|
}));
|
|
74
72
|
// highlighter should still focus the target button
|
|
75
|
-
expect(yield findByText('input/button')).
|
|
73
|
+
expect(yield findByText('input/button')).toBeInstanceOf(HTMLElement);
|
|
74
|
+
}));
|
|
75
|
+
it('should hide the highlighter when moving the mouse away of it', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
const { getByText, queryByText, findByText } = (0, react_2.render)(react_1.default.createElement(hover_highlighter_1.HoverHighlighter, { debounceSelection: debounceTime },
|
|
77
|
+
react_1.default.createElement(ButtonComponent, null, "hover here")));
|
|
78
|
+
const rendered = getByText('hover here');
|
|
79
|
+
// hover on target element:
|
|
80
|
+
yield (0, test_utils_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
81
|
+
react_2.fireEvent.mouseOver(rendered);
|
|
82
|
+
}));
|
|
83
|
+
const highlightBubble = yield findByText('input/button');
|
|
84
|
+
yield (0, test_utils_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
+
// hover on highlighter
|
|
86
|
+
react_2.fireEvent.mouseEnter(highlightBubble);
|
|
87
|
+
// leave the highlighter
|
|
88
|
+
react_2.fireEvent.mouseOut(highlightBubble);
|
|
89
|
+
yield new Promise((resolve) => setTimeout(resolve, debounceTime + 10));
|
|
90
|
+
}));
|
|
91
|
+
// highlighter sometimes disappears before this check,
|
|
92
|
+
// so not using waitForElementToBeRemoved, and using setTimeout instead
|
|
93
|
+
expect(queryByText('input/button')).toBeNull();
|
|
76
94
|
}));
|
|
77
95
|
//# sourceMappingURL=hover-highlighter.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-highlighter.spec.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.spec.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,kDAAyC;AACzC,qDAA2C;AAC3C,kDAAsF;AACtF,
|
|
1
|
+
{"version":3,"file":"hover-highlighter.spec.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.spec.tsx"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ Simplest way to use the component is by wrapping your code with `HoverHighlighte
|
|
|
16
16
|
It will automatically detect components from DOM elements, just by hovering on them.
|
|
17
17
|
|
|
18
18
|
```tsx
|
|
19
|
-
import {
|
|
19
|
+
import { HoverHighlighter } from '@teambit/react.ui.component-highlighter';
|
|
20
20
|
|
|
21
21
|
function App() {
|
|
22
22
|
return (
|
|
@@ -33,9 +33,7 @@ You can also use it manually, to have more control:
|
|
|
33
33
|
```tsx
|
|
34
34
|
const [element, setElement] = useState<HTMLElement | undefined>(undefined);
|
|
35
35
|
|
|
36
|
-
useEffect(() => setElement(
|
|
37
|
-
document.getElementById('to-highlight')
|
|
38
|
-
), [targetRef.current]);
|
|
36
|
+
useEffect(() => setElement(document.getElementById('to-highlight')), [targetRef.current]);
|
|
39
37
|
|
|
40
38
|
const target = targetElement && {
|
|
41
39
|
element: targetElement,
|
|
@@ -55,22 +53,24 @@ return (
|
|
|
55
53
|
```
|
|
56
54
|
|
|
57
55
|
## How does it work?
|
|
56
|
+
|
|
58
57
|
The manual highlighter works by positioning elements (a frame and a label) to a target element. It uses [PopperJS](https://popper.js.org/) to correctly align them to the element.
|
|
59
58
|
|
|
60
59
|
The automatic highlighter then adds an event listener for hover events, which automatically tracks mouse movements and finds the most relevant React component using [DOM-to-react](https://bit.dev/teambit/react/modules/dom-to-react). It bubbles up the DOM until it finds a component with bit metadata.
|
|
61
60
|
|
|
62
61
|
Where does the metadata come from? The highlighter assumes the code has been transpiled by Bit's [custom babel plugin](https://bit.dev/teambit/react/babel/bit-react-transformer). The plugin looks for React components (i.e. functions or classes), and attaches a metadata object to them.
|
|
62
|
+
|
|
63
63
|
> The `Bit React Transformer` babel plugin is already running in the Preview during `bit start`.
|
|
64
|
-
It only effects the browser bundle, and not the dists.
|
|
64
|
+
> It only effects the browser bundle, and not the dists.
|
|
65
65
|
|
|
66
66
|
The result looks like this:
|
|
67
67
|
|
|
68
68
|
```tsx
|
|
69
69
|
var __bit_component = {
|
|
70
70
|
id: 'teambit.base-ui/button@1.0.0',
|
|
71
|
-
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
71
|
+
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
72
72
|
exported: true,
|
|
73
|
-
}
|
|
73
|
+
};
|
|
74
74
|
|
|
75
75
|
export function Button() {
|
|
76
76
|
return <div>click me!</div>;
|
|
@@ -80,9 +80,36 @@ export function Button() {
|
|
|
80
80
|
Button.__bit_component = __bit_component;
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
### Debounce
|
|
84
|
+
|
|
85
|
+
Normally, moving quickly between elements could produce a jitter effect, where the highlighter "jumps" between elements, making interaction difficult.
|
|
86
|
+
A debounce mitigates this by batching re-targets and smooths out the experience.
|
|
87
|
+
First time selection will always happen immediately, for a snappy experience.
|
|
88
|
+
|
|
89
|
+
You can control the debounce rate with the `debounceSelection` prop. (default - `80ms`)
|
|
90
|
+
|
|
91
|
+
## Multi highlighter
|
|
92
|
+
|
|
93
|
+
This component is similar to the Hover Highlighter, but provides automatic highlighting to all components nested inside it.
|
|
94
|
+
|
|
95
|
+
Simply wrap your code like so, and see the highlighting in action:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { MultiHighlighter } from '@teambit/react.ui.component-highlighter';
|
|
99
|
+
|
|
100
|
+
// ...
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<MultiHighlighter>
|
|
104
|
+
<App />
|
|
105
|
+
</MultiHighlighter>
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
83
109
|
## Customization
|
|
84
110
|
|
|
85
111
|
Use these CSS variables to edit the highlighter color
|
|
112
|
+
|
|
86
113
|
```css
|
|
87
114
|
--bit-highlighter-color: #eebcc9;
|
|
88
115
|
--bit-highlighter-color-hover: #f6dae2;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
declare type HighlightedElementProps = {
|
|
3
|
+
style?: CSSProperties;
|
|
4
|
+
targetStyle?: CSSProperties;
|
|
3
5
|
className?: string;
|
|
4
|
-
|
|
6
|
+
watchMotion?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare const HighlightedElement: ({ style, targetStyle, watchMotion, className }: HighlightedElementProps) => JSX.Element;
|
|
5
9
|
export declare const Customized: () => JSX.Element;
|
|
6
10
|
export declare const Sizes: () => JSX.Element;
|
|
11
|
+
export declare const MovingElement: () => JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -19,26 +19,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.Sizes = exports.Customized = exports.HighlightedElement = void 0;
|
|
22
|
+
exports.MovingElement = exports.Sizes = exports.Customized = exports.HighlightedElement = void 0;
|
|
23
23
|
const react_1 = __importStar(require("react"));
|
|
24
24
|
const element_highlighter_1 = require("./element-highlighter");
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
const mockTarget = {
|
|
26
|
+
id: 'teambit.design/ui/icon-button',
|
|
27
|
+
link: 'https://bit.dev/teambit/design/ui/icon-button',
|
|
28
|
+
scopeLink: 'https://bit.dev/teambit/design',
|
|
29
|
+
};
|
|
30
|
+
const HighlightedElement = ({ style, targetStyle, watchMotion, className }) => {
|
|
27
31
|
const [targetElement, setTargetElement] = (0, react_1.useState)(undefined);
|
|
28
32
|
const targetRef = (0, react_1.createRef)();
|
|
29
|
-
(0, react_1.useEffect)(() =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
element: targetElement,
|
|
35
|
-
id: mockTargetId,
|
|
36
|
-
link: 'https://bit.dev/teambit/design/ui/icon-button',
|
|
37
|
-
scopeLink: 'https://bit.dev/teambit/design',
|
|
38
|
-
};
|
|
39
|
-
return (react_1.default.createElement("div", { className: className, style: { padding: '16px 160px 50px 16px' } },
|
|
40
|
-
react_1.default.createElement("div", { ref: targetRef, style: { width: 100 } }, "highlight target"),
|
|
41
|
-
target && react_1.default.createElement(element_highlighter_1.ElementHighlighter, { target: target, style: style, placement: "bottom" })));
|
|
33
|
+
(0, react_1.useEffect)(() => setTargetElement(targetRef.current || undefined), [targetRef.current]);
|
|
34
|
+
const target = targetElement && Object.assign(Object.assign({}, mockTarget), { element: targetElement });
|
|
35
|
+
return (react_1.default.createElement("div", { className: className, style: { padding: '16px 16px 50px 16px', width: 300 } },
|
|
36
|
+
react_1.default.createElement("div", { ref: targetRef, style: Object.assign({ width: 100 }, targetStyle) }, "highlight target"),
|
|
37
|
+
target && react_1.default.createElement(element_highlighter_1.ElementHighlighter, { target: target, style: style, watchMotion: watchMotion, placement: "bottom" })));
|
|
42
38
|
};
|
|
43
39
|
exports.HighlightedElement = HighlightedElement;
|
|
44
40
|
const Customized = () => {
|
|
@@ -53,4 +49,13 @@ const Sizes = () => {
|
|
|
53
49
|
return react_1.default.createElement(exports.HighlightedElement, { style: { fontSize: '16px' } });
|
|
54
50
|
};
|
|
55
51
|
exports.Sizes = Sizes;
|
|
52
|
+
const MovingElement = () => {
|
|
53
|
+
const [margin, setMargin] = (0, react_1.useState)(0);
|
|
54
|
+
(0, react_1.useEffect)(() => {
|
|
55
|
+
const intervalId = setInterval(() => setMargin((x) => (x + 1) % 100), 80);
|
|
56
|
+
return () => clearInterval(intervalId);
|
|
57
|
+
}, []);
|
|
58
|
+
return react_1.default.createElement(exports.HighlightedElement, { targetStyle: { marginLeft: margin } });
|
|
59
|
+
};
|
|
60
|
+
exports.MovingElement = MovingElement;
|
|
56
61
|
//# sourceMappingURL=element-highlighter.compositions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-highlighter.compositions.js","sourceRoot":"","sources":["../../element-highlighter/element-highlighter.compositions.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,+
|
|
1
|
+
{"version":3,"file":"element-highlighter.compositions.js","sourceRoot":"","sources":["../../element-highlighter/element-highlighter.compositions.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA6E;AAC7E,+DAA4E;AAE5E,MAAM,UAAU,GAA6B;IAC3C,EAAE,EAAE,+BAA+B;IACnC,IAAI,EAAE,+CAA+C;IACrD,SAAS,EAAE,gCAAgC;CAC5C,CAAC;AASK,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAA2B,EAAE,EAAE;IAC5G,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,IAAA,gBAAQ,EAA0B,SAAS,CAAC,CAAC;IACvF,MAAM,SAAS,GAAG,IAAA,iBAAS,GAAkB,CAAC;IAE9C,IAAA,iBAAS,EAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACvF,MAAM,MAAM,GAAG,aAAa,oCAAS,UAAU,KAAE,OAAO,EAAE,aAAa,GAAE,CAAC;IAE1E,OAAO,CACL,uCAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE;QAC9E,uCAAK,GAAG,EAAE,SAAS,EAAE,KAAK,kBAAI,KAAK,EAAE,GAAG,IAAK,WAAW,wBAElD;QACL,MAAM,IAAI,8BAAC,wCAAkB,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAC,QAAQ,GAAG,CACxG,CACP,CAAC;AACJ,CAAC,CAAC;AAfW,QAAA,kBAAkB,sBAe7B;AAEK,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,CACL,8BAAC,0BAAkB,IACjB,KAAK,EACH;YACE,yBAAyB,EAAE,SAAS;YACpC,+BAA+B,EAAE,SAAS;YAC1C,gCAAgC,EAAE,SAAS;SAC3B,GAEpB,CACH,CAAC;AACJ,CAAC,CAAC;AAZW,QAAA,UAAU,cAYrB;AAEK,MAAM,KAAK,GAAG,GAAG,EAAE;IACxB,OAAO,8BAAC,0BAAkB,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAI,CAAC;AAC7D,CAAC,CAAC;AAFW,QAAA,KAAK,SAEhB;AAEK,MAAM,aAAa,GAAG,GAAG,EAAE;IAChC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IAExC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,8BAAC,0BAAkB,IAAC,WAAW,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,GAAI,CAAC;AACrE,CAAC,CAAC;AATW,QAAA,aAAa,iBASxB"}
|
|
@@ -7,6 +7,8 @@ export interface ElementHighlighterProps extends React.HTMLAttributes<HTMLDivEle
|
|
|
7
7
|
placement?: Placement;
|
|
8
8
|
/** customize styles */
|
|
9
9
|
classes?: HighlightClasses;
|
|
10
|
+
/** continually update highlighter to match moving elements */
|
|
11
|
+
watchMotion?: boolean;
|
|
10
12
|
}
|
|
11
13
|
export { Placement };
|
|
12
14
|
export declare type HighlightTarget = {
|
|
@@ -24,4 +26,4 @@ export declare type HighlightClasses = {
|
|
|
24
26
|
frame?: string;
|
|
25
27
|
label?: string;
|
|
26
28
|
};
|
|
27
|
-
export declare function ElementHighlighter({ target, placement, className, classes, ...props }: ElementHighlighterProps): JSX.Element;
|
|
29
|
+
export declare function ElementHighlighter({ target, placement, watchMotion, className, classes, ...props }: ElementHighlighterProps): JSX.Element;
|
|
@@ -22,10 +22,10 @@ const label_1 = require("../label");
|
|
|
22
22
|
const ignore_highlighter_1 = require("../ignore-highlighter");
|
|
23
23
|
const element_highlighter_module_scss_1 = __importDefault(require("./element-highlighter.module.scss"));
|
|
24
24
|
function ElementHighlighter(_a) {
|
|
25
|
-
var { target, placement = 'top', className, classes } = _a, props = __rest(_a, ["target", "placement", "className", "classes"]);
|
|
25
|
+
var { target, placement = 'top', watchMotion = true, className, classes } = _a, props = __rest(_a, ["target", "placement", "watchMotion", "className", "classes"]);
|
|
26
26
|
return (react_1.default.createElement("div", Object.assign({}, props, ignore_highlighter_1.excludeHighlighterAtt, { className: (0, classnames_1.default)(classes === null || classes === void 0 ? void 0 : classes.container, element_highlighter_module_scss_1.default.container, className) }),
|
|
27
|
-
react_1.default.createElement(frame_1.Frame, { targetRef: target.element, className: classes === null || classes === void 0 ? void 0 : classes.frame }),
|
|
28
|
-
target.id && (react_1.default.createElement(label_1.LabelContainer, { className: element_highlighter_module_scss_1.default.label, targetRef: target.element, placement: placement },
|
|
27
|
+
react_1.default.createElement(frame_1.Frame, { targetRef: target.element, className: (0, classnames_1.default)(element_highlighter_module_scss_1.default.frame, classes === null || classes === void 0 ? void 0 : classes.frame), watchMotion: watchMotion }),
|
|
28
|
+
target.id && (react_1.default.createElement(label_1.LabelContainer, { className: element_highlighter_module_scss_1.default.label, targetRef: target.element, placement: placement, watchMotion: watchMotion },
|
|
29
29
|
react_1.default.createElement(label_1.Label, { componentId: target.id, link: target.link, scopeLink: target.scopeLink, local: target.local, className: classes === null || classes === void 0 ? void 0 : classes.label })))));
|
|
30
30
|
}
|
|
31
31
|
exports.ElementHighlighter = ElementHighlighter;
|