Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add point api #425

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/demos/show-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: ShowComponent
nav:
title: Demo
path: /demo
---

<code src="../examples/show-component.tsx"></code>
8 changes: 8 additions & 0 deletions docs/demos/show.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Show
nav:
title: Demo
path: /demo
---

<code src="../examples/show.tsx"></code>
75 changes: 75 additions & 0 deletions docs/examples/show-component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import Trigger from '@/index';

const builtinPlacements = {
topLeft: {
points: ['tl', 'tl'],
},
};

const innerTrigger = (
<div style={{ padding: 20, background: 'rgba(0, 255, 0, 0.3)' }}>This is popup</div>
);

class Test extends React.Component {
state = {
mouseX: 600,
mouseY: 300,
};

onMouseXChange = ({ target: { value } }) => {
this.setState({ mouseX: Number(value) || 0 });
};

onMouseYChange = ({ target: { value } }) => {
this.setState({ mouseY: Number(value) || 0 });
};

show = ()=>{
this.forceUpdate();
}

render() {
const { mouseX,mouseY } = this.state;

return (
<div>
<label>
Show Point:{' '}
<input type="text" value={mouseX} onChange={this.onMouseXChange} />
<input type="text" value={mouseY} onChange={this.onMouseYChange} />
</label>
<label>
<button onClick={this.show}>show</button>
</label>
<Trigger
popupPlacement="topLeft"
action={['contextMenu']}
popupAlign={{
overflow: {
adjustX: 1,
adjustY: 1,
},
}}
popupClassName="point-popup"
builtinPlacements={builtinPlacements}
popup={innerTrigger}
alignPoint
point={[this.state.mouseX,this.state.mouseY]}
>
<div
style={{
border: '1px solid red',
padding: '100px 0',
textAlign: 'center',
}}
>
Interactive region
</div>
</Trigger>
</div>
);
}
}

export default Test;
67 changes: 67 additions & 0 deletions docs/examples/show.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import { triggerShow } from '@/show';

const builtinPlacements = {
topLeft: {
points: ['tl', 'tl'],
},
};

const innerTrigger = (
<div style={{ padding: 20, background: 'rgba(0, 255, 0, 0.3)' }}>This is popup</div>
);

class Test extends React.Component {
state = {
mouseX: 600,
mouseY: 300,
};

onMouseXChange = ({ target: { value } }) => {
this.setState({ mouseX: Number(value) || 0 });
};

onMouseYChange = ({ target: { value } }) => {
this.setState({ mouseY: Number(value) || 0 });
};

show = ()=>{
triggerShow.show({
point: [this.state.mouseX, this.state.mouseY],
popup: innerTrigger,
builtinPlacements,
popupClassName:'point-popup',
popupAlign:{
overflow: {
adjustX: 1,
adjustY: 1,
},
},
popupPlacement:'topLeft'
})
}

hide = () => {
triggerShow.hide();
}

render() {
const { mouseX,mouseY } = this.state;

return (
<div>
<label>
Show Point:{' '}
<input type="text" value={mouseX} onChange={this.onMouseXChange} />
<input type="text" value={mouseY} onChange={this.onMouseYChange} />
</label>
<label>
<button onClick={this.show}>show</button>
<button onClick={this.hide}>hide</button>
</label>
</div>
);
}
}

export default Test;
16 changes: 14 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export interface TriggerProps {
onPopupClick?: React.MouseEventHandler<HTMLDivElement>;

alignPoint?: boolean; // Maybe we can support user pass position in the future
point?: [x: number, y: number];

/**
* Trigger will memo content when close.
Expand Down Expand Up @@ -189,6 +190,7 @@ export function generateTrigger(
fresh,

alignPoint,
point,

onPopupClick,
onPopupAlign,
Expand Down Expand Up @@ -347,6 +349,14 @@ export function generateTrigger(

React.useEffect(() => clearDelay, []);

React.useEffect(()=>{
if (point){
queueMicrotask(()=>{
triggerOpen(true);
})
}
},[point])

// ========================== Motion ============================
const [inMotion, setInMotion] = React.useState(false);

Expand All @@ -363,14 +373,16 @@ export function generateTrigger(
React.useState<VoidFunction>(null);

// =========================== Align ============================
const [mousePos, setMousePos] = React.useState<[x: number, y: number]>([
const [mousePos, setMousePos] = React.useState<[x: number, y: number]>(point ?? [
0, 0,
]);

const setMousePosByEvent = (
event: Pick<React.MouseEvent, 'clientX' | 'clientY'>,
) => {
setMousePos([event.clientX, event.clientY]);
if (!point){
setMousePos([event.clientX, event.clientY]);
}
};

const [
Expand Down
47 changes: 47 additions & 0 deletions src/show.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import type { TriggerProps } from './index';
import Trigger from './index';
import type { Root } from 'react-dom/client';
import { createRoot } from 'react-dom/client';

export interface ShowProps extends Omit<TriggerProps, 'children'> {
point: [x: number, y: number];
}

export class TriggerShow {
public container = document.createElement('div');
public root?: Root;

public constructor() {
this.container.id = 'trigger-show-container';
document.body.append(this.container);
}

public show(props: ShowProps) {
if (this.root) {
this.root.unmount();
}
this.root = createRoot(this.container);
this.root.render(
<Trigger
popupPlacement='topLeft'
popupAlign={{
overflow: {
adjustX: 1,
adjustY: 1,
},
}}
popupClassName='point-popup'
{...props}
alignPoint
point={props.point}>
<div />
</Trigger>);
}

public hide() {
this.root?.unmount();
}
}

export const triggerShow = new TriggerShow();