@teambit/react.ui.component-highlighter 0.0.0-2240a868c0f88bba4f62719e6d10d31987cae1f9
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/children-highlighter/children-highlighter.composition.tsx +103 -0
- package/children-highlighter/children-highlighter.spec.tsx +22 -0
- package/children-highlighter/children-highlighter.tsx +9 -0
- package/children-highlighter/index.ts +5 -0
- package/children-highlighter/use-children-highlighter.tsx +79 -0
- package/component-highlighter.docs.md +191 -0
- package/dist/children-highlighter/children-highlighter.composition.d.ts +6 -0
- package/dist/children-highlighter/children-highlighter.composition.js +93 -0
- package/dist/children-highlighter/children-highlighter.composition.js.map +1 -0
- package/dist/children-highlighter/children-highlighter.d.ts +4 -0
- package/dist/children-highlighter/children-highlighter.js +24 -0
- package/dist/children-highlighter/children-highlighter.js.map +1 -0
- package/dist/children-highlighter/children-highlighter.spec.d.ts +1 -0
- package/dist/children-highlighter/children-highlighter.spec.js +22 -0
- package/dist/children-highlighter/children-highlighter.spec.js.map +1 -0
- package/dist/children-highlighter/index.d.ts +4 -0
- package/dist/children-highlighter/index.js +8 -0
- package/dist/children-highlighter/index.js.map +1 -0
- package/dist/children-highlighter/use-children-highlighter.d.ts +18 -0
- package/dist/children-highlighter/use-children-highlighter.js +51 -0
- package/dist/children-highlighter/use-children-highlighter.js.map +1 -0
- package/dist/component-highlighter.docs.md +191 -0
- package/dist/element-highlighter/element-highlighter.compositions.d.ts +14 -0
- package/dist/element-highlighter/element-highlighter.compositions.js +113 -0
- package/dist/element-highlighter/element-highlighter.compositions.js.map +1 -0
- package/dist/element-highlighter/element-highlighter.d.ts +22 -0
- package/dist/element-highlighter/element-highlighter.js +31 -0
- package/dist/element-highlighter/element-highlighter.js.map +1 -0
- package/dist/element-highlighter/element-highlighter.module.scss +10 -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/frame/frame.d.ts +14 -0
- package/dist/frame/frame.js +138 -0
- package/dist/frame/frame.js.map +1 -0
- package/dist/frame/frame.module.scss +23 -0
- package/dist/frame/index.d.ts +2 -0
- package/dist/frame/index.js +6 -0
- package/dist/frame/index.js.map +1 -0
- package/dist/hover-highlighter/bubble-to-component.d.ts +24 -0
- package/dist/hover-highlighter/bubble-to-component.js +55 -0
- package/dist/hover-highlighter/bubble-to-component.js.map +1 -0
- package/dist/hover-highlighter/bubble-to-component.spec.d.ts +1 -0
- package/dist/hover-highlighter/bubble-to-component.spec.js +38 -0
- package/dist/hover-highlighter/bubble-to-component.spec.js.map +1 -0
- package/dist/hover-highlighter/hover-highlighter.compositions.d.ts +4 -0
- package/dist/hover-highlighter/hover-highlighter.compositions.js +83 -0
- package/dist/hover-highlighter/hover-highlighter.compositions.js.map +1 -0
- package/dist/hover-highlighter/hover-highlighter.d.ts +4 -0
- package/dist/hover-highlighter/hover-highlighter.js +24 -0
- package/dist/hover-highlighter/hover-highlighter.js.map +1 -0
- package/dist/hover-highlighter/hover-highlighter.spec.d.ts +1 -0
- package/dist/hover-highlighter/hover-highlighter.spec.js +95 -0
- package/dist/hover-highlighter/hover-highlighter.spec.js.map +1 -0
- package/dist/hover-highlighter/index.d.ts +4 -0
- package/dist/hover-highlighter/index.js +8 -0
- package/dist/hover-highlighter/index.js.map +1 -0
- package/dist/hover-highlighter/use-hover-highlighter.d.ts +25 -0
- package/dist/hover-highlighter/use-hover-highlighter.js +47 -0
- package/dist/hover-highlighter/use-hover-highlighter.js.map +1 -0
- package/dist/hybrid-highlighter/hybrid-highlighter.d.ts +36 -0
- package/dist/hybrid-highlighter/hybrid-highlighter.js +93 -0
- package/dist/hybrid-highlighter/hybrid-highlighter.js.map +1 -0
- package/dist/hybrid-highlighter/index.d.ts +2 -0
- package/dist/hybrid-highlighter/index.js +6 -0
- package/dist/hybrid-highlighter/index.js.map +1 -0
- package/dist/ignore-highlighter.d.ts +19 -0
- package/dist/ignore-highlighter.js +25 -0
- package/dist/ignore-highlighter.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/label/component-strip.compositions.d.ts +2 -0
- package/dist/label/component-strip.compositions.js +17 -0
- package/dist/label/component-strip.compositions.js.map +1 -0
- package/dist/label/component-strip.d.ts +7 -0
- package/dist/label/component-strip.js +71 -0
- package/dist/label/component-strip.js.map +1 -0
- package/dist/label/component-strip.module.scss +68 -0
- package/dist/label/index.d.ts +4 -0
- package/dist/label/index.js +8 -0
- package/dist/label/index.js.map +1 -0
- package/dist/label/label-container.d.ts +13 -0
- package/dist/label/label-container.js +87 -0
- package/dist/label/label-container.js.map +1 -0
- package/dist/label/label.d.ts +6 -0
- package/dist/label/label.js +70 -0
- package/dist/label/label.js.map +1 -0
- package/dist/label/label.module.scss +32 -0
- package/dist/label/links.d.ts +2 -0
- package/dist/label/links.js +16 -0
- package/dist/label/links.js.map +1 -0
- package/dist/label/other-components.d.ts +9 -0
- package/dist/label/other-components.js +34 -0
- package/dist/label/other-components.js.map +1 -0
- package/dist/mock-component.d.ts +14 -0
- package/dist/mock-component.js +43 -0
- package/dist/mock-component.js.map +1 -0
- package/dist/preview-1768840768294.js +10 -0
- package/dist/rule-matcher.d.ts +8 -0
- package/dist/rule-matcher.js +32 -0
- package/dist/rule-matcher.js.map +1 -0
- package/element-highlighter/element-highlighter.compositions.tsx +130 -0
- package/element-highlighter/element-highlighter.module.scss +10 -0
- package/element-highlighter/element-highlighter.tsx +51 -0
- package/element-highlighter/index.ts +2 -0
- package/frame/frame.module.scss +23 -0
- package/frame/frame.tsx +142 -0
- package/frame/index.ts +2 -0
- package/hover-highlighter/bubble-to-component.spec.tsx +57 -0
- package/hover-highlighter/bubble-to-component.tsx +82 -0
- package/hover-highlighter/hover-highlighter.compositions.tsx +65 -0
- package/hover-highlighter/hover-highlighter.spec.tsx +115 -0
- package/hover-highlighter/hover-highlighter.tsx +8 -0
- package/hover-highlighter/index.ts +5 -0
- package/hover-highlighter/use-hover-highlighter.tsx +85 -0
- package/hybrid-highlighter/hybrid-highlighter.tsx +142 -0
- package/hybrid-highlighter/index.ts +2 -0
- package/ignore-highlighter.tsx +22 -0
- package/index.ts +21 -0
- package/label/component-strip.compositions.tsx +13 -0
- package/label/component-strip.module.scss +68 -0
- package/label/component-strip.tsx +57 -0
- package/label/index.ts +5 -0
- package/label/label-container.tsx +74 -0
- package/label/label.module.scss +32 -0
- package/label/label.tsx +37 -0
- package/label/links.tsx +9 -0
- package/label/other-components.tsx +51 -0
- package/mock-component.tsx +23 -0
- package/package.json +60 -0
- package/rule-matcher.tsx +42 -0
- package/types/asset.d.ts +29 -0
- package/types/style.d.ts +42 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.calcComponentLink = calcComponentLink;
|
|
7
|
+
const url_join_1 = __importDefault(require("url-join"));
|
|
8
|
+
const component_modules_component_url_1 = require("@teambit/component.modules.component-url");
|
|
9
|
+
function calcComponentLink(id, exported) {
|
|
10
|
+
if (!id)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (exported)
|
|
13
|
+
return component_modules_component_url_1.ComponentUrl.toUrl(id);
|
|
14
|
+
return (0, url_join_1.default)('/', id.fullName);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../label/links.tsx"],"names":[],"mappings":";;;;;AAIA,8CAIC;AARD,wDAA+B;AAE/B,8FAAwE;AAExE,SAAgB,iBAAiB,CAAC,EAA2B,EAAE,QAA6B;IAC1F,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1B,IAAI,QAAQ;QAAE,OAAO,8CAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAA,kBAAO,EAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TippyProps } from '@tippyjs/react/headless';
|
|
3
|
+
import { ComponentMetaHolder } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
4
|
+
export type OtherComponentsProps = {
|
|
5
|
+
components: (ComponentMetaHolder | string)[];
|
|
6
|
+
start?: number;
|
|
7
|
+
end?: number;
|
|
8
|
+
} & TippyProps;
|
|
9
|
+
export declare function OtherComponentsPopper({ components, children, start, end, placement, interactive, ...tippyProps }: OtherComponentsProps): React.JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.OtherComponentsPopper = OtherComponentsPopper;
|
|
18
|
+
const react_1 = __importDefault(require("react"));
|
|
19
|
+
const headless_1 = __importDefault(require("@tippyjs/react/headless"));
|
|
20
|
+
const component_strip_1 = require("./component-strip");
|
|
21
|
+
const label_module_scss_1 = __importDefault(require("./label.module.scss"));
|
|
22
|
+
// a popper ("tooltip") that shows the additional React Components related to this dom element
|
|
23
|
+
function OtherComponentsPopper(_a) {
|
|
24
|
+
var { components, children, start, end = -1, placement = 'bottom', interactive = true } = _a, tippyProps = __rest(_a, ["components", "children", "start", "end", "placement", "interactive"]);
|
|
25
|
+
const content = (react_1.default.createElement(react_1.default.Fragment, null, components
|
|
26
|
+
.slice(start, end)
|
|
27
|
+
.reverse()
|
|
28
|
+
.map((comp, idx) => (react_1.default.createElement(component_strip_1.ComponentStrip, { key: idx, component: comp })))));
|
|
29
|
+
return (react_1.default.createElement(headless_1.default, Object.assign({ placement: placement, interactive: interactive }, tippyProps, {
|
|
30
|
+
// second parameter "content" is always undefined, use content inline
|
|
31
|
+
// https://github.com/atomiks/tippyjs-react/issues/341
|
|
32
|
+
render: (attrs) => (react_1.default.createElement("div", Object.assign({}, attrs, { className: label_module_scss_1.default.othersContainer }), content)) }), children));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=other-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"other-components.js","sourceRoot":"","sources":["../../label/other-components.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAcA,sDAoCC;AAlDD,kDAA0B;AAC1B,uEAA4D;AAG5D,uDAAmD;AACnD,4EAAyC;AAQzC,8FAA8F;AAC9F,SAAgB,qBAAqB,CAAC,EAQf;QARe,EACpC,UAAU,EACV,QAAQ,EACR,KAAK,EACL,GAAG,GAAG,CAAC,CAAC,EACR,SAAS,GAAG,QAAQ,EACpB,WAAW,GAAG,IAAI,OAEG,EADlB,UAAU,cAPuB,sEAQrC,CADc;IAEb,MAAM,OAAO,GAAG,CACd,8DACG,UAAU;SACR,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;SACjB,OAAO,EAAE;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAClB,8BAAC,gCAAc,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,GAAI,CAC9C,CAAC,CACH,CACJ,CAAC;IAEF,OAAO,CACL,8BAAC,kBAAK,kBACJ,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW,IACpB,UAAU;QACd,qEAAqE;QACrE,sDAAsD;QACtD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CACjB,uDAAS,KAAK,IAAE,SAAS,EAAE,2BAAM,CAAC,eAAe,KAC9C,OAAO,CACJ,CACP,KAEA,QAAQ,CACH,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, { ButtonHTMLAttributes, HTMLAttributes } from 'react';
|
|
2
|
+
import { ComponentMeta } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
3
|
+
export declare function MockTarget({ children, ...rest }: HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
4
|
+
export declare namespace MockTarget {
|
|
5
|
+
var __bit_component: ComponentMeta;
|
|
6
|
+
}
|
|
7
|
+
export declare function MockButton({ children, ...rest }: ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
|
|
8
|
+
export declare namespace MockButton {
|
|
9
|
+
var __bit_component: ComponentMeta;
|
|
10
|
+
}
|
|
11
|
+
export declare function MockSnap({ children, ...rest }: ButtonHTMLAttributes<HTMLButtonElement>): React.JSX.Element;
|
|
12
|
+
export declare namespace MockSnap {
|
|
13
|
+
var __bit_component: ComponentMeta;
|
|
14
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.MockTarget = MockTarget;
|
|
18
|
+
exports.MockButton = MockButton;
|
|
19
|
+
exports.MockSnap = MockSnap;
|
|
20
|
+
const react_1 = __importDefault(require("react"));
|
|
21
|
+
const react_ui_highlighter_component_metadata_bit_component_meta_1 = require("@teambit/react.ui.highlighter.component-metadata.bit-component-meta");
|
|
22
|
+
function MockTarget(_a) {
|
|
23
|
+
var { children } = _a, rest = __rest(_a, ["children"]);
|
|
24
|
+
return react_1.default.createElement("div", Object.assign({}, rest), children);
|
|
25
|
+
}
|
|
26
|
+
MockTarget[react_ui_highlighter_component_metadata_bit_component_meta_1.componentMetaField] = {
|
|
27
|
+
id: 'teambit.design/ui/mock-target@1.6.2',
|
|
28
|
+
};
|
|
29
|
+
function MockButton(_a) {
|
|
30
|
+
var { children } = _a, rest = __rest(_a, ["children"]);
|
|
31
|
+
return react_1.default.createElement("button", Object.assign({}, rest), children);
|
|
32
|
+
}
|
|
33
|
+
MockButton[react_ui_highlighter_component_metadata_bit_component_meta_1.componentMetaField] = {
|
|
34
|
+
id: 'teambit.design/ui/icon-button@1.6.2',
|
|
35
|
+
};
|
|
36
|
+
function MockSnap(_a) {
|
|
37
|
+
var { children } = _a, rest = __rest(_a, ["children"]);
|
|
38
|
+
return react_1.default.createElement("button", Object.assign({}, rest), children);
|
|
39
|
+
}
|
|
40
|
+
MockSnap[react_ui_highlighter_component_metadata_bit_component_meta_1.componentMetaField] = {
|
|
41
|
+
id: 'teambit.design/ui/icon-button@a21594d5cc63fd24d2b4763fa7d817b131f0edbb',
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=mock-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-component.js","sourceRoot":"","sources":["../mock-component.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAGA,gCAEC;AAKD,gCAEC;AAKD,4BAEC;AAnBD,kDAAoE;AACpE,oJAAwH;AAExH,SAAgB,UAAU,CAAC,EAAqD;QAArD,EAAE,QAAQ,OAA2C,EAAtC,IAAI,cAAnB,YAAqB,CAAF;IAC5C,OAAO,uDAAS,IAAI,GAAG,QAAQ,CAAO,CAAC;AACzC,CAAC;AACD,UAAU,CAAC,+EAAkB,CAAC,GAAG;IAC/B,EAAE,EAAE,qCAAqC;CACzB,CAAC;AAEnB,SAAgB,UAAU,CAAC,EAA8D;QAA9D,EAAE,QAAQ,OAAoD,EAA/C,IAAI,cAAnB,YAAqB,CAAF;IAC5C,OAAO,0DAAY,IAAI,GAAG,QAAQ,CAAU,CAAC;AAC/C,CAAC;AACD,UAAU,CAAC,+EAAkB,CAAC,GAAG;IAC/B,EAAE,EAAE,qCAAqC;CACzB,CAAC;AAEnB,SAAgB,QAAQ,CAAC,EAA8D;QAA9D,EAAE,QAAQ,OAAoD,EAA/C,IAAI,cAAnB,YAAqB,CAAF;IAC1C,OAAO,0DAAY,IAAI,GAAG,QAAQ,CAAU,CAAC;AAC/C,CAAC;AACD,QAAQ,CAAC,+EAAkB,CAAC,GAAG;IAC7B,EAAE,EAAE,wEAAwE;CAC5D,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as compositions_0 from '/tmp/capsules-root/sign-capsules/2026-0-19/z4rgtj/teambit.react_ui_component-highlighter@2240a868c0f88bba4f62719e6d10d31987cae1f9/dist/children-highlighter/children-highlighter.composition.js';
|
|
2
|
+
import * as compositions_1 from '/tmp/capsules-root/sign-capsules/2026-0-19/z4rgtj/teambit.react_ui_component-highlighter@2240a868c0f88bba4f62719e6d10d31987cae1f9/dist/element-highlighter/element-highlighter.compositions.js';
|
|
3
|
+
import * as compositions_2 from '/tmp/capsules-root/sign-capsules/2026-0-19/z4rgtj/teambit.react_ui_component-highlighter@2240a868c0f88bba4f62719e6d10d31987cae1f9/dist/hover-highlighter/hover-highlighter.compositions.js';
|
|
4
|
+
import * as compositions_3 from '/tmp/capsules-root/sign-capsules/2026-0-19/z4rgtj/teambit.react_ui_component-highlighter@2240a868c0f88bba4f62719e6d10d31987cae1f9/dist/label/component-strip.compositions.js';
|
|
5
|
+
import * as overview_0 from '/tmp/capsules-root/sign-capsules/2026-0-19/z4rgtj/teambit.react_ui_component-highlighter@2240a868c0f88bba4f62719e6d10d31987cae1f9/dist/component-highlighter.docs.md';
|
|
6
|
+
|
|
7
|
+
export const compositions = [compositions_0, compositions_1, compositions_2, compositions_3];
|
|
8
|
+
export const overview = [overview_0];
|
|
9
|
+
|
|
10
|
+
export const compositions_metadata = {"compositions":[{"displayName":"Children highlighter preview","identifier":"ChildrenHighlighterPreview"},{"displayName":"Children highlighter with custom colors","identifier":"ChildrenHighlighterWithCustomColors"},{"displayName":"Children highlighter inside ignore","identifier":"ChildrenHighlighterInsideIgnore"},{"displayName":"Children highlighter with rule","identifier":"ChildrenHighlighterWithRule"},{"displayName":"Children highlighter with component rule","identifier":"ChildrenHighlighterWithComponentRule"},{"displayName":"Highlighted element","identifier":"HighlightedElement"},{"displayName":"Customized","identifier":"Customized"},{"displayName":"Sizes","identifier":"Sizes"},{"displayName":"Moving element","identifier":"MovingElement"},{"displayName":"Fullscreen element","identifier":"FullscreenElement"},{"displayName":"Offscreen elements","identifier":"OffscreenElements"},{"displayName":"Show when hovering","identifier":"ShowWhenHovering"},{"displayName":"Unmounting element","identifier":"UnmountingElement"},{"displayName":"Hover exclusion zones","identifier":"HoverExclusionZones"},{"displayName":"Component strip preview","identifier":"ComponentStripPreview"}]};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ComponentMeta } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
2
|
+
export type MatchRule = undefined | string | ((element: HTMLElement) => boolean);
|
|
3
|
+
export type ComponentMatchRule = undefined | string | string[] | ((target: ComponentMatchTarget) => boolean);
|
|
4
|
+
export declare function ruleMatcher(element: HTMLElement, rule: MatchRule): boolean;
|
|
5
|
+
export type ComponentMatchTarget = {
|
|
6
|
+
meta: ComponentMeta;
|
|
7
|
+
};
|
|
8
|
+
export declare function componentRuleMatcher(target: ComponentMatchTarget, rule: ComponentMatchRule): boolean;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ruleMatcher = ruleMatcher;
|
|
4
|
+
exports.componentRuleMatcher = componentRuleMatcher;
|
|
5
|
+
// in the future, we will add more options here, like include / exclude objects.
|
|
6
|
+
const component_id_1 = require("@teambit/component-id");
|
|
7
|
+
function ruleMatcher(element, rule) {
|
|
8
|
+
if (typeof rule === 'string') {
|
|
9
|
+
return element.matches(rule);
|
|
10
|
+
}
|
|
11
|
+
if (typeof rule === 'function') {
|
|
12
|
+
return rule(element);
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
function componentRuleMatcher(target, rule) {
|
|
17
|
+
if (typeof rule === 'string') {
|
|
18
|
+
const targetCmpId = component_id_1.ComponentID.tryFromString(target.meta.id);
|
|
19
|
+
const ruleCmpId = component_id_1.ComponentID.tryFromString(rule);
|
|
20
|
+
return component_id_1.ComponentID.isEqual(ruleCmpId, targetCmpId, { ignoreVersion: true });
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(rule)) {
|
|
23
|
+
const targetCmpId = component_id_1.ComponentID.tryFromString(target.meta.id);
|
|
24
|
+
const ruleCmpIds = rule.map((x) => component_id_1.ComponentID.tryFromString(x));
|
|
25
|
+
return ruleCmpIds.some((cmdId) => component_id_1.ComponentID.isEqual(targetCmpId, cmdId, { ignoreVersion: true }));
|
|
26
|
+
}
|
|
27
|
+
if (typeof rule === 'function') {
|
|
28
|
+
return rule(target);
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=rule-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-matcher.js","sourceRoot":"","sources":["../rule-matcher.tsx"],"names":[],"mappings":";;AAOA,kCAUC;AAID,oDAoBC;AAzCD,gFAAgF;AAChF,wDAAoD;AAMpD,SAAgB,WAAW,CAAC,OAAoB,EAAE,IAAe;IAC/D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAID,SAAgB,oBAAoB,CAAC,MAA4B,EAAE,IAAwB;IACzF,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,0BAAW,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,0BAAW,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAElD,OAAO,0BAAW,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,0BAAW,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,0BAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,0BAAW,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACtG,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useState, createRef, useEffect, CSSProperties } from 'react';
|
|
2
|
+
import { ElementHighlighter } from './element-highlighter';
|
|
3
|
+
import { MockTarget } from '../mock-component';
|
|
4
|
+
|
|
5
|
+
type HighlightedElementProps = {
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
targetStyle?: CSSProperties;
|
|
8
|
+
className?: string;
|
|
9
|
+
watchMotion?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const HighlightedElement = ({ style, targetStyle, watchMotion, className }: HighlightedElementProps) => {
|
|
13
|
+
const targetRef = createRef<HTMLDivElement>();
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className={className} style={{ padding: '16px 16px 40px 16px', width: 300, fontFamily: 'sans-serif' }}>
|
|
17
|
+
<div ref={targetRef} style={{ width: 100, ...targetStyle }}>
|
|
18
|
+
highlight target
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<ElementHighlighter
|
|
22
|
+
targetRef={targetRef}
|
|
23
|
+
components={[MockTarget]}
|
|
24
|
+
style={style}
|
|
25
|
+
watchMotion={watchMotion}
|
|
26
|
+
placement="bottom"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Customized = () => {
|
|
33
|
+
return (
|
|
34
|
+
<HighlightedElement
|
|
35
|
+
style={
|
|
36
|
+
{
|
|
37
|
+
'--bit-highlighter-color': '#94deb4',
|
|
38
|
+
'--bit-highlighter-color-hover': '#d0f1de',
|
|
39
|
+
'--bit-highlighter-color-active': '#37b26c',
|
|
40
|
+
} as CSSProperties
|
|
41
|
+
}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const Sizes = () => {
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
<HighlightedElement style={{ fontSize: 10 }} />
|
|
50
|
+
<HighlightedElement style={{ fontSize: 14 }} />
|
|
51
|
+
<HighlightedElement style={{ fontSize: 18 }} />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const fps = 30;
|
|
57
|
+
const frameInterval = 1000 / fps;
|
|
58
|
+
|
|
59
|
+
export const MovingElement = () => {
|
|
60
|
+
const [margin, setMargin] = useState(0);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const intervalId = setInterval(() => setMargin((x) => (x + 1) % 100), frameInterval);
|
|
64
|
+
return () => clearInterval(intervalId);
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
return <HighlightedElement targetStyle={{ marginLeft: margin }} watchMotion />;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const FullscreenElement = () => {
|
|
71
|
+
const targetRef = createRef<HTMLDivElement>();
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div style={{ fontFamily: 'sans-serif' }}>
|
|
75
|
+
<div
|
|
76
|
+
ref={targetRef}
|
|
77
|
+
style={{
|
|
78
|
+
height: '100vh',
|
|
79
|
+
width: '100%',
|
|
80
|
+
background: '#bceed4',
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
This element will cover the entire document,
|
|
84
|
+
<br />
|
|
85
|
+
pushing the highlighter to the edge of the window.
|
|
86
|
+
<br />
|
|
87
|
+
The highlighter should remain inside and expand no further than the document.
|
|
88
|
+
</div>
|
|
89
|
+
<ElementHighlighter targetRef={targetRef} components={[MockTarget]} watchMotion />
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const edgeStyles = { position: 'absolute', background: 'cyan', padding: 30 } as const;
|
|
95
|
+
const centerStyles = {
|
|
96
|
+
top: { top: -30, left: '50%', transform: 'translate(-50%,0)' },
|
|
97
|
+
right: { right: -30, top: '50%', transform: 'translate(0, -50%)' },
|
|
98
|
+
bottom: { bottom: -30, left: '50%', transform: 'translate(-50%,0)' },
|
|
99
|
+
left: { left: -30, top: '50%', transform: 'translate(0, -50%)' },
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export function OffscreenElements() {
|
|
103
|
+
const target01 = createRef<HTMLDivElement>();
|
|
104
|
+
const target02 = createRef<HTMLDivElement>();
|
|
105
|
+
const target03 = createRef<HTMLDivElement>();
|
|
106
|
+
const target04 = createRef<HTMLDivElement>();
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div style={{ fontFamily: 'sans-serif', height: '100%' }}>
|
|
110
|
+
<div style={{ position: 'relative', width: '100%', height: '100%', overflow: 'hidden' }}>
|
|
111
|
+
<div ref={target01} style={{ ...edgeStyles, ...centerStyles.top }}>
|
|
112
|
+
top
|
|
113
|
+
</div>
|
|
114
|
+
<div ref={target02} style={{ ...edgeStyles, ...centerStyles.right }}>
|
|
115
|
+
right
|
|
116
|
+
</div>
|
|
117
|
+
<div ref={target03} style={{ ...edgeStyles, ...centerStyles.bottom }}>
|
|
118
|
+
bottom
|
|
119
|
+
</div>
|
|
120
|
+
<div ref={target04} style={{ ...edgeStyles, ...centerStyles.left }}>
|
|
121
|
+
left
|
|
122
|
+
</div>
|
|
123
|
+
<ElementHighlighter targetRef={target01} components={[MockTarget]} watchMotion />
|
|
124
|
+
<ElementHighlighter targetRef={target02} components={[MockTarget]} watchMotion />
|
|
125
|
+
<ElementHighlighter targetRef={target03} components={[MockTarget]} watchMotion />
|
|
126
|
+
<ElementHighlighter targetRef={target04} components={[MockTarget]} watchMotion />
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { RefObject } from 'react';
|
|
2
|
+
import classnames from 'classnames';
|
|
3
|
+
import { ComponentMetaHolder } from '@teambit/react.ui.highlighter.component-metadata.bit-component-meta';
|
|
4
|
+
import { Frame } from '../frame';
|
|
5
|
+
import { Label, LabelContainer, Placement } from '../label';
|
|
6
|
+
import { skipHighlighterAttr } from '../ignore-highlighter';
|
|
7
|
+
import styles from './element-highlighter.module.scss';
|
|
8
|
+
|
|
9
|
+
export interface ElementHighlighterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
10
|
+
/** highlight this element */
|
|
11
|
+
targetRef: RefObject<HTMLElement | null>;
|
|
12
|
+
/** components with metadata to show in the label */
|
|
13
|
+
components?: (ComponentMetaHolder | string)[];
|
|
14
|
+
|
|
15
|
+
/** default location of the label */
|
|
16
|
+
placement?: Placement;
|
|
17
|
+
/** customize styles */
|
|
18
|
+
classes?: HighlightClasses;
|
|
19
|
+
/** continually update highlighter to match moving elements */
|
|
20
|
+
watchMotion?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Placement };
|
|
24
|
+
|
|
25
|
+
export type HighlightClasses = {
|
|
26
|
+
container?: string;
|
|
27
|
+
frame?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function ElementHighlighter({
|
|
32
|
+
targetRef,
|
|
33
|
+
components,
|
|
34
|
+
placement = 'top',
|
|
35
|
+
watchMotion,
|
|
36
|
+
className,
|
|
37
|
+
classes,
|
|
38
|
+
...props
|
|
39
|
+
}: ElementHighlighterProps) {
|
|
40
|
+
return (
|
|
41
|
+
<div {...props} {...skipHighlighterAttr} className={classnames(classes?.container, styles.container, className)}>
|
|
42
|
+
<Frame targetRef={targetRef} className={classnames(styles.frame, classes?.frame)} watchMotion={watchMotion} />
|
|
43
|
+
|
|
44
|
+
{components && (
|
|
45
|
+
<LabelContainer targetRef={targetRef} className={styles.label} placement={placement} watchMotion={watchMotion}>
|
|
46
|
+
<Label components={components} className={classes?.label} />
|
|
47
|
+
</LabelContainer>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
$border: 2;
|
|
2
|
+
$padding: 4;
|
|
3
|
+
|
|
4
|
+
.overlayBorder {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
border: $border * 1px solid var(--bit-highlighter-color, #eebcc9);
|
|
7
|
+
|
|
8
|
+
border-radius: 11px;
|
|
9
|
+
padding: $padding * 1px;
|
|
10
|
+
|
|
11
|
+
pointer-events: none;
|
|
12
|
+
user-select: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.hidden {
|
|
16
|
+
// the frame's size is ignored anyways,
|
|
17
|
+
// and so we can use 'display: none' and not 'visibility: hidden'
|
|
18
|
+
display: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:export {
|
|
22
|
+
offset: $border + $padding;
|
|
23
|
+
}
|
package/frame/frame.tsx
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import React, { useEffect, useLayoutEffect, useRef, RefObject, CSSProperties } from 'react';
|
|
2
|
+
import classnames from 'classnames';
|
|
3
|
+
import { useFloating, autoUpdate, offset, size, detectOverflow, hide } from '@floating-ui/react-dom';
|
|
4
|
+
import type { Coords } from '@floating-ui/react-dom';
|
|
5
|
+
|
|
6
|
+
import styles from './frame.module.scss';
|
|
7
|
+
|
|
8
|
+
export const useIsomorphicLayoutEffect =
|
|
9
|
+
typeof window !== 'undefined' ? useLayoutEffect : useEffect
|
|
10
|
+
|
|
11
|
+
/** frame padding around the target */
|
|
12
|
+
const MARGIN_FROM_TARGET = +styles.offset || 6; // setting fallback 6, for tests
|
|
13
|
+
/** min. distance from the edge of the screen. */
|
|
14
|
+
const MARGIN_FROM_DOC_EDGE = 0;
|
|
15
|
+
|
|
16
|
+
const overflowParameters = { rootBoundary: 'document', padding: MARGIN_FROM_DOC_EDGE } as const;
|
|
17
|
+
const SHIFT_POSITIVE = 'shiftPositive';
|
|
18
|
+
|
|
19
|
+
const HAS_RESIZE_OBSERVER = typeof window !== 'undefined' && !!window.ResizeObserver;
|
|
20
|
+
|
|
21
|
+
export interface FrameProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
22
|
+
/** apply the frame to this element */
|
|
23
|
+
targetRef: RefObject<HTMLElement | null>;
|
|
24
|
+
/**
|
|
25
|
+
* the specific flavor of the frame.
|
|
26
|
+
* @default "redBorderClass"
|
|
27
|
+
*/
|
|
28
|
+
stylesClass?: string;
|
|
29
|
+
/** continually update frame position to match moving elements */
|
|
30
|
+
watchMotion?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// position - bottom start (bottom left corner)
|
|
34
|
+
// x - width - horizontal (cross axis)
|
|
35
|
+
// y - height - vertical (main axis)
|
|
36
|
+
|
|
37
|
+
type DimensionsStyle = Pick<CSSProperties, 'width' | 'height' | 'maxWidth' | 'maxHeight'>;
|
|
38
|
+
|
|
39
|
+
export function Frame({ targetRef, watchMotion, className, stylesClass = styles.overlayBorder, style }: FrameProps) {
|
|
40
|
+
const dimensionRef = useRef<DimensionsStyle>({ width: 0, height: 0 });
|
|
41
|
+
|
|
42
|
+
const { x, y, strategy, reference, floating, update, refs, middlewareData } = useFloating({
|
|
43
|
+
placement: 'bottom-start',
|
|
44
|
+
middleware: [
|
|
45
|
+
// replace dimensions from previous iterations with the target's size
|
|
46
|
+
// this is only the measured size, not yet the applied size
|
|
47
|
+
{
|
|
48
|
+
name: 'align-to-target',
|
|
49
|
+
fn({ rects }) {
|
|
50
|
+
rects.floating = {
|
|
51
|
+
...rects.floating,
|
|
52
|
+
width: rects.reference.width + 2 * MARGIN_FROM_TARGET,
|
|
53
|
+
height: rects.reference.height + 2 * MARGIN_FROM_TARGET,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return {};
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
// reposition x,y, to the top of the reference
|
|
60
|
+
offset(({ rects }) => -rects.reference.height),
|
|
61
|
+
// offset the frame by its extra padding
|
|
62
|
+
offset(() => ({ mainAxis: -MARGIN_FROM_TARGET, crossAxis: -MARGIN_FROM_TARGET })),
|
|
63
|
+
// pushes the frame into the document. Similar to shift(), but only pushes when coods are negative
|
|
64
|
+
{
|
|
65
|
+
name: 'shiftPositive',
|
|
66
|
+
fn: async (args) => {
|
|
67
|
+
const overflow = await detectOverflow(args, overflowParameters);
|
|
68
|
+
|
|
69
|
+
const nextCoords = {
|
|
70
|
+
x: overflow.left > 0 ? args.x + overflow.left : args.x,
|
|
71
|
+
y: overflow.top > 0 ? args.y + overflow.top : args.y,
|
|
72
|
+
};
|
|
73
|
+
const shiftAmount = {
|
|
74
|
+
x: nextCoords.x - args.x,
|
|
75
|
+
y: nextCoords.y - args.y,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...nextCoords,
|
|
80
|
+
data: shiftAmount,
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
// size also applies overflow detection via width and height
|
|
85
|
+
size({
|
|
86
|
+
// apply overflow detection in reference to the document
|
|
87
|
+
rootBoundary: 'document',
|
|
88
|
+
padding: MARGIN_FROM_DOC_EDGE,
|
|
89
|
+
apply({ elements, rects, availableHeight, availableWidth, middlewareData }) {
|
|
90
|
+
const shift: Coords = middlewareData[SHIFT_POSITIVE] || { x: 0, y: 0 };
|
|
91
|
+
const paddingX = 2 * MARGIN_FROM_TARGET - shift.x;
|
|
92
|
+
const paddingY = 2 * MARGIN_FROM_TARGET - shift.y;
|
|
93
|
+
|
|
94
|
+
const dimensions: DimensionsStyle = {
|
|
95
|
+
width: rects.reference.width + paddingX,
|
|
96
|
+
height: rects.reference.height + paddingY,
|
|
97
|
+
maxWidth: availableWidth,
|
|
98
|
+
maxHeight: availableHeight,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// per floating-ui docs, apply styles directly during apply()
|
|
102
|
+
Object.assign(elements.floating.style, dimensions);
|
|
103
|
+
|
|
104
|
+
// also store in reference, so react renders will have the same value
|
|
105
|
+
dimensionRef.current = dimensions;
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
hide({ strategy: 'referenceHidden' }),
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// set target as floating reference
|
|
113
|
+
useIsomorphicLayoutEffect(() => {
|
|
114
|
+
reference(targetRef.current);
|
|
115
|
+
}, [targetRef.current]);
|
|
116
|
+
|
|
117
|
+
// automatically update on scroll, resize, etc.
|
|
118
|
+
// `watchMotion` will trigger continuous updates using animation frame
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (!refs.reference.current || !refs.floating.current || !HAS_RESIZE_OBSERVER) return () => {};
|
|
121
|
+
|
|
122
|
+
return autoUpdate(refs.reference.current, refs.floating.current, update, { animationFrame: watchMotion });
|
|
123
|
+
}, [refs.reference.current, refs.floating.current, update, watchMotion]);
|
|
124
|
+
|
|
125
|
+
// could check if x !== null
|
|
126
|
+
const isReady = !middlewareData.hide?.referenceHidden;
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div
|
|
130
|
+
ref={floating}
|
|
131
|
+
className={classnames(className, stylesClass, !isReady && styles.hidden)}
|
|
132
|
+
style={{
|
|
133
|
+
...style,
|
|
134
|
+
...dimensionRef.current,
|
|
135
|
+
position: strategy,
|
|
136
|
+
// starting at pos [0,0] will ensure the label doesn't increase the document size.
|
|
137
|
+
top: y ?? 0,
|
|
138
|
+
left: x ?? 0,
|
|
139
|
+
}}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
}
|
package/frame/index.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { MockTarget } from '../mock-component';
|
|
4
|
+
import { bubbleToComponent } from './bubble-to-component';
|
|
5
|
+
|
|
6
|
+
it('should find component when starting from a div', () => {
|
|
7
|
+
const { getByText, getByTestId } = render(
|
|
8
|
+
<MockTarget data-testid="expected-result">
|
|
9
|
+
<div>hello world</div>
|
|
10
|
+
</MockTarget>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const rendered = getByText('hello world');
|
|
14
|
+
|
|
15
|
+
const result = bubbleToComponent(rendered);
|
|
16
|
+
|
|
17
|
+
expect(result?.element).toBe(getByTestId('expected-result'));
|
|
18
|
+
expect(result?.components).toEqual([MockTarget]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should bubble to root component when it renders itself recursively', () => {
|
|
22
|
+
const { getByText, getByTestId } = render(
|
|
23
|
+
<MockTarget data-testid="expected-result">
|
|
24
|
+
<MockTarget>
|
|
25
|
+
<MockTarget>
|
|
26
|
+
<div>hello world</div>
|
|
27
|
+
</MockTarget>
|
|
28
|
+
</MockTarget>
|
|
29
|
+
</MockTarget>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const rendered = getByText('hello world');
|
|
33
|
+
|
|
34
|
+
const result = bubbleToComponent(rendered);
|
|
35
|
+
|
|
36
|
+
expect(result?.element).toBe(getByTestId('expected-result'));
|
|
37
|
+
expect(result?.components).toEqual([MockTarget]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should find first component, when parent propagation is disabled', () => {
|
|
41
|
+
const { getByText, getByTestId } = render(
|
|
42
|
+
<MockTarget>
|
|
43
|
+
<MockTarget>
|
|
44
|
+
<MockTarget data-testid="expected-result">
|
|
45
|
+
<div>hello world</div>
|
|
46
|
+
</MockTarget>
|
|
47
|
+
</MockTarget>
|
|
48
|
+
</MockTarget>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const rendered = getByText('hello world');
|
|
52
|
+
|
|
53
|
+
const result = bubbleToComponent(rendered, { propagateSameParents: false });
|
|
54
|
+
|
|
55
|
+
expect(result?.element).toBe(getByTestId('expected-result'));
|
|
56
|
+
expect(result?.components).toEqual([MockTarget]);
|
|
57
|
+
});
|