Skip to content

Commit

Permalink
Add share menu item in header
Browse files Browse the repository at this point in the history
  • Loading branch information
baktiaditya committed Jun 7, 2021
1 parent d55cc10 commit ff89542
Show file tree
Hide file tree
Showing 17 changed files with 1,061 additions and 19 deletions.
2 changes: 1 addition & 1 deletion @types/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare module '*.woff2';
declare module '*.txt';

declare module 'cother' {
export type Pane = 'html' | 'css' | 'javascript' | 'output';
export type Pane = 'html' | 'css' | 'javascript' | 'result';

export type ReduxState = {
app: {
Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"build": "next build && next export",
"serve": "next start",
"serve-static": "serve -c serve.json",
"deploy-firebase": "node run deploy"
"deploy-firebase": "node run deploy",
"lint": "tsc --noEmit && eslint --ext .ts --ext .tsx src/"
},
"dependencies": {
"@emotion/react": "^11.4.0",
Expand All @@ -18,6 +19,8 @@
"@fortawesome/free-regular-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14",
"@popperjs/core": "^2.9.2",
"copy-to-clipboard": "^3.3.1",
"css-element-queries": "^1.2.3",
"facepaint": "^1.2.1",
"lodash": "^4.17.21",
Expand All @@ -28,14 +31,18 @@
"react": "17.0.2",
"react-dom": "17.0.2",
"react-ga": "^3.3.0",
"react-popper": "^2.2.5",
"react-redux": "^7.2.4",
"react-transition-group": "^4.4.2",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@types/facepaint": "^1.2.1",
"@types/lodash": "^4.14.170",
"@types/qs": "^6.9.6",
"@types/react": "17.0.6",
"@types/react-dom": "^17.0.6",
"@types/react-transition-group": "^4.4.1",
"@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0",
"eslint": "^7.27.0",
Expand Down
193 changes: 193 additions & 0 deletions src/components/base/popper-content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/* eslint-disable no-console */
// https://dev.to/tannerhallman/using-usepopper-to-create-a-practical-dropdown-5bf8
import React from 'react';
import ReactDOM from 'react-dom';
import { Placement } from '@popperjs/core';
import { Popper as ReactPopper } from 'react-popper';
import { CSSTransitionProps } from 'react-transition-group/CSSTransition';
import { CSSTransition } from 'react-transition-group';
import merge from 'lodash/merge';
import { useTheme } from '@emotion/react';
import { isBrowser, useDidMount, useDidUpdate, usePrevious } from 'src/utils';

export type PopperContentProps = React.HTMLAttributes<HTMLDivElement> & {
arrow?: boolean;
arrowClassName?: string;
className?: string;
fallbackPlacements?: Array<Placement>;
inline?: boolean;
log?: boolean;
open?: boolean;
placement?: Placement;
target: HTMLElement | SVGElement;
transition?: CSSTransitionProps;
};

type State = {
open: boolean;
};

const PopperContent = React.forwardRef<HTMLElement, PopperContentProps>((props, ref) => {
const {
arrow = true,
arrowClassName,
children,
className,
fallbackPlacements = [
'top',
'top-start',
'top-end',
'right',
'right-start',
'right-end',
'bottom',
'bottom-start',
'bottom-end',
'left',
'left-start',
'left-end',
],
inline = false,
log = false,
open = false,
placement = 'auto',
target,
transition: _transition,
...rest
} = props;
const [state, setState] = React.useState<State>({ open: false });
const theme = useTheme();
const prevProps = usePrevious<PopperContentProps>(props);
const elementRef = React.useRef<HTMLDivElement>(null);
const transitionDefault: CSSTransitionProps = {
appear: true,
enter: true,
exit: true,
timeout: theme.animation.timing.normal,
classNames: {
appear: 'appear',
appearActive: 'appear-active',
appearDone: 'appear-done',
enter: 'enter',
enterActive: 'enter-active',
enterDone: 'enter-done',
exit: 'exit',
exitActive: 'exit-active',
exitDone: 'exit-done',
},
};
const transition = merge(transitionDefault, _transition);

useDidMount(() => {
if (open) {
setState({ open: true });
}
const element = elementRef.current;
if (element && element.childNodes && element.childNodes[0]) {
const childNodes = element.childNodes[0] as HTMLElement | null;
if (childNodes && 'focus' in childNodes) {
childNodes.focus();
}
}
});

useDidUpdate(() => {
if (prevProps && !prevProps.open && open) {
setState({ open: true });
}
}, [open]);

const handleTransitionExited = (node: HTMLElement) => {
setState({ open: false });
transition.onExited && transition.onExited(node);
};

const renderChildren = () => {
return (
<CSSTransition {...transition} onExited={handleTransitionExited} in={open}>
<ReactPopper
innerRef={ref}
referenceElement={target}
placement={placement}
modifiers={[
{
name: 'offset',
phase: 'main',
options: {
offset: [0, 0],
},
},
{
name: 'flip',
phase: 'main',
options: {
fallbackPlacements,
},
},
{
name: 'computeStyles',
phase: 'beforeWrite',
options: {
gpuAcceleration: false,
adaptive: false,
},
},
{
name: 'topLogger',
enabled: log,
phase: 'main',
fn({ state: _state }) {
console.log('popper state:', _state);
},
},
{
name: 'applyArrowEdge',
enabled: true,
phase: 'write',
fn({ state: _state }) {
const { arrow: _arrow } = _state.elements;

if (_arrow) {
if (_state.modifiersData.arrow && _state.modifiersData.arrow.centerOffset !== 0) {
_arrow.setAttribute('data-edge', '');
} else {
_arrow.removeAttribute('data-edge');
}
}
},
},
]}
>
{({ ref: popperRef, style, placement: _placement, arrowProps }) => {
return (
<div
{...rest}
ref={popperRef}
className={className}
style={style}
data-placement={_placement}
>
{children}
{arrow && (
<div ref={arrowProps.ref} className={arrowClassName} style={arrowProps.style} />
)}
</div>
);
}}
</ReactPopper>
</CSSTransition>
);
};

if (isBrowser && state.open) {
if (inline) {
return renderChildren();
} else {
return ReactDOM.createPortal(<div ref={elementRef}>{renderChildren()}</div>, document.body);
}
}

return null;
});

export default PopperContent;
Loading

0 comments on commit ff89542

Please sign in to comment.