@ta-interaktiv/react-annotated-content
Version:
Component to render annotations above other content
705 lines (695 loc) • 32.2 kB
JavaScript
import React, { useState, useRef, useEffect, useCallback, isValidElement, cloneElement, useId } from 'react';
import styled from 'styled-components';
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
}typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var FUNC_ERROR_TEXT = 'Expected a function';
var NAN = 0 / 0;
var symbolTag = '[object Symbol]';
var reTrim = /^\s+|\s+$/g;
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
var reIsBinary = /^0b[01]+$/i;
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
var root = freeGlobal || freeSelf || Function('return this')();
var objectProto = Object.prototype;
var objectToString = objectProto.toString;
var nativeMax = Math.max,
nativeMin = Math.min;
var now = function() {
return root.Date.now();
};
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
result,
timerId,
lastCallTime,
lastInvokeTime = 0,
leading = false,
maxing = false,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs,
thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
lastInvokeTime = time;
timerId = setTimeout(timerExpired, wait);
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime,
result = wait - timeSinceLastCall;
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime;
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
function isObject(value) {
var type = typeof value;
return !!value && (type == 'object' || type == 'function');
}
function isObjectLike(value) {
return !!value && typeof value == 'object';
}
function isSymbol(value) {
return typeof value == 'symbol' ||
(isObjectLike(value) && objectToString.call(value) == symbolTag);
}
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
var lodash_debounce = debounce;
getDefaultExportFromCjs(lodash_debounce);
function useIntersectionObserver({
threshold = 0,
root = null,
rootMargin = "0%",
freezeOnceVisible = false,
initialIsIntersecting = false,
onChange
} = {}) {
var _a;
const [ref, setRef] = useState(null);
const [state, setState] = useState(() => ({
isIntersecting: initialIsIntersecting,
entry: void 0
}));
const callbackRef = useRef();
callbackRef.current = onChange;
const frozen = ((_a = state.entry) == null ? void 0 : _a.isIntersecting) && freezeOnceVisible;
useEffect(() => {
if (!ref)
return;
if (!("IntersectionObserver" in window))
return;
if (frozen)
return;
let unobserve;
const observer = new IntersectionObserver(
(entries) => {
const thresholds = Array.isArray(observer.thresholds) ? observer.thresholds : [observer.thresholds];
entries.forEach((entry) => {
const isIntersecting = entry.isIntersecting && thresholds.some((threshold2) => entry.intersectionRatio >= threshold2);
setState({ isIntersecting, entry });
if (callbackRef.current) {
callbackRef.current(isIntersecting, entry);
}
if (isIntersecting && freezeOnceVisible && unobserve) {
unobserve();
unobserve = void 0;
}
});
},
{ threshold, root, rootMargin }
);
observer.observe(ref);
return () => {
observer.disconnect();
};
}, [
ref,
JSON.stringify(threshold),
root,
rootMargin,
frozen,
freezeOnceVisible
]);
const prevRef = useRef(null);
useEffect(() => {
var _a2;
if (!ref && ((_a2 = state.entry) == null ? void 0 : _a2.target) && !freezeOnceVisible && !frozen && prevRef.current !== state.entry.target) {
prevRef.current = state.entry.target;
setState({ isIntersecting: initialIsIntersecting, entry: void 0 });
}
}, [ref, state.entry, freezeOnceVisible, frozen, initialIsIntersecting]);
const result = [
setRef,
!!state.isIntersecting,
state.entry
];
result.ref = result[0];
result.isIntersecting = result[1];
result.entry = result[2];
return result;
}
function useIsMounted() {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
return useCallback(() => isMounted.current, []);
}
var initialSize = {
width: void 0,
height: void 0
};
function useResizeObserver(options) {
const { ref, box = "content-box" } = options;
const [{ width, height }, setSize] = useState(initialSize);
const isMounted = useIsMounted();
const previousSize = useRef({ ...initialSize });
const onResize = useRef(void 0);
onResize.current = options.onResize;
useEffect(() => {
if (!ref.current)
return;
if (typeof window === "undefined" || !("ResizeObserver" in window))
return;
const observer = new ResizeObserver(([entry]) => {
const boxProp = box === "border-box" ? "borderBoxSize" : box === "device-pixel-content-box" ? "devicePixelContentBoxSize" : "contentBoxSize";
const newWidth = extractSize(entry, boxProp, "inlineSize");
const newHeight = extractSize(entry, boxProp, "blockSize");
const hasChanged = previousSize.current.width !== newWidth || previousSize.current.height !== newHeight;
if (hasChanged) {
const newSize = { width: newWidth, height: newHeight };
previousSize.current.width = newWidth;
previousSize.current.height = newHeight;
if (onResize.current) {
onResize.current(newSize);
} else {
if (isMounted()) {
setSize(newSize);
}
}
}
});
observer.observe(ref.current, { box });
return () => {
observer.disconnect();
};
}, [box, ref, isMounted]);
return { width, height };
}
function extractSize(entry, box, sizeType) {
if (!entry[box]) {
if (box === "contentBoxSize") {
return entry.contentRect[sizeType === "inlineSize" ? "width" : "height"];
}
return void 0;
}
return Array.isArray(entry[box]) ? entry[box][0][sizeType] : (
entry[box][sizeType]
);
}
var isDev = window.location.hostname === 'localhost';
var AnnotatedContent = function (_a) {
var children = _a.children, _b = _a.annotations, annotations = _b === void 0 ? [] : _b, _c = _a.className, className = _c === void 0 ? '' : _c, connectorStyle = _a.connectorStyle, _d = _a.shapeStyle, shapeStyle = _d === void 0 ? {} : _d;
var ref = useRef(null);
var _e = useResizeObserver({
ref: ref,
box: 'border-box',
}), _f = _e.width, width = _f === void 0 ? 0 : _f, _g = _e.height, height = _g === void 0 ? 0 : _g;
var validateAnnotation = function (annotation) {
return (annotation.pos.x >= 0 &&
annotation.pos.x <= 100 &&
annotation.pos.y >= 0 &&
annotation.pos.y <= 100);
};
var renderAnnotation = function (annotation, index) {
var _a, _b, _c;
var basePosition = {
position: 'absolute',
left: "".concat(annotation.pos.x, "%"),
top: "".concat(annotation.pos.y, "%"),
};
if (annotation.type === 'custom') {
return (React.createElement("div", { key: (_a = annotation.id) !== null && _a !== void 0 ? _a : index, className: annotation.className, style: __assign(__assign(__assign({}, basePosition), { transform: 'translate(-50%, -50%)' }), annotation.style) }, annotation.content));
}
if (isValidElement(annotation.content)) {
return (React.createElement("div", { key: (_b = annotation.id) !== null && _b !== void 0 ? _b : index, style: basePosition }, cloneElement(annotation.content, __assign(__assign({}, annotation.content.props), { connectorStyle: __assign(__assign({}, connectorStyle), annotation.content.props.connectorStyle), shapeStyle: __assign(__assign({}, shapeStyle), annotation.content.props.shapeStyle), fullSize: [width, height] }))));
}
return (React.createElement("div", { key: (_c = annotation.id) !== null && _c !== void 0 ? _c : index, style: basePosition }, annotation.content));
};
return (React.createElement(AnnotatedImageContainer, { ref: ref, className: "annotated-image ".concat(className).trim(), onClick: function (e) {
if (!isDev)
return;
if (!e.shiftKey) {
var rect = e.currentTarget.getBoundingClientRect();
var x = ((e.clientX - rect.left) / rect.width) * 100;
var y = ((e.clientY - rect.top) / rect.height) * 100;
console.log("{ x: ".concat(x.toFixed(2), ", y: ").concat(y.toFixed(2), " },"));
}
} },
children,
annotations.filter(validateAnnotation).map(renderAnnotation)));
};
var AnnotatedImageContainer = styled.div(templateObject_1$2 || (templateObject_1$2 = __makeTemplateObject(["\n width: 100%;\n position: relative;\n line-height: 0;\n * {\n line-height: 1.2em;\n }\n .annotated-image__image {\n width: 100%;\n height: auto;\n display: block;\n }\n"], ["\n width: 100%;\n position: relative;\n line-height: 0;\n * {\n line-height: 1.2em;\n }\n .annotated-image__image {\n width: 100%;\n height: auto;\n display: block;\n }\n"])));
var templateObject_1$2;
var defaultShapeStyle = {
pattern: 'none',
patternRotation: 45,
patternWidth: 10,
patternSpace: 5,
fill: 'rgba(0,0,0,0.15)',
stroke: 'gray',
strokeWidth: 0.5,
cornerRadius: 10,
};
var AreaAnnotation = function (_a) {
var children = _a.children, _b = _a.shapeType, shapeType = _b === void 0 ? 'circle' : _b, _c = _a.size, size = _c === void 0 ? 5 : _c, _d = _a.rotation, rotation = _d === void 0 ? 0 : _d, customShape = _a.customShape, _e = _a.fullSize, fullSize = _e === void 0 ? [100, 100] : _e, _f = _a.textAnchor, textAnchor = _f === void 0 ? 'center' : _f, _g = _a.offset, offset = _g === void 0 ? 0 : _g, _h = _a.shapeStyle, shapeStyle = _h === void 0 ? {} : _h;
var _j = getOffset$1(offset), h = _j[0], v = _j[1];
var currentShapeStyle = __assign(__assign({}, defaultShapeStyle), shapeStyle);
var pattern = currentShapeStyle.pattern, patternWidth = currentShapeStyle.patternWidth, patternSpace = currentShapeStyle.patternSpace, patternRotation = currentShapeStyle.patternRotation, fill = currentShapeStyle.fill;
var hatchId = Math.random().toString(36).substring(7);
if (shapeType === 'custom' && !customShape) {
console.warn('Custom shape type requires customShape prop. Falling back to circle.');
shapeType = 'circle';
}
var getRotation = function () {
if (shapeType === 'custom')
return 0;
return rotation !== null && rotation !== void 0 ? rotation : 0;
};
var getShapeSize = function () {
if (shapeType === 'custom')
return [0, 0];
return getSize(size !== null && size !== void 0 ? size : 20, fullSize[0], fullSize[1]);
};
var _k = getShapeSize(), sx = _k[0], sy = _k[1];
rotation = getRotation();
var getPatternFill = function () {
switch (pattern) {
case 'hatched':
return "url(#hatched_".concat(hatchId, ")");
case 'dotted':
return "url(#dotted_".concat(hatchId, ")");
case 'crossed':
return "url(#crossed_".concat(hatchId, ")");
default:
return fill;
}
};
var renderShape = function () {
var shapeProps = {
style: __assign(__assign({}, currentShapeStyle), { fill: getPatternFill() }),
};
switch (shapeType) {
case 'circle':
return (React.createElement("ellipse", __assign({ rx: sx / 2, ry: sy / 2, transform: "rotate(".concat(rotation, ")") }, shapeProps)));
case 'rect':
return (React.createElement("rect", __assign({ rx: currentShapeStyle.cornerRadius, ry: currentShapeStyle.cornerRadius, x: -sx / 2, y: -sy / 2, width: sx, height: sy, transform: "rotate(".concat(rotation, ")") }, shapeProps)));
case 'custom':
return (React.createElement("path", __assign({ d: customShapeToPath(customShape, fullSize[0], fullSize[1]) }, shapeProps)));
}
};
return (React.createElement(AnnotationContainer$1, { className: 'annoContainer' },
React.createElement(AreaSvg, { width: Math.max(4, Math.abs(h)), height: Math.max(4, Math.abs(v)), style: {
left: h >= 0 ? 0 : h,
top: v >= 0 ? 0 : v,
} },
React.createElement("defs", null,
React.createElement("pattern", { id: "dotted_".concat(hatchId), patternUnits: 'userSpaceOnUse', x: -Math.round(patternSpace / 2), y: -Math.round(patternWidth / 2), patternTransform: "rotate(".concat(patternRotation - rotation, " 0 0)"), width: patternWidth + patternSpace, height: patternWidth + patternSpace },
React.createElement("circle", { cx: Math.round(patternWidth / 2), cy: Math.round(patternWidth / 2), r: Math.round(patternWidth / 2), style: { stroke: 'none', fill: fill } })),
React.createElement("pattern", { id: 'hatched_' + hatchId, patternUnits: 'userSpaceOnUse', width: patternSpace + patternWidth, height: patternSpace + patternWidth, patternTransform: 'rotate(' + (patternRotation - rotation) + ' 0 0)' },
React.createElement("line", { x1: '0', y1: '0', x2: 0, y2: patternSpace + patternWidth, style: {
stroke: fill,
strokeWidth: patternWidth,
} })),
React.createElement("pattern", { id: "crossed_".concat(hatchId), patternUnits: 'userSpaceOnUse', width: patternWidth + patternSpace, height: patternWidth + patternSpace, patternTransform: "rotate(".concat(patternRotation - rotation, ")") },
React.createElement("path", { d: createCrosshatchPath(patternWidth, patternSpace), stroke: fill, strokeWidth: patternWidth, strokeOpacity: 0.5 }))),
renderShape()),
React.createElement(ContentContainer$1, { style: {
minWidth: 'max-content',
left: h,
top: v,
transform: 'translate(-50%, -50%)',
textAlign: textAnchor,
} }, children)));
};
var AnnotationContainer$1 = styled.div(templateObject_1$1 || (templateObject_1$1 = __makeTemplateObject(["\n display: inline-block;\n line-height: 1em;\n position: absolute;\n"], ["\n display: inline-block;\n line-height: 1em;\n position: absolute;\n"])));
var ContentContainer$1 = styled.div(templateObject_2$1 || (templateObject_2$1 = __makeTemplateObject(["\n position: absolute;\n line-height: 1em;\n"], ["\n position: absolute;\n line-height: 1em;\n"])));
var AreaSvg = styled.svg(templateObject_3$1 || (templateObject_3$1 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n overflow: visible;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n overflow: visible;\n"])));
var createCrosshatchPath = function (width, space) {
var tileSize = width + space;
return "M ".concat(space / 2, " 0 \n L ").concat(space / 2, " ").concat(tileSize, "\n M 0 ").concat(space / 2, " \n L ").concat(tileSize, " ").concat(space / 2);
};
function percentageToPixel(percentage, total) {
return (percentage * total) / 100;
}
function customShapeToPath(customShape, width, height) {
return [
customShape
.map(function (point, index) {
var x = percentageToPixel(point.x, width);
var y = percentageToPixel(point.y, height);
return "".concat(index === 0 ? 'M' : 'L', " ").concat(x, " ").concat(y);
})
.join(' '),
'Z',
].join(' ');
}
function getOffset$1(offset) {
if (Array.isArray(offset)) {
return offset;
}
return [offset, offset];
}
function getSize(size, width, height) {
if (Array.isArray(size)) {
return [
percentageToPixel(size[0], width),
percentageToPixel(size[1], height),
];
}
return [percentageToPixel(size, width), percentageToPixel(size, width)];
}
var templateObject_1$1, templateObject_2$1, templateObject_3$1;
var defaultConnectorStyle = {
type: 'straight',
stroke: 'black',
width: 1,
markerSize: 6.5,
direction: 'cw',
strokeWidth: 1,
strokeOpacity: 1,
strokeLinecap: 'butt',
strokeLinejoin: 'miter',
strokeMiterlimit: 4,
strokeDasharray: 'none',
strokeDashoffset: 0,
};
var PointAnnotation = function (_a) {
var children = _a.children, _b = _a.offset, offset = _b === void 0 ? 0 : _b, connectorStyle = _a.connectorStyle, _c = _a.endMarker, endMarker = _c === void 0 ? 'none' : _c, _d = _a.startMarker, startMarker = _d === void 0 ? 'none' : _d, _e = _a.padding, padding = _e === void 0 ? 0 : _e, textAnchor = _a.textAnchor, _f = _a.animationDelay, animationDelay = _f === void 0 ? 200 : _f, _g = _a.threshold, threshold = _g === void 0 ? 0.1 : _g;
var id = useId();
var _h = useState(false), isVisible = _h[0], setIsVisible = _h[1];
var _j = useState(false), hasAnimated = _j[0], setHasAnimated = _j[1];
var _k = useIntersectionObserver({
threshold: threshold,
rootMargin: '50px',
freezeOnceVisible: true,
}), isIntersecting = _k.isIntersecting, ref = _k.ref;
useEffect(function () {
if (isIntersecting && !hasAnimated) {
setHasAnimated(true);
setTimeout(function () {
setIsVisible(true);
}, animationDelay);
}
}, [isIntersecting, animationDelay, hasAnimated]);
var _l = getOffset(offset), h = _l[0], v = _l[1];
var connectorSettings = __assign(__assign({}, defaultConnectorStyle), connectorStyle);
var connectorDirection = connectorSettings.direction;
var direction = getDirection([h, v]);
var shiftToTop = direction === 'top' ||
(direction === 'top-left' && connectorDirection === 'ccw') ||
(direction === 'top-right' && connectorDirection === 'cw');
var shiftToBottom = direction === 'bottom' ||
(direction === 'bottom-left' && connectorDirection === 'cw') ||
(direction === 'bottom-right' && connectorDirection === 'ccw') ||
(direction === 'top-left' && connectorDirection === 'cw');
var shiftToRight = direction === 'right' ||
(direction === 'top-right' && connectorDirection === 'ccw') ||
(direction === 'bottom-right' && connectorDirection === 'cw');
var shiftToLeft = direction === 'left' ||
(direction === 'top-left' && connectorDirection === 'cw') ||
(direction === 'bottom-left' && connectorDirection === 'ccw');
var noshift = !shiftToTop && !shiftToBottom && !shiftToRight && !shiftToLeft;
if (noshift && padding) {
shiftToRight = true;
shiftToBottom = true;
}
var markerSize = connectorSettings.markerSize;
var shiftLabelHorizontal = h >= 0 ? 0 : -100;
if (textAnchor === 'center') {
shiftLabelHorizontal = -50;
}
if (textAnchor === 'right') {
shiftLabelHorizontal = -100;
}
if (textAnchor === 'left') {
shiftLabelHorizontal = 0;
}
return (React.createElement(AnnotationContainer, { className: 'annoContainer', ref: ref },
React.createElement(LineSvg, { width: Math.max(4, Math.abs(h)), height: Math.max(4, Math.abs(v)), style: {
left: h >= 0 ? 0 : h,
top: v >= 0 ? 0 : v,
}, "$isVisible": isVisible },
React.createElement("defs", null,
React.createElement("marker", { id: "arrow-".concat(id), viewBox: "0 0 ".concat(markerSize * 2, " ").concat(markerSize * 2), refX: markerSize, refY: markerSize, markerWidth: markerSize, markerHeight: markerSize, orient: 'auto-start-reverse' },
React.createElement("path", { d: "M 0 0 L ".concat(markerSize * 2, " ").concat(markerSize, " L 0 ").concat(markerSize * 2, " z"), fill: connectorSettings.stroke })),
React.createElement("marker", { id: "circle-".concat(id), viewBox: "0 0 ".concat(markerSize * 1.6, " ").concat(markerSize * 1.6), refX: markerSize * 0.8, refY: markerSize * 0.8, markerWidth: markerSize * 0.8, markerHeight: markerSize * 0.8, orient: 'auto-start-reverse' },
React.createElement("circle", { cx: markerSize * 0.8, cy: markerSize * 0.8, r: markerSize * 0.8, fill: connectorSettings.stroke }))),
React.createElement(Path, { d: getLinePath(v, h, direction, connectorDirection, connectorSettings.type), style: {
stroke: connectorSettings.stroke,
strokeWidth: connectorSettings.strokeWidth,
strokeLinecap: connectorSettings.strokeLinecap,
strokeLinejoin: connectorSettings.strokeLinejoin,
strokeDasharray: connectorSettings.strokeDasharray,
strokeDashoffset: connectorSettings.strokeDashoffset,
strokeMiterlimit: connectorSettings.strokeMiterlimit,
strokeOpacity: connectorSettings.strokeOpacity,
}, fill: 'none', markerEnd: startMarker === 'arrow'
? "url(#arrow-".concat(id, ")")
: startMarker === 'circle'
? "url(#circle-".concat(id, ")")
: '', markerStart: endMarker === 'arrow'
? "url(#arrow-".concat(id, ")")
: endMarker === 'circle'
? "url(#circle-".concat(id, ")")
: '', "$isVisible": isVisible })),
React.createElement(ContentContainer, { style: {
minWidth: 'max-content',
left: h,
top: v,
transform: "translate(".concat(shiftLabelHorizontal, "%,").concat(v >= 0 ? 0 : 'calc(-100%)', ")"),
marginTop: direction === 'left' || direction === 'right' ? '-1em' : 0,
paddingRight: shiftToLeft ? padding + 'px' : 0,
paddingLeft: shiftToRight ? padding + 'px' : 0,
paddingBottom: shiftToTop ? padding + 'px' : 0,
paddingTop: shiftToBottom ? padding + 'px' : 0,
}, "$isVisible": isVisible }, children)));
};
var AnnotationContainer = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: inline-block;\n line-height: 1em;\n position: absolute;\n"], ["\n display: inline-block;\n line-height: 1em;\n position: absolute;\n"])));
var ContentContainer = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n position: absolute;\n line-height: 1em;\n opacity: ", ";\n scale: ", ";\n transform: ", ";\n transform-origin: left center;\n transition: opacity 0.3s ease-in-out;\n * {\n line-height: unset;\n }\n\n animation: ", ";\n\n @keyframes scaleUp {\n 0% {\n scale: 0;\n }\n 70% {\n scale: 1.2;\n }\n 100% {\n scale: 1;\n }\n }\n"], ["\n position: absolute;\n line-height: 1em;\n opacity: ", ";\n scale: ", ";\n transform: ", ";\n transform-origin: left center;\n transition: opacity 0.3s ease-in-out;\n * {\n line-height: unset;\n }\n\n animation: ", ";\n\n @keyframes scaleUp {\n 0% {\n scale: 0;\n }\n 70% {\n scale: 1.2;\n }\n 100% {\n scale: 1;\n }\n }\n"])), function (props) { return (props.$isVisible ? 1 : 0); }, function (props) { return (props.$isVisible ? 1 : 0); }, function (props) { var _a; return (_a = props.style) === null || _a === void 0 ? void 0 : _a.transform; }, function (props) {
return props.$isVisible
? "scaleUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards"
: 'none';
});
var LineSvg = styled.svg(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n overflow: visible;\n opacity: ", ";\n transition: opacity 0.3s ease-in-out;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n overflow: visible;\n opacity: ", ";\n transition: opacity 0.3s ease-in-out;\n"])), function (props) { return (props.$isVisible ? 1 : 0); });
var Path = styled.path(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n stroke-dasharray: 1000;\n stroke-dashoffset: ", ";\n transition: stroke-dashoffset 0.6s ease-in-out;\n"], ["\n stroke-dasharray: 1000;\n stroke-dashoffset: ", ";\n transition: stroke-dashoffset 0.6s ease-in-out;\n"])), function (props) { return (props.$isVisible ? 0 : 1000); });
function getOffset(offset) {
if (Array.isArray(offset)) {
return offset;
}
return [offset, offset];
}
function getDirection(offset) {
var h = offset[0], v = offset[1];
if (h === 0 && v === 0)
return 'center';
if (h === 0)
return v > 0 ? 'bottom' : 'top';
if (v === 0)
return h > 0 ? 'right' : 'left';
if (h > 0) {
return v > 0 ? 'bottom-right' : 'top-right';
}
else {
return v > 0 ? 'bottom-left' : 'top-left';
}
}
function getLinePoints(v, h) {
var sx = h >= 0 ? 0 : Math.abs(h);
var sy = v >= 0 ? 0 : Math.abs(v);
var ex = h >= 0 ? h : 0;
var ey = v >= 0 ? v : 0;
return { sx: sx, sy: sy, ex: ex, ey: ey };
}
function getLinePath(v, h, direction, curveDirection, connectorStyle) {
var linePoints = getLinePoints(v, h);
if (connectorStyle === 'straight') {
return "M ".concat(linePoints.sx, " ").concat(linePoints.sy, " L ").concat(linePoints.ex, " ").concat(linePoints.ey);
}
var halfH = Math.abs(h / 2);
var halfV = Math.abs(v / 2);
var c1x, c1y, c2x, c2y;
switch (direction) {
case 'top':
case 'top-right':
if (curveDirection === 'cw') {
c1x = linePoints.sx + halfH;
c1y = linePoints.sy;
c2x = linePoints.ex;
c2y = linePoints.sy - halfV;
}
else {
c1x = linePoints.sx;
c1y = linePoints.sy - halfV;
c2x = linePoints.sx + halfH;
c2y = linePoints.ey;
}
break;
case 'right':
case 'bottom-right':
if (curveDirection === 'cw') {
c1x = linePoints.sx;
c1y = linePoints.sy + halfV;
c2x = linePoints.sx + halfH;
c2y = linePoints.ey;
}
else {
c1x = linePoints.sx + halfH;
c1y = linePoints.sy;
c2x = linePoints.ex;
c2y = linePoints.sy + halfV;
}
break;
case 'bottom':
case 'bottom-left':
if (curveDirection === 'cw') {
c1x = linePoints.sx - halfH;
c1y = linePoints.sy;
c2x = linePoints.ex;
c2y = linePoints.sy + halfV;
}
else {
c1x = linePoints.sx;
c1y = linePoints.sy + halfV;
c2x = linePoints.sx - halfH;
c2y = linePoints.ey;
}
break;
case 'left':
case 'top-left':
if (curveDirection === 'cw') {
c1x = linePoints.sx;
c1y = linePoints.sy - halfV;
c2x = linePoints.sx - halfH;
c2y = linePoints.ey;
}
else {
c1x = linePoints.sx - halfH;
c1y = linePoints.sy;
c2x = linePoints.ex;
c2y = linePoints.sy - halfV;
}
break;
default:
if (curveDirection === 'cw') {
c1x = halfH;
c1y = linePoints.sy;
c2x = linePoints.ex;
c2y = halfV;
}
else {
c1x = linePoints.sx;
c1y = halfV;
c2x = halfH;
c2y = linePoints.ey;
}
}
return "M ".concat(linePoints.sx, " ").concat(linePoints.sy, " C ").concat(c1x, " ").concat(c1y, " ").concat(c2x, " ").concat(c2y, " ").concat(linePoints.ex, " ").concat(linePoints.ey);
}
var templateObject_1, templateObject_2, templateObject_3, templateObject_4;
export { AnnotatedContent, AreaAnnotation, PointAnnotation };
//# sourceMappingURL=index.m.js.map