@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.
Files changed (58) hide show
  1. package/component-highlighter/hover-highlighter/hover-highlighter.spec.tsx +38 -11
  2. package/component-highlighter/hover-highlighter/hover-highlighter.tsx +18 -15
  3. package/component-highlighter.docs.md +34 -7
  4. package/dist/component-highlighter/hover-highlighter/hover-highlighter.d.ts +3 -1
  5. package/dist/component-highlighter/hover-highlighter/hover-highlighter.js +6 -9
  6. package/dist/component-highlighter/hover-highlighter/hover-highlighter.js.map +1 -1
  7. package/dist/component-highlighter/hover-highlighter/hover-highlighter.spec.js +30 -12
  8. package/dist/component-highlighter/hover-highlighter/hover-highlighter.spec.js.map +1 -1
  9. package/dist/component-highlighter.docs.md +34 -7
  10. package/dist/element-highlighter/element-highlighter.compositions.d.ts +9 -3
  11. package/dist/element-highlighter/element-highlighter.compositions.js +21 -16
  12. package/dist/element-highlighter/element-highlighter.compositions.js.map +1 -1
  13. package/dist/element-highlighter/element-highlighter.d.ts +3 -1
  14. package/dist/element-highlighter/element-highlighter.js +3 -3
  15. package/dist/element-highlighter/element-highlighter.js.map +1 -1
  16. package/dist/element-highlighter/element-highlighter.module.scss +7 -0
  17. package/dist/frame/frame.d.ts +3 -2
  18. package/dist/frame/frame.js +3 -18
  19. package/dist/frame/frame.js.map +1 -1
  20. package/dist/index.d.ts +3 -1
  21. package/dist/index.js +5 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/label/label.d.ts +3 -1
  24. package/dist/label/label.js +4 -7
  25. package/dist/label/label.js.map +1 -1
  26. package/dist/multi-highlighter/index.d.ts +2 -0
  27. package/dist/multi-highlighter/index.js +6 -0
  28. package/dist/multi-highlighter/index.js.map +1 -0
  29. package/dist/multi-highlighter/multi-highlighter.composition.d.ts +2 -0
  30. package/dist/multi-highlighter/multi-highlighter.composition.js +36 -0
  31. package/dist/multi-highlighter/multi-highlighter.composition.js.map +1 -0
  32. package/dist/multi-highlighter/multi-highlighter.d.ts +15 -0
  33. package/dist/multi-highlighter/multi-highlighter.js +84 -0
  34. package/dist/multi-highlighter/multi-highlighter.js.map +1 -0
  35. package/dist/multi-highlighter/multi-highlighter.spec.d.ts +1 -0
  36. package/dist/multi-highlighter/multi-highlighter.spec.js +22 -0
  37. package/dist/multi-highlighter/multi-highlighter.spec.js.map +1 -0
  38. package/dist/use-animation-frame.d.ts +1 -0
  39. package/dist/use-animation-frame.js +23 -0
  40. package/dist/use-animation-frame.js.map +1 -0
  41. package/element-highlighter/element-highlighter.compositions.tsx +37 -22
  42. package/element-highlighter/element-highlighter.module.scss +7 -0
  43. package/element-highlighter/element-highlighter.tsx +14 -2
  44. package/frame/frame.tsx +6 -21
  45. package/index.ts +9 -1
  46. package/label/label.tsx +14 -12
  47. package/multi-highlighter/index.ts +2 -0
  48. package/multi-highlighter/multi-highlighter.composition.tsx +41 -0
  49. package/multi-highlighter/multi-highlighter.spec.tsx +22 -0
  50. package/multi-highlighter/multi-highlighter.tsx +85 -0
  51. package/package-tar/teambit-react.ui.component-highlighter-0.0.483.tgz +0 -0
  52. package/package.json +12 -11
  53. package/use-animation-frame.tsx +20 -0
  54. package/component-highlighter/bit-react-component.ts +0 -5
  55. package/dist/component-highlighter/bit-react-component.d.ts +0 -2
  56. package/dist/component-highlighter/bit-react-component.js +0 -8
  57. package/dist/component-highlighter/bit-react-component.js.map +0 -1
  58. 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.babel.bit-react-transformer';
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 = 1;
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).toBeTruthy();
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).toBeTruthy();
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 verify highlighter remains
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')).toBeTruthy();
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 '../bit-react-component';
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
- <HoverSelector
74
- {...rest}
75
- className={classnames(styles.highlighter, !disabled && styles.active)}
76
- onElementChange={handleElement}
77
- disabled={disabled}
78
- data-nullify-component-highlight
79
- >
80
- {children}
81
- </HoverSelector>
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
- // could also achieve this by moving the ElementHighlighter into HoverSelector.
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 { HoverHighlightbr } from '@teambit/react.ui.component-highlighter';
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 bit_react_component_1 = require("../bit-react-component");
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(react_1.default.Fragment, null,
78
- 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 }), children),
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, bit_react_component_1.hasComponentMeta)(component)) {
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":"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"}
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 react_babel_bit_react_transformer_1 = require("@teambit/react.babel.bit-react-transformer");
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 = 1;
20
+ const debounceTime = 2;
21
21
  function ButtonComponent({ children }) {
22
22
  return react_1.default.createElement("button", null, children);
23
23
  }
24
- ButtonComponent[react_babel_bit_react_transformer_1.componentMetaField] = {
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).toBeTruthy();
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).toBeTruthy();
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 verify highlighter remains
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')).toBeTruthy();
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":"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"}
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,oJAAwH;AAExH,2DAAuD;AAEvD,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB,SAAS,eAAe,CAAC,EAAE,QAAQ,EAA2B;IAC5D,OAAO,8CAAS,QAAQ,CAAU,CAAC;AACrC,CAAC;AAED,eAAe,CAAC,+EAAkB,CAAC,GAAG;IACpC,wDAAwD;IACxD,EAAE,EAAE,8BAA8B;CAClB,CAAC;AAEnB,EAAE,CAAC,yDAAyD,EAAE,GAAS,EAAE;IACvE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAA,cAAM,EACtC,8BAAC,oCAAgB,IAAC,iBAAiB,EAAE,YAAY;QAC/C,8BAAC,eAAe,qBAA6B,CAC5B,CACpB,CAAC;IACF,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,CAAC;IAE9B,IAAA,gBAAG,EAAC,GAAG,EAAE;QACP,iBAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;IACzD,MAAM,CAAC,eAAe,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC,CAAA,CAAC,CAAC;AAEH,EAAE,CAAC,4DAA4D,EAAE,GAAS,EAAE;IAC1E,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAA,cAAM,EACnD,8BAAC,oCAAgB,IAAC,iBAAiB,EAAE,YAAY;QAC/C,8BAAC,eAAe,qBAA6B,CAC5B,CACpB,CAAC;IACF,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IAEzC,IAAA,gBAAG,EAAC,GAAG,EAAE;QACP,iBAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;IACzD,MAAM,CAAC,eAAe,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAEpD,IAAA,gBAAG,EAAC,GAAG,EAAE;QACP,iBAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,MAAM,IAAA,iCAAyB,EAAC,GAAG,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;AACrE,CAAC,CAAA,CAAC,CAAC;AAEH,EAAE,CAAC,+FAA+F,EAAE,GAAS,EAAE;IAC7G,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAA,cAAM,EACtC,8BAAC,oCAAgB,IAAC,iBAAiB,EAAE,YAAY;QAC/C,8BAAC,eAAe,qBAA6B,CAC5B,CACpB,CAAC;IACF,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IAEzC,IAAA,gBAAG,EAAC,GAAG,EAAE;QACP,2BAA2B;QAC3B,iBAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;IAEzD,MAAM,IAAA,gBAAG,EAAC,GAAS,EAAE;QACnB,qEAAqE;QACrE,6BAA6B;QAC7B,iBAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE7B,yCAAyC;QACzC,iBAAS,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QACtC,+CAA+C;QAC/C,2CAA2C;QAC3C,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC,CAAA,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,CAAC,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;AACvE,CAAC,CAAA,CAAC,CAAC;AAEH,EAAE,CAAC,8DAA8D,EAAE,GAAS,EAAE;IAC5E,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,IAAA,cAAM,EACnD,8BAAC,oCAAgB,IAAC,iBAAiB,EAAE,YAAY;QAC/C,8BAAC,eAAe,qBAA6B,CAC5B,CACpB,CAAC;IAEF,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IAEzC,2BAA2B;IAC3B,MAAM,IAAA,gBAAG,EAAC,GAAS,EAAE;QACnB,iBAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;IAEzD,MAAM,IAAA,gBAAG,EAAC,GAAS,EAAE;QACnB,uBAAuB;QACvB,iBAAS,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QACtC,wBAAwB;QACxB,iBAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACpC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC,CAAA,CAAC,CAAC;IAEH,sDAAsD;IACtD,uEAAuE;IACvE,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACjD,CAAC,CAAA,CAAC,CAAC"}
@@ -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 { HoverHighlightbr } from '@teambit/react.ui.component-highlighter';
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
- export declare const HighlightedElement: ({ style, className }: {
2
- style?: Record<string, string>;
1
+ import { CSSProperties } from 'react';
2
+ declare type HighlightedElementProps = {
3
+ style?: CSSProperties;
4
+ targetStyle?: CSSProperties;
3
5
  className?: string;
4
- }) => JSX.Element;
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 mockTargetId = 'teambit.design/ui/icon-button';
26
- const HighlightedElement = ({ style, className }) => {
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
- const { current } = targetRef;
31
- setTargetElement(current || undefined);
32
- }, [targetRef.current]);
33
- const target = targetElement && {
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,+CAA8D;AAC9D,+DAA4E;AAE5E,MAAM,YAAY,GAAG,+BAA+B,CAAC;AAE9C,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAA0D,EAAE,EAAE;IACjH,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;QACb,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;QAC9B,gBAAgB,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;IACzC,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAExB,MAAM,MAAM,GAAgC,aAAa,IAAI;QAC3D,OAAO,EAAE,aAAa;QACtB,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,+CAA+C;QACrD,SAAS,EAAE,gCAAgC;KAC5C,CAAC;IAEF,OAAO,CACL,uCAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE;QACnE,uCAAK,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,uBAEpC;QACL,MAAM,IAAI,8BAAC,wCAAkB,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAC,QAAQ,GAAG,CAC9E,CACP,CAAC;AACJ,CAAC,CAAC;AAxBW,QAAA,kBAAkB,sBAwB7B;AAEK,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,CACL,8BAAC,0BAAkB,IACjB,KAAK,EAAE;YACL,yBAAyB,EAAE,SAAS;YACpC,+BAA+B,EAAE,SAAS;YAC1C,gCAAgC,EAAE,SAAS;SAC5C,GACD,CACH,CAAC;AACJ,CAAC,CAAC;AAVW,QAAA,UAAU,cAUrB;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"}
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;