@teambit/react.ui.component-highlighter 0.0.447 → 0.0.451
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/bubble/bubble.module.scss +1 -1
- package/component-highlighter/hover-highlighter/hover-highlighter.compositions.tsx +21 -0
- package/{dist/component-highlighter/component-highlighter.module.scss → component-highlighter/hover-highlighter/hover-highlighter.module.scss} +0 -9
- package/component-highlighter/hover-highlighter/hover-highlighter.tsx +100 -0
- package/component-highlighter/hover-highlighter/index.ts +1 -0
- package/component-highlighter/index.ts +2 -2
- package/component-highlighter.docs.md +110 -0
- package/dist/bubble/bubble.module.scss +1 -1
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.compositions.d.ts +1 -0
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.compositions.js +37 -0
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.compositions.js.map +1 -0
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.d.ts +13 -0
- package/dist/component-highlighter/{component-highlighter.js → hover-highlighter/hover-highlighter.js} +22 -18
- package/dist/component-highlighter/hover-highlighter/hover-highlighter.js.map +1 -0
- package/{component-highlighter/component-highlighter.module.scss → dist/component-highlighter/hover-highlighter/hover-highlighter.module.scss} +0 -9
- package/dist/component-highlighter/hover-highlighter/index.d.ts +1 -0
- package/dist/component-highlighter/hover-highlighter/index.js +6 -0
- package/dist/component-highlighter/hover-highlighter/index.js.map +1 -0
- package/dist/component-highlighter/index.d.ts +2 -2
- package/dist/component-highlighter/index.js +3 -3
- package/dist/component-highlighter/index.js.map +1 -1
- package/dist/component-highlighter.docs.md +110 -0
- package/dist/element-highlighter/element-highlighter.compositions.d.ts +6 -0
- package/dist/element-highlighter/element-highlighter.compositions.js +56 -0
- package/dist/element-highlighter/element-highlighter.compositions.js.map +1 -0
- package/dist/element-highlighter/element-highlighter.d.ts +27 -0
- package/dist/element-highlighter/element-highlighter.js +32 -0
- package/dist/element-highlighter/element-highlighter.js.map +1 -0
- package/dist/element-highlighter/element-highlighter.module.scss +8 -0
- package/dist/element-highlighter/index.d.ts +2 -0
- package/dist/element-highlighter/index.js +6 -0
- package/dist/element-highlighter/index.js.map +1 -0
- package/dist/ignore-highlighter.d.ts +10 -0
- package/dist/ignore-highlighter.js +18 -0
- package/dist/ignore-highlighter.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/label/component-label/component-label.js +3 -3
- package/dist/label/component-label/component-label.js.map +1 -1
- package/dist/label/default-label/default-label.js +1 -2
- package/dist/label/default-label/default-label.js.map +1 -1
- package/dist/label/default-label/default-label.module.scss +4 -0
- package/dist/label/index.d.ts +1 -1
- package/dist/label/label.d.ts +1 -0
- package/dist/label/label.js +3 -8
- package/dist/label/label.js.map +1 -1
- package/element-highlighter/element-highlighter.compositions.tsx +46 -0
- package/element-highlighter/element-highlighter.module.scss +8 -0
- package/element-highlighter/element-highlighter.tsx +60 -0
- package/element-highlighter/index.ts +2 -0
- package/ignore-highlighter.tsx +14 -0
- package/index.ts +7 -2
- package/label/component-label/component-label.tsx +2 -3
- package/label/default-label/default-label.module.scss +4 -0
- package/label/default-label/default-label.tsx +1 -2
- package/label/index.ts +1 -1
- package/label/label.tsx +13 -9
- package/package-tar/teambit-react.ui.component-highlighter-0.0.451.tgz +0 -0
- package/package.json +12 -12
- package/component-highlighter/component-highlighter.docs.md +0 -23
- package/component-highlighter/component-highlighter.tsx +0 -109
- package/dist/component-highlighter/component-highlighter.d.ts +0 -5
- package/dist/component-highlighter/component-highlighter.docs.md +0 -23
- package/dist/component-highlighter/component-highlighter.js.map +0 -1
- package/dist/label/label.module.scss +0 -3
- package/label/label.module.scss +0 -3
- package/package-tar/teambit-react.ui.component-highlighter-0.0.447.tgz +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { IconButton } from '@teambit/design.ui.icon-button';
|
|
3
|
+
import { HoverHighlighter } from './hover-highlighter';
|
|
4
|
+
|
|
5
|
+
export const ShowWhenHovering = () => {
|
|
6
|
+
const [disabled, setDisabled] = useState<boolean>(false);
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div style={{ padding: '16px 80px 32px 16px' }}>
|
|
10
|
+
<HoverHighlighter style={{ padding: 16 }} disabled={disabled}>
|
|
11
|
+
<div>
|
|
12
|
+
some div
|
|
13
|
+
<br />
|
|
14
|
+
<div>
|
|
15
|
+
<IconButton onClick={() => setDisabled((x) => !x)}>Hover here</IconButton>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</HoverHighlighter>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -6,17 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
transition: border 300ms;
|
|
8
8
|
|
|
9
|
-
--bit-highlighter-color: #eebcc9;
|
|
10
|
-
--bit-highlighter-color-light: #f6dae2;
|
|
11
|
-
--bit-highlighter-color-active: #e79db1;
|
|
12
|
-
|
|
13
9
|
&.active {
|
|
14
10
|
border-width: 8px;
|
|
15
11
|
overflow: auto;
|
|
16
12
|
}
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
.label {
|
|
20
|
-
font-family: sans-serif;
|
|
21
|
-
padding: 8px;
|
|
22
|
-
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, { useState, useCallback, useEffect, CSSProperties } from 'react';
|
|
2
|
+
import classnames from 'classnames';
|
|
3
|
+
import { useDebouncedCallback } from 'use-debounce';
|
|
4
|
+
import { domToReact, toRootElement } from '@teambit/react.modules.dom-to-react';
|
|
5
|
+
import { HoverSelector } from '@teambit/react.ui.hover-selector';
|
|
6
|
+
import { hasComponentMeta } from '../bit-react-component';
|
|
7
|
+
|
|
8
|
+
import styles from './hover-highlighter.module.scss';
|
|
9
|
+
import { excludeHighlighterSelector } from '../../ignore-highlighter';
|
|
10
|
+
import { ElementHighlighter, HighlightTarget, Placement, HighlightClasses } from '../../element-highlighter';
|
|
11
|
+
|
|
12
|
+
export interface HoverHighlighterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** default pop location for the label */
|
|
15
|
+
placement?: Placement;
|
|
16
|
+
/** customize styles */
|
|
17
|
+
classes?: HighlightClasses;
|
|
18
|
+
/** customize highlighter */
|
|
19
|
+
highlightStyle?: CSSProperties;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** automatically highlight components on hover */
|
|
23
|
+
export function HoverHighlighter({
|
|
24
|
+
children,
|
|
25
|
+
disabled,
|
|
26
|
+
classes,
|
|
27
|
+
highlightStyle,
|
|
28
|
+
placement,
|
|
29
|
+
...rest
|
|
30
|
+
}: HoverHighlighterProps) {
|
|
31
|
+
const [target, setTarget] = useState<HighlightTarget | undefined>();
|
|
32
|
+
|
|
33
|
+
const _handleElement = useCallback((element: HTMLElement | null) => {
|
|
34
|
+
// clear highlighter at the edges:
|
|
35
|
+
if (!element || element.hasAttribute('data-nullify-component-highlight')) {
|
|
36
|
+
setTarget(undefined);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// skip DOM trees having 'data-ignore-component-highlight'
|
|
41
|
+
if (element.closest(excludeHighlighterSelector)) return;
|
|
42
|
+
|
|
43
|
+
const result = bubbleToBitComponent(element);
|
|
44
|
+
if (!result) return;
|
|
45
|
+
|
|
46
|
+
setTarget({
|
|
47
|
+
element: result.element,
|
|
48
|
+
id: result.meta.id,
|
|
49
|
+
scopeLink: undefined,
|
|
50
|
+
link: result.meta.homepage,
|
|
51
|
+
local: result.meta.exported === false,
|
|
52
|
+
});
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
const handleElement = useDebouncedCallback(_handleElement, target ? 80 : 0);
|
|
56
|
+
|
|
57
|
+
// clear target when disabled
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (disabled) {
|
|
60
|
+
setTarget(undefined);
|
|
61
|
+
}
|
|
62
|
+
}, [disabled]);
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<>
|
|
66
|
+
<HoverSelector
|
|
67
|
+
{...rest}
|
|
68
|
+
className={classnames(styles.highlighter, !disabled && styles.active)}
|
|
69
|
+
onElementChange={handleElement}
|
|
70
|
+
disabled={disabled}
|
|
71
|
+
data-nullify-component-highlight
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
</HoverSelector>
|
|
75
|
+
{target && <ElementHighlighter target={target} classes={classes} style={highlightStyle} placement={placement} />}
|
|
76
|
+
</>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** go up the dom tree until reaching a react bit component */
|
|
81
|
+
function bubbleToBitComponent(element: HTMLElement | null, filter?: (elem: Element) => boolean) {
|
|
82
|
+
for (let current = element; current; current = current.parentElement) {
|
|
83
|
+
current = toRootElement(current);
|
|
84
|
+
if (!current || filter?.(current) === false) return undefined;
|
|
85
|
+
|
|
86
|
+
const component = domToReact(current);
|
|
87
|
+
|
|
88
|
+
if (hasComponentMeta(component)) {
|
|
89
|
+
const meta = component.__bit_component;
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
element: current,
|
|
93
|
+
component,
|
|
94
|
+
meta,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HoverHighlighterProps, HoverHighlighter } from './hover-highlighter';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export { HoverHighlighter } from './hover-highlighter';
|
|
2
|
+
export type { HoverHighlighterProps } from './hover-highlighter';
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Highlights Bit Components and links to their Bit scope
|
|
3
|
+
labels: ['component', 'highlight', 'react']
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { HighlightedElement } from './element-highlighter/element-highlighter.compositions';
|
|
7
|
+
|
|
8
|
+
The component highlighter allows you to visually inspect bit react components, and provides a link to its documentation page.
|
|
9
|
+
It is mostly used for compositions debugging.
|
|
10
|
+
|
|
11
|
+
<HighlightedElement />
|
|
12
|
+
|
|
13
|
+
## How to use?
|
|
14
|
+
|
|
15
|
+
Simplest way to use the component is by wrapping your code with `HoverHighlighter`.
|
|
16
|
+
It will automatically detect components from DOM elements, just by hovering on them.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { HoverHighlightbr } from '@teambit/react.ui.component-highlighter';
|
|
20
|
+
|
|
21
|
+
function App() {
|
|
22
|
+
return (
|
|
23
|
+
<HoverHighlighter>
|
|
24
|
+
<Header />
|
|
25
|
+
<Feed />
|
|
26
|
+
</HoverHighlighter>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
You can also use it manually, to have more control:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const [element, setElement] = useState<HTMLElement | undefined>(undefined);
|
|
35
|
+
|
|
36
|
+
useEffect(() => setElement(
|
|
37
|
+
document.getElementById('to-highlight')
|
|
38
|
+
), [targetRef.current]);
|
|
39
|
+
|
|
40
|
+
const target = targetElement && {
|
|
41
|
+
element: targetElement,
|
|
42
|
+
id: 'teambit.design/ui/icon-button',
|
|
43
|
+
|
|
44
|
+
// explicit overrides:
|
|
45
|
+
link: 'https://bit.dev/teambit/design/ui/icon-button',
|
|
46
|
+
scopeLink: 'https://bit.dev/teambit/design',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div>
|
|
51
|
+
<div id="to-highlight">highlight target</div>
|
|
52
|
+
{target && <ElementHighlighter target={target} />}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## How does it work?
|
|
58
|
+
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
|
+
|
|
60
|
+
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
|
+
|
|
62
|
+
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.
|
|
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.
|
|
65
|
+
|
|
66
|
+
The result looks like this:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
var __bit_component = {
|
|
70
|
+
id: 'teambit.base-ui/button@1.0.0',
|
|
71
|
+
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
72
|
+
exported: true,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function Button() {
|
|
76
|
+
return <div>click me!</div>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// attaches metadata:
|
|
80
|
+
Button.__bit_component = __bit_component;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Customization
|
|
84
|
+
|
|
85
|
+
Use these CSS variables to edit the highlighter color
|
|
86
|
+
```css
|
|
87
|
+
--bit-highlighter-color: #eebcc9;
|
|
88
|
+
--bit-highlighter-color-hover: #f6dae2;
|
|
89
|
+
--bit-highlighter-color-active: #e79db1;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can also pass these classes for complete control:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const classes = {
|
|
96
|
+
/** containing div */
|
|
97
|
+
container?: string;
|
|
98
|
+
/** border */
|
|
99
|
+
frame?: string;
|
|
100
|
+
/** component id links */
|
|
101
|
+
label?: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
<HoverHighlighter classes={classes}>
|
|
105
|
+
...
|
|
106
|
+
</HoverHighlighter>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
You can control the size using regular `font-size`.
|
|
110
|
+
Keep in mind that the label can be either two elements (when using component id), and a single element (for other texts)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ShowWhenHovering: () => JSX.Element;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ShowWhenHovering = void 0;
|
|
23
|
+
const react_1 = __importStar(require("react"));
|
|
24
|
+
const design_ui_icon_button_1 = require("@teambit/design.ui.icon-button");
|
|
25
|
+
const hover_highlighter_1 = require("./hover-highlighter");
|
|
26
|
+
const ShowWhenHovering = () => {
|
|
27
|
+
const [disabled, setDisabled] = (0, react_1.useState)(false);
|
|
28
|
+
return (react_1.default.createElement("div", { style: { padding: '16px 80px 32px 16px' } },
|
|
29
|
+
react_1.default.createElement(hover_highlighter_1.HoverHighlighter, { style: { padding: 16 }, disabled: disabled },
|
|
30
|
+
react_1.default.createElement("div", null,
|
|
31
|
+
"some div",
|
|
32
|
+
react_1.default.createElement("br", null),
|
|
33
|
+
react_1.default.createElement("div", null,
|
|
34
|
+
react_1.default.createElement(design_ui_icon_button_1.IconButton, { onClick: () => setDisabled((x) => !x) }, "Hover here"))))));
|
|
35
|
+
};
|
|
36
|
+
exports.ShowWhenHovering = ShowWhenHovering;
|
|
37
|
+
//# sourceMappingURL=hover-highlighter.compositions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hover-highlighter.compositions.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.compositions.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAwC;AACxC,0EAA4D;AAC5D,2DAAuD;AAEhD,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAA,gBAAQ,EAAU,KAAK,CAAC,CAAC;IAEzD,OAAO,CACL,uCAAK,KAAK,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE;QAC5C,8BAAC,oCAAgB,IAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ;YAC1D;;gBAEE,yCAAM;gBACN;oBACE,8BAAC,kCAAU,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAyB,CACtE,CACF,CACW,CACf,CACP,CAAC;AACJ,CAAC,CAAC;AAhBW,QAAA,gBAAgB,oBAgB3B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React, { CSSProperties } from 'react';
|
|
2
|
+
import { Placement, HighlightClasses } from '../../element-highlighter';
|
|
3
|
+
export interface HoverHighlighterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
/** default pop location for the label */
|
|
6
|
+
placement?: Placement;
|
|
7
|
+
/** customize styles */
|
|
8
|
+
classes?: HighlightClasses;
|
|
9
|
+
/** customize highlighter */
|
|
10
|
+
highlightStyle?: CSSProperties;
|
|
11
|
+
}
|
|
12
|
+
/** automatically highlight components on hover */
|
|
13
|
+
export declare function HoverHighlighter({ children, disabled, classes, highlightStyle, placement, ...rest }: HoverHighlighterProps): JSX.Element;
|
|
@@ -33,25 +33,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
33
33
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.HoverHighlighter = void 0;
|
|
37
37
|
const react_1 = __importStar(require("react"));
|
|
38
38
|
const classnames_1 = __importDefault(require("classnames"));
|
|
39
|
+
const use_debounce_1 = require("use-debounce");
|
|
39
40
|
const react_modules_dom_to_react_1 = require("@teambit/react.modules.dom-to-react");
|
|
40
41
|
const react_ui_hover_selector_1 = require("@teambit/react.ui.hover-selector");
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
function
|
|
47
|
-
var { children, disabled } = _a, rest = __rest(_a, ["children", "disabled"]);
|
|
42
|
+
const bit_react_component_1 = require("../bit-react-component");
|
|
43
|
+
const hover_highlighter_module_scss_1 = __importDefault(require("./hover-highlighter.module.scss"));
|
|
44
|
+
const ignore_highlighter_1 = require("../../ignore-highlighter");
|
|
45
|
+
const element_highlighter_1 = require("../../element-highlighter");
|
|
46
|
+
/** automatically highlight components on hover */
|
|
47
|
+
function HoverHighlighter(_a) {
|
|
48
|
+
var { children, disabled, classes, highlightStyle, placement } = _a, rest = __rest(_a, ["children", "disabled", "classes", "highlightStyle", "placement"]);
|
|
48
49
|
const [target, setTarget] = (0, react_1.useState)();
|
|
49
50
|
const _handleElement = (0, react_1.useCallback)((element) => {
|
|
50
|
-
|
|
51
|
+
// clear highlighter at the edges:
|
|
52
|
+
if (!element || element.hasAttribute('data-nullify-component-highlight')) {
|
|
51
53
|
setTarget(undefined);
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
|
-
|
|
56
|
+
// skip DOM trees having 'data-ignore-component-highlight'
|
|
57
|
+
if (element.closest(ignore_highlighter_1.excludeHighlighterSelector))
|
|
58
|
+
return;
|
|
59
|
+
const result = bubbleToBitComponent(element);
|
|
55
60
|
if (!result)
|
|
56
61
|
return;
|
|
57
62
|
setTarget({
|
|
@@ -63,19 +68,18 @@ function ComponentHighlighter(_a) {
|
|
|
63
68
|
});
|
|
64
69
|
}, []);
|
|
65
70
|
const handleElement = (0, use_debounce_1.useDebouncedCallback)(_handleElement, target ? 80 : 0);
|
|
71
|
+
// clear target when disabled
|
|
66
72
|
(0, react_1.useEffect)(() => {
|
|
67
73
|
if (disabled) {
|
|
68
74
|
setTarget(undefined);
|
|
69
75
|
}
|
|
70
76
|
}, [disabled]);
|
|
71
|
-
return (react_1.default.createElement(
|
|
72
|
-
children,
|
|
73
|
-
target &&
|
|
74
|
-
react_1.default.createElement(frame_1.Frame, { targetRef: target.element, "data-ignore-component-highlight": true }),
|
|
75
|
-
target.id && (react_1.default.createElement(label_1.LabelContainer, { className: component_highlighter_module_scss_1.default.label, targetRef: target.element, placement: "top", "data-ignore-component-highlight": true },
|
|
76
|
-
react_1.default.createElement(label_1.Label, { componentId: target.id, link: target.link, scopeLink: target.scopeLink, local: target.local, "data-ignore-component-highlight": true })))))));
|
|
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 })));
|
|
77
80
|
}
|
|
78
|
-
exports.
|
|
81
|
+
exports.HoverHighlighter = HoverHighlighter;
|
|
82
|
+
/** go up the dom tree until reaching a react bit component */
|
|
79
83
|
function bubbleToBitComponent(element, filter) {
|
|
80
84
|
for (let current = element; current; current = current.parentElement) {
|
|
81
85
|
current = (0, react_modules_dom_to_react_1.toRootElement)(current);
|
|
@@ -93,4 +97,4 @@ function bubbleToBitComponent(element, filter) {
|
|
|
93
97
|
}
|
|
94
98
|
return undefined;
|
|
95
99
|
}
|
|
96
|
-
//# sourceMappingURL=
|
|
100
|
+
//# sourceMappingURL=hover-highlighter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hover-highlighter.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/hover-highlighter.tsx"],"names":[],"mappings":"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"}
|
|
@@ -6,17 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
transition: border 300ms;
|
|
8
8
|
|
|
9
|
-
--bit-highlighter-color: #eebcc9;
|
|
10
|
-
--bit-highlighter-color-light: #f6dae2;
|
|
11
|
-
--bit-highlighter-color-active: #e79db1;
|
|
12
|
-
|
|
13
9
|
&.active {
|
|
14
10
|
border-width: 8px;
|
|
15
11
|
overflow: auto;
|
|
16
12
|
}
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
.label {
|
|
20
|
-
font-family: sans-serif;
|
|
21
|
-
padding: 8px;
|
|
22
|
-
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HoverHighlighterProps, HoverHighlighter } from './hover-highlighter';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HoverHighlighter = void 0;
|
|
4
|
+
var hover_highlighter_1 = require("./hover-highlighter");
|
|
5
|
+
Object.defineProperty(exports, "HoverHighlighter", { enumerable: true, get: function () { return hover_highlighter_1.HoverHighlighter; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../component-highlighter/hover-highlighter/index.ts"],"names":[],"mappings":";;;AAAA,yDAA8E;AAA9C,qHAAA,gBAAgB,OAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export { HoverHighlighter } from './hover-highlighter';
|
|
2
|
+
export type { HoverHighlighterProps } from './hover-highlighter';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "
|
|
3
|
+
exports.HoverHighlighter = void 0;
|
|
4
|
+
var hover_highlighter_1 = require("./hover-highlighter");
|
|
5
|
+
Object.defineProperty(exports, "HoverHighlighter", { enumerable: true, get: function () { return hover_highlighter_1.HoverHighlighter; } });
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../component-highlighter/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../component-highlighter/index.ts"],"names":[],"mappings":";;;AAAA,yDAAuD;AAA9C,qHAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Highlights Bit Components and links to their Bit scope
|
|
3
|
+
labels: ['component', 'highlight', 'react']
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { HighlightedElement } from './element-highlighter/element-highlighter.compositions';
|
|
7
|
+
|
|
8
|
+
The component highlighter allows you to visually inspect bit react components, and provides a link to its documentation page.
|
|
9
|
+
It is mostly used for compositions debugging.
|
|
10
|
+
|
|
11
|
+
<HighlightedElement />
|
|
12
|
+
|
|
13
|
+
## How to use?
|
|
14
|
+
|
|
15
|
+
Simplest way to use the component is by wrapping your code with `HoverHighlighter`.
|
|
16
|
+
It will automatically detect components from DOM elements, just by hovering on them.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { HoverHighlightbr } from '@teambit/react.ui.component-highlighter';
|
|
20
|
+
|
|
21
|
+
function App() {
|
|
22
|
+
return (
|
|
23
|
+
<HoverHighlighter>
|
|
24
|
+
<Header />
|
|
25
|
+
<Feed />
|
|
26
|
+
</HoverHighlighter>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
You can also use it manually, to have more control:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const [element, setElement] = useState<HTMLElement | undefined>(undefined);
|
|
35
|
+
|
|
36
|
+
useEffect(() => setElement(
|
|
37
|
+
document.getElementById('to-highlight')
|
|
38
|
+
), [targetRef.current]);
|
|
39
|
+
|
|
40
|
+
const target = targetElement && {
|
|
41
|
+
element: targetElement,
|
|
42
|
+
id: 'teambit.design/ui/icon-button',
|
|
43
|
+
|
|
44
|
+
// explicit overrides:
|
|
45
|
+
link: 'https://bit.dev/teambit/design/ui/icon-button',
|
|
46
|
+
scopeLink: 'https://bit.dev/teambit/design',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div>
|
|
51
|
+
<div id="to-highlight">highlight target</div>
|
|
52
|
+
{target && <ElementHighlighter target={target} />}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## How does it work?
|
|
58
|
+
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
|
+
|
|
60
|
+
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
|
+
|
|
62
|
+
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.
|
|
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.
|
|
65
|
+
|
|
66
|
+
The result looks like this:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
var __bit_component = {
|
|
70
|
+
id: 'teambit.base-ui/button@1.0.0',
|
|
71
|
+
homepage: 'https://bit.dev/teambit/base-ui/input/button',
|
|
72
|
+
exported: true,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function Button() {
|
|
76
|
+
return <div>click me!</div>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// attaches metadata:
|
|
80
|
+
Button.__bit_component = __bit_component;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Customization
|
|
84
|
+
|
|
85
|
+
Use these CSS variables to edit the highlighter color
|
|
86
|
+
```css
|
|
87
|
+
--bit-highlighter-color: #eebcc9;
|
|
88
|
+
--bit-highlighter-color-hover: #f6dae2;
|
|
89
|
+
--bit-highlighter-color-active: #e79db1;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can also pass these classes for complete control:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const classes = {
|
|
96
|
+
/** containing div */
|
|
97
|
+
container?: string;
|
|
98
|
+
/** border */
|
|
99
|
+
frame?: string;
|
|
100
|
+
/** component id links */
|
|
101
|
+
label?: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
<HoverHighlighter classes={classes}>
|
|
105
|
+
...
|
|
106
|
+
</HoverHighlighter>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
You can control the size using regular `font-size`.
|
|
110
|
+
Keep in mind that the label can be either two elements (when using component id), and a single element (for other texts)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.Sizes = exports.Customized = exports.HighlightedElement = void 0;
|
|
23
|
+
const react_1 = __importStar(require("react"));
|
|
24
|
+
const element_highlighter_1 = require("./element-highlighter");
|
|
25
|
+
const mockTargetId = 'teambit.design/ui/icon-button';
|
|
26
|
+
const HighlightedElement = ({ style, className }) => {
|
|
27
|
+
const [targetElement, setTargetElement] = (0, react_1.useState)(undefined);
|
|
28
|
+
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" })));
|
|
42
|
+
};
|
|
43
|
+
exports.HighlightedElement = HighlightedElement;
|
|
44
|
+
const Customized = () => {
|
|
45
|
+
return (react_1.default.createElement(exports.HighlightedElement, { style: {
|
|
46
|
+
'--bit-highlighter-color': '#94deb4',
|
|
47
|
+
'--bit-highlighter-color-hover': '#d0f1de',
|
|
48
|
+
'--bit-highlighter-color-active': '#37b26c',
|
|
49
|
+
} }));
|
|
50
|
+
};
|
|
51
|
+
exports.Customized = Customized;
|
|
52
|
+
const Sizes = () => {
|
|
53
|
+
return react_1.default.createElement(exports.HighlightedElement, { style: { fontSize: '16px' } });
|
|
54
|
+
};
|
|
55
|
+
exports.Sizes = Sizes;
|
|
56
|
+
//# sourceMappingURL=element-highlighter.compositions.js.map
|