react-use#useMeasure TypeScript Examples
The following examples show how to use
react-use#useMeasure.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Reveal.tsx From covid19map with MIT License | 5 votes |
Reveal = ({
button,
full,
open,
toggle,
children,
}: {
button: any;
full: boolean;
open: boolean;
toggle: (open: boolean) => void;
children: React.ReactNode;
}) => {
const defaultHeight = 0;
// if (!open && !toggle) {
// [open, toggle] = useState(false);
// }
const [contentHeight, setContentHeight] = useState<number>(defaultHeight);
const [ref, { height }] = useMeasure();
// Animations
const expand = useSpring({
// config: {
// friction: 10,
// duration: 300,
// },
height: open ? `${contentHeight}px` : defaultHeight,
});
useEffect(() => {
//Sets initial height
setContentHeight(height);
//Adds resize event listener
// window.addEventListener("resize", setContentHeight(height));
// return window.removeEventListener("resize", setContentHeight(height));
}, [height]);
return (
<>
{button && (
<InvisibleButton
onClick={() => {
toggle(!open);
}}
active={open}
>
{button}
</InvisibleButton>
)}
<Container full={full}>
<animated.div style={expand}>
<div ref={ref}>{children}</div>
</animated.div>
</Container>
</>
);
}
Example #2
Source File: index.tsx From polkabtc-ui with Apache License 2.0 | 5 votes |
Layout = ({ children }: Props): JSX.Element => {
const address = useSelector((state: StoreType) => state.general.address);
const location = useLocation();
const [ref, { height: footerHeight }] = useMeasure<HTMLDivElement>();
const handleRequestDotFromFaucet = async (): Promise<void> => {
// TODO: should show a descriptive warning
if (!address) return;
try {
const receiverId = window.polkaBTC.api.createType(ACCOUNT_ID_TYPE_NAME, address);
await window.faucet.fundAccount(receiverId);
toast.success('Your account has been funded.');
} catch (error) {
toast.error(`Funding failed. ${error.message}`);
}
};
/**
* TODO: a hack for now.
* - Should apply the gradient on the landing page
*/
const isHomePage = location.pathname === PAGES.home;
return (
<div
style={{
// TODO: should avoid hard-coding colors (https://tailwindcss.com/docs/gradient-color-stops)
backgroundImage:
isHomePage ?
// eslint-disable-next-line max-len
'linear-gradient(to right bottom, #e1106d, #e52766, #e83761, #ea445b, #eb5157, #ed5952, #ef624e, #f06a4a, #f37143, #f4783c, #f58035, #f5882d)' :
'unset'
}}
className={clsx(
'relative',
'min-h-screen'
)}>
<main
style={{ paddingBottom: footerHeight }}
className={clsx(
'flex',
'flex-col'
)}>
{!checkStaticPage() && (
<Topbar
address={address}
requestDOT={handleRequestDotFromFaucet} />
)}
{!isHomePage && <TestnetBanner />}
{!isHomePage && <MaintenanceBanner />}
{children}
</main>
<Footer
ref={ref}
className={clsx(
'absolute',
'bottom-0',
'w-full',
'shadow',
'border-t'
)} />
</div>
);
}
Example #3
Source File: CardGrid.tsx From oxen-website with GNU General Public License v3.0 | 5 votes |
export function CardGrid({ rows, children }: Props) {
const { isDesktop, isHuge } = useContext(ScreenContext);
const [ref, { width }] = useMeasure();
const widthOfCardPx = 200;
const grouping = Math.max(1, Math.min(4, Math.floor(width / widthOfCardPx)));
const numPaddingCards =
Math.ceil(children.length / grouping) * grouping - children.length;
const spacing = isHuge ? 3 : isDesktop ? 6 : 4;
const spacingY = `space-y-${spacing}`;
const spacingX = `space-x-${spacing}`;
const items =
rows && rows > 0 ? children.slice(0, grouping * rows) : children;
// Add cards to ensure we fill up each row. Hidden where the row is incomplete
// to keep even widths
const cards = [
...items,
...Array.from(Array(numPaddingCards).keys()).map(i => <div key={i}></div>),
];
return (
<>
{
<Contained>
<div ref={ref} className={classNames('flex flex-col', spacingY)}>
{_.chunk(cards, grouping).map(group => (
<div key={uuid()} className={classNames('flex w-full', spacingX)}>
{group.map(item => (
<div key={uuid()} className="flex-1">
{item}
</div>
))}
</div>
))}
</div>
</Contained>
}
</>
);
}
Example #4
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
export function TraceGraph(props: IProps) {
const { dataSource } = props;
const width = dataSource?.depth <= 12 ? 300 : dataSource?.depth * 24 + 100;
const bg = ['#4E6097', '#498E9E', '#6CB38B', 'purple', '#F7A76B'];
const errorColor = '#CE4324';
// const bg = ['#5872C0', '#ADDD8B', '#DE6E6A', '#84BFDB', '#599F76', '#ED895D', '#9165AF','#DC84C8','#F3C96B'];
const [expandedKeys, setExpandedKeys] = React.useState([] as string[]);
const [selectedTimeRange, setSelectedTimeRange] = React.useState(null! as ITimeRange);
const [proportion, setProportion] = React.useState([24, 0]);
const [loading, setLoading] = React.useState(false);
const [spanDetailData, setSpanDetailData] = React.useState({});
const { roots, min, max } = listToTree(dataSource?.spans);
const [tags, setTags] = React.useState(null! as MONITOR_TRACE.ITag);
const [spanStartTime, setSpanStartTime] = React.useState(null! as number);
const [timeRange, setTimeRange] = React.useState([null!, null!] as number[]);
const [selectedSpanId, setSelectedSpanId] = React.useState(null! as string);
const [view, setView] = React.useState('waterfall');
const [spanData, spanDataLoading] = getSpanEvents.useState();
const spanDataSource = spanData?.spanEvents || [];
const duration = max - min;
const allKeys: string[] = [];
const { serviceAnalysis } = (spanDetailData as MONITOR_TRACE.ISpanRelationChart) || {};
const [flameRef, { width: flameWidth }] = useMeasure();
const containerRef = React.useRef(null);
const [tooltipState, setTooltipState] = React.useState(
null as { content: MONITOR_TRACE.FlameChartData; mouseX: number; mouseY: number } | null,
);
function getMousePos(
relativeContainer: { getBoundingClientRect: () => DOMRect } | null,
mouseEvent: { clientX: number; clientY: number },
) {
if (relativeContainer !== null) {
const rect = relativeContainer.getBoundingClientRect();
const mouseX = mouseEvent.clientX - rect.left;
const mouseY = mouseEvent.clientY - rect.top;
return { mouseX, mouseY };
} else {
return { mouseX: 0, mouseY: 0 };
}
}
const onMouseOver = (event: { clientX: number; clientY: number }, data: MONITOR_TRACE.FlameChartData) => {
const { name, value, children, serviceName, selfDuration, spanKind, component } = data;
setTooltipState({
content: { name, value, children, serviceName, selfDuration, spanKind, component },
...getMousePos(containerRef.current, event),
});
};
const onMouseOut = () => {
setTooltipState(null);
};
const tooltipRef = useSmartTooltip({
mouseX: tooltipState === null ? 0 : tooltipState.mouseX,
mouseY: tooltipState === null ? 0 : tooltipState.mouseY,
});
const columns = [
{
title: i18n.t('Time'),
dataIndex: 'timestamp',
render: (time: number) => moment(time / 1000 / 1000).format('YYYY-MM-DD HH:mm:ss'),
},
{
title: i18n.t('msp:Event'),
dataIndex: 'events',
ellipsis: true,
render: (events: object) => (
<div>
{Object.keys(events).map((k) => (
<Ellipsis title={`${k}: ${events[k]}`} key={k} />
))}
</div>
),
},
];
const getMetaData = React.useCallback(async () => {
setLoading(true);
try {
const { span_layer, span_kind, terminus_key, service_instance_id } = tags;
const type = `${span_layer}_${span_kind}`;
if (!service_instance_id) {
return null;
}
const { success, data } = await getSpanAnalysis({
type,
startTime: timeRange[0],
endTime: timeRange[1],
serviceInstanceId: service_instance_id,
tenantId: terminus_key,
});
if (success) {
setSpanDetailData(data);
}
} finally {
setLoading(false);
}
}, [tags, timeRange]);
React.useEffect(() => {
if (tags) {
getMetaData();
}
}, [getMetaData, tags]);
React.useEffect(() => {
handleTableChange();
}, [selectedSpanId, spanStartTime]);
const handleTableChange = () => {
if (selectedSpanId && spanStartTime) {
getSpanEvents.fetch({
startTime: Math.floor(spanStartTime),
spanId: selectedSpanId,
});
}
};
const traverseData = (data: MONITOR_TRACE.ITraceSpan[]) => {
for (let i = 0; i < data.length; i++) {
data[i] = format(data[i], 0, handleClickTimeSpan);
}
return data;
};
const handleChangeView = (e: RadioChangeEvent) => {
setView(e.target.value);
};
const treeData = traverseData(roots);
const formatDashboardVariable = (conditions: string[]) => {
const dashboardVariable = {};
for (let i = 0; i < conditions?.length; i++) {
dashboardVariable[conditions[i]] = tags?.[conditions[i]];
}
return dashboardVariable;
};
function handleClickTimeSpan(startTime: number, selectedTag: MONITOR_TRACE.ITag, id: string) {
const r1 = moment(startTime / 1000 / 1000)
.subtract(15, 'minute')
.valueOf();
const r2 = Math.min(
moment(startTime / 1000 / 1000)
.add(15, 'minute')
.valueOf(),
moment().valueOf(),
);
setSelectedTimeRange({
mode: 'customize',
customize: {
start: moment(r1),
end: moment(r2),
},
});
setTimeRange([r1, r2]);
setTags(selectedTag);
setSpanStartTime(startTime / 1000 / 1000);
setProportion([14, 10]);
setSelectedSpanId(id);
}
function format(
item: MONITOR_TRACE.ISpanItem,
depth = 0,
_handleClickTimeSpan: (startTime: number, selectedTag: MONITOR_TRACE.ITag, id: string) => void,
) {
item.depth = depth;
item.key = item.id;
allKeys.push(item.id);
const { startTime, endTime, duration: totalDuration, selfDuration, operationName, tags: _tags, id } = item;
const { span_kind: spanKind, component, error, service_name: serviceName } = _tags;
const leftRatio = (startTime - min) / duration;
const centerRatio = (endTime - startTime) / duration;
const rightRatio = (max - endTime) / duration;
const showTextOnLeft = leftRatio > 0.2;
const showTextOnRight = !showTextOnLeft && rightRatio > 0.2;
const displayTotalDuration = mkDurationStr(totalDuration / 1000);
item.title = (
<div
className="wrapper flex items-center"
onClick={() => {
_handleClickTimeSpan(startTime, _tags, id);
}}
>
<Tooltip
title={
<SpanTitleInfo
operationName={operationName}
spanKind={spanKind}
component={component}
serviceName={serviceName}
/>
}
>
<div className="left flex items-center" style={{ width: width - 24 * depth }}>
<div className="w-1 h-4 relative mr-1" style={{ background: error ? errorColor : bg[depth % 5] }} />
<div className="flex items-center w-full">
<span className="font-semibold text-ms mr-2 whitespace-nowrap">{serviceName}</span>
<span className="truncate text-xs">{operationName}</span>
</div>
</div>
</Tooltip>
<div className="right text-gray">
<div style={{ flex: leftRatio }} className="text-right text-xs self-center">
{showTextOnLeft && displayTotalDuration}
</div>
<Tooltip title={<SpanTimeInfo totalSpanTime={totalDuration} selfSpanTime={selfDuration} />}>
<div
style={{ flex: centerRatio < 0.01 ? 0.01 : centerRatio, background: error ? errorColor : bg[depth % 5] }}
className="rounded-sm mx-1"
/>
</Tooltip>
<div style={{ flex: rightRatio }} className="self-center text-left text-xs">
{showTextOnRight && displayTotalDuration}
</div>
</div>
</div>
);
if (item.children) {
item.children = item.children.map((x) => format(x, depth + 1, _handleClickTimeSpan));
}
return item;
}
const formatFlameData = () => {
let flameData = {} as MONITOR_TRACE.FlameChartData;
if (roots?.length === 1) {
const { operationName, duration: totalDuration, tags: _tags, selfDuration } = roots[0];
const { service_name, span_kind, component } = _tags;
flameData = {
name: operationName,
value: totalDuration,
children: [],
serviceName: service_name,
selfDuration,
spanKind: span_kind,
component,
};
forEach(roots[0].children, (span) => flameData.children.push(formatFlameDataChild(span)));
} else {
flameData = {
name: 'root',
value: dataSource?.duration,
children: [],
serviceName: '',
selfDuration: dataSource?.duration,
spanKind: '',
component: '',
};
forEach(roots, (span) => flameData.children.push(formatFlameDataChild(span)));
}
return flameData;
};
const formatFlameDataChild = (span: MONITOR_TRACE.ISpanItem) => {
let node = {} as MONITOR_TRACE.FlameChartData;
const { operationName, duration: totalDuration, tags: _tags, selfDuration } = span;
const { service_name, span_kind, component } = _tags;
node = {
name: operationName,
value: totalDuration,
children: [],
serviceName: service_name,
selfDuration,
spanKind: span_kind,
component,
};
if (span && span.children) {
for (const item of span.children) {
const child = formatFlameDataChild(item);
node.children.push(child);
}
}
return node;
};
const onExpand = (keys: string[]) => {
setExpandedKeys(keys);
};
return (
<>
<TraceDetailInfo dataSource={dataSource} />
<RadioGroup defaultValue="waterfall" value={view} onChange={handleChangeView} className="flex justify-end">
<RadioButton value="waterfall">
<span className="flex items-center">
<ErdaIcon className="mr-1" type="pubutu" color="currentColor" />
{i18n.t('msp:Waterfall Chart')}
</span>
</RadioButton>
<RadioButton value="flame">
<span className="flex items-center">
<ErdaIcon className="mr-1" type="huoyantu" color="currentColor" />
{i18n.t('msp:Flame Graph')}
</span>
</RadioButton>
</RadioGroup>
<div className="mt-4 trace-span-detail" ref={flameRef}>
{view === 'waterfall' && (
<Row gutter={20}>
<Col span={proportion[0]} className={`${proportion[0] !== 24 ? 'pr-0' : ''}`}>
<TraceHeader
duration={duration}
width={width}
setExpandedKeys={setExpandedKeys}
allKeys={allKeys}
expandedKeys={expandedKeys}
/>
<div className="trace-graph">
{treeData.length > 0 && (
<Tree
showLine={{ showLeafIcon: false }}
defaultExpandAll
height={window.innerHeight - 200}
// switcherIcon={<DownOutlined />}
// switcherIcon={<CustomIcon type="caret-down" />}
expandedKeys={expandedKeys}
treeData={treeData}
onExpand={onExpand}
/>
)}
</div>
</Col>
<Col span={proportion[1]} className={`${proportion[0] !== 24 ? 'pl-0' : ''}`}>
<div className="flex justify-between items-center my-2 px-3 py-1">
<div className="text-sub text-sm font-semibold w-5/6">
<Ellipsis title={tags?.operation_name}>{tags?.operation_name}</Ellipsis>
</div>
<Tooltip title={i18n.t('close')}>
<span onClick={() => setProportion([24, 0])} className="cursor-pointer">
<CustomIcon type="gb" className="text-holder" />
</span>
</Tooltip>
</div>
<div className="px-3">
{selectedTimeRange && (
<TimeSelect
// defaultValue={globalTimeSelectSpan.data}
// className={className}
onChange={(data, range) => {
if (Object.keys(data)?.length !== 0) {
setSelectedTimeRange(data);
}
const { quick = '' } = data;
let range1 = range?.[0]?.valueOf() || selectedTimeRange?.customize?.start?.valueOf();
let range2 = range?.[1]?.valueOf() || selectedTimeRange?.customize?.end?.valueOf();
if (quick) {
const [unit, count] = quick.split(':');
const [start, end] = translateRelativeTime(unit, Number(count));
range1 = start?.valueOf();
range2 = Math.min(end?.valueOf(), moment().valueOf());
}
setTimeRange([range1, range2]);
}}
value={selectedTimeRange}
/>
)}
</div>
{(serviceAnalysis || proportion[0] === 14) && (
<div className="px-3 trace-detail-chart" style={{ height: window.innerHeight - 200 }}>
<Tabs>
<TabPane tab={i18n.t('msp:Attributes')} key={1}>
<KeyValueList data={tags} />
</TabPane>
<TabPane tab={i18n.t('msp:Events')} key={2}>
<Spin spinning={spanDataLoading}>
<ErdaTable columns={columns} dataSource={spanDataSource} onChange={handleTableChange} />
</Spin>
</TabPane>
<TabPane tab={i18n.t('msp:Related Services')} key={3}>
{!serviceAnalysis?.dashboardId && <EmptyHolder relative />}
{serviceAnalysis?.dashboardId && (
<ServiceListDashboard
timeSpan={{ startTimeMs: timeRange[0], endTimeMs: timeRange[1] }}
dashboardId={serviceAnalysis?.dashboardId}
extraGlobalVariable={formatDashboardVariable(serviceAnalysis?.conditions)}
/>
)}
</TabPane>
</Tabs>
</div>
)}
</Col>
</Row>
)}
{view === 'flame' && (
<div ref={containerRef} className="relative graph-flame overflow-y-auto overflow-x-hidden">
<FlameGraph
data={formatFlameData()}
height={dataSource ? 20 * dataSource.depth + 1 : 200}
width={flameWidth}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
disableDefaultTooltips
/>
{tooltipState !== null && (
<div ref={tooltipRef} className="absolute bg-default p-2 shadow-lg break-words rounded-[3px]">
<SpanTitleInfo
operationName={tooltipState?.content.name}
spanKind={tooltipState?.content.spanKind}
component={tooltipState?.content.component}
serviceName={tooltipState?.content.serviceName}
/>
<div className="text-white">
{i18n.t('current')} span {mkDurationStr(tooltipState?.content.selfDuration / 1000)} -{' '}
{i18n.t('total')} span {mkDurationStr(tooltipState?.content.value / 1000)}
</div>
</div>
)}
</div>
)}
</div>
</>
);
}
Example #5
Source File: ArticleCard.tsx From oxen-website with GNU General Public License v3.0 | 4 votes |
export function ArticleCard(props: IPost): JSX.Element {
const {
title,
description,
subtitle,
featureImage,
publishedDate,
author,
slug,
} = props;
const router = useRouter();
const [ref, { width }] = useMeasure();
const isSmall = width < 130;
const { href, as } = generateURL(slug);
// Order tags such that the search tag appears first
const searchTag = String(router.query?.tag);
const tags = props.tags?.find(t => t === searchTag)
? [searchTag, ...props.tags.filter(t => t !== searchTag)]
: props.tags;
return (
<div
ref={ref}
style={{ wordBreak: 'break-word' }}
className={classNames(
'overflow-hidden w-full bg-opacity-75',
isSmall ? 'pb-3' : 'pb-1',
)}
>
<Link href={href} as={as}>
<a>
<div
className={classNames(
'relative cursor-pointer aspect-w-16 aspect-h-9',
)}
>
{featureImage?.imageUrl && (
<Image
src={`${featureImage?.imageUrl}?w=600`}
alt={featureImage?.description ?? title}
layout="fill"
quality={100}
lazyBoundary={`500px 200px`}
className="object-cover"
/>
)}
</div>
</a>
</Link>
<div>
<div className={isSmall ? 'py-1' : 'py-3'}>
<Link href={href} as={as}>
<a>
<p
className={classNames(
isSmall ? 'text-base' : 'text-lg',
'font-sans overflow-hidden cursor-pointer mb-3 hover:underline leading-none text-primary',
)}
>
{title}
</p>
</a>
</Link>
<p
style={{
height: '4em',
paddingBottom: '2.1em',
}}
className="mt-1 overflow-hidden text-xs leading-none text-gray-800"
>
{description?.substr(0, 250) ?? subtitle}...
</p>
<div className="flex flex-col space-y-1">
<p className="mt-2 font-sans text-xs text-gray-800">
{publishedDate} — {author?.name}
</p>
<TagRow tags={tags} limit={3} />
</div>
</div>
</div>
</div>
);
}