first commit
This commit is contained in:
230
frontend/node_modules/antd/lib/watermark/index.js
generated
vendored
Normal file
230
frontend/node_modules/antd/lib/watermark/index.js
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
"use strict";
|
||||
"use client";
|
||||
|
||||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var _mutateObserver = require("@rc-component/mutate-observer");
|
||||
var _classnames = _interopRequireDefault(require("classnames"));
|
||||
var _useEvent = _interopRequireDefault(require("rc-util/lib/hooks/useEvent"));
|
||||
var _toList = _interopRequireDefault(require("../_util/toList"));
|
||||
var _internal = require("../theme/internal");
|
||||
var _context = _interopRequireDefault(require("./context"));
|
||||
var _useClips = _interopRequireWildcard(require("./useClips"));
|
||||
var _useRafDebounce = _interopRequireDefault(require("./useRafDebounce"));
|
||||
var _useSingletonCache = _interopRequireDefault(require("./useSingletonCache"));
|
||||
var _useWatermark = _interopRequireDefault(require("./useWatermark"));
|
||||
var _utils = require("./utils");
|
||||
/**
|
||||
* Only return `next` when size changed.
|
||||
* This is only used for elements compare, not a shallow equal!
|
||||
*/
|
||||
function getSizeDiff(prev, next) {
|
||||
return prev.size === next.size ? prev : next;
|
||||
}
|
||||
const DEFAULT_GAP_X = 100;
|
||||
const DEFAULT_GAP_Y = 100;
|
||||
const fixedStyle = {
|
||||
position: 'relative',
|
||||
overflow: 'hidden'
|
||||
};
|
||||
const Watermark = props => {
|
||||
var _a, _b;
|
||||
const {
|
||||
/**
|
||||
* The antd content layer zIndex is basically below 10
|
||||
* https://github.com/ant-design/ant-design/blob/6192403b2ce517c017f9e58a32d58774921c10cd/components/style/themes/default.less#L335
|
||||
*/
|
||||
zIndex = 9,
|
||||
rotate = -22,
|
||||
width,
|
||||
height,
|
||||
image,
|
||||
content,
|
||||
font = {},
|
||||
style,
|
||||
className,
|
||||
rootClassName,
|
||||
gap = [DEFAULT_GAP_X, DEFAULT_GAP_Y],
|
||||
offset,
|
||||
children,
|
||||
inherit = true
|
||||
} = props;
|
||||
const mergedStyle = Object.assign(Object.assign({}, fixedStyle), style);
|
||||
const [, token] = (0, _internal.useToken)();
|
||||
const {
|
||||
color = token.colorFill,
|
||||
fontSize = token.fontSizeLG,
|
||||
fontWeight = 'normal',
|
||||
fontStyle = 'normal',
|
||||
fontFamily = 'sans-serif',
|
||||
textAlign = 'center'
|
||||
} = font;
|
||||
const [gapX = DEFAULT_GAP_X, gapY = DEFAULT_GAP_Y] = gap;
|
||||
const gapXCenter = gapX / 2;
|
||||
const gapYCenter = gapY / 2;
|
||||
const offsetLeft = (_a = offset === null || offset === void 0 ? void 0 : offset[0]) !== null && _a !== void 0 ? _a : gapXCenter;
|
||||
const offsetTop = (_b = offset === null || offset === void 0 ? void 0 : offset[1]) !== null && _b !== void 0 ? _b : gapYCenter;
|
||||
const markStyle = _react.default.useMemo(() => {
|
||||
const mergedMarkStyle = {
|
||||
zIndex,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
pointerEvents: 'none',
|
||||
backgroundRepeat: 'repeat'
|
||||
};
|
||||
/** Calculate the style of the offset */
|
||||
let positionLeft = offsetLeft - gapXCenter;
|
||||
let positionTop = offsetTop - gapYCenter;
|
||||
if (positionLeft > 0) {
|
||||
mergedMarkStyle.left = `${positionLeft}px`;
|
||||
mergedMarkStyle.width = `calc(100% - ${positionLeft}px)`;
|
||||
positionLeft = 0;
|
||||
}
|
||||
if (positionTop > 0) {
|
||||
mergedMarkStyle.top = `${positionTop}px`;
|
||||
mergedMarkStyle.height = `calc(100% - ${positionTop}px)`;
|
||||
positionTop = 0;
|
||||
}
|
||||
mergedMarkStyle.backgroundPosition = `${positionLeft}px ${positionTop}px`;
|
||||
return mergedMarkStyle;
|
||||
}, [zIndex, offsetLeft, gapXCenter, offsetTop, gapYCenter]);
|
||||
const [container, setContainer] = _react.default.useState();
|
||||
// Used for nest case like Modal, Drawer
|
||||
const [subElements, setSubElements] = _react.default.useState(() => new Set());
|
||||
// Nest elements should also support watermark
|
||||
const targetElements = _react.default.useMemo(() => {
|
||||
const list = container ? [container] : [];
|
||||
return [].concat(list, (0, _toConsumableArray2.default)(Array.from(subElements)));
|
||||
}, [container, subElements]);
|
||||
// ============================ Content =============================
|
||||
/**
|
||||
* Get the width and height of the watermark. The default values are as follows
|
||||
* Image: [120, 64]; Content: It's calculated by content;
|
||||
*/
|
||||
const getMarkSize = ctx => {
|
||||
let defaultWidth = 120;
|
||||
let defaultHeight = 64;
|
||||
if (!image && ctx.measureText) {
|
||||
ctx.font = `${Number(fontSize)}px ${fontFamily}`;
|
||||
const contents = (0, _toList.default)(content);
|
||||
const sizes = contents.map(item => {
|
||||
const metrics = ctx.measureText(item);
|
||||
return [metrics.width, metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent];
|
||||
});
|
||||
defaultWidth = Math.ceil(Math.max.apply(Math, (0, _toConsumableArray2.default)(sizes.map(size => size[0]))));
|
||||
defaultHeight = Math.ceil(Math.max.apply(Math, (0, _toConsumableArray2.default)(sizes.map(size => size[1])))) * contents.length + (contents.length - 1) * _useClips.FontGap;
|
||||
}
|
||||
return [width !== null && width !== void 0 ? width : defaultWidth, height !== null && height !== void 0 ? height : defaultHeight];
|
||||
};
|
||||
const getClips = (0, _useClips.default)();
|
||||
const getClipsCache = (0, _useSingletonCache.default)();
|
||||
const [watermarkInfo, setWatermarkInfo] = _react.default.useState(null);
|
||||
// Generate new Watermark content
|
||||
const renderWatermark = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (ctx) {
|
||||
const ratio = (0, _utils.getPixelRatio)();
|
||||
const [markWidth, markHeight] = getMarkSize(ctx);
|
||||
const drawCanvas = drawContent => {
|
||||
const params = [drawContent || '', rotate, ratio, markWidth, markHeight, {
|
||||
color,
|
||||
fontSize,
|
||||
fontStyle,
|
||||
fontWeight,
|
||||
fontFamily,
|
||||
textAlign
|
||||
}, gapX, gapY];
|
||||
const [nextClips, clipWidth] = getClipsCache(params, () => getClips.apply(void 0, params));
|
||||
setWatermarkInfo([nextClips, clipWidth]);
|
||||
};
|
||||
if (image) {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
drawCanvas(img);
|
||||
};
|
||||
img.onerror = () => {
|
||||
drawCanvas(content);
|
||||
};
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.referrerPolicy = 'no-referrer';
|
||||
img.src = image;
|
||||
} else {
|
||||
drawCanvas(content);
|
||||
}
|
||||
}
|
||||
};
|
||||
const syncWatermark = (0, _useRafDebounce.default)(renderWatermark);
|
||||
// ============================= Effect =============================
|
||||
// Append watermark to the container
|
||||
const [appendWatermark, removeWatermark, isWatermarkEle] = (0, _useWatermark.default)(markStyle);
|
||||
(0, _react.useEffect)(() => {
|
||||
if (watermarkInfo) {
|
||||
targetElements.forEach(holder => {
|
||||
appendWatermark(watermarkInfo[0], watermarkInfo[1], holder);
|
||||
});
|
||||
}
|
||||
}, [watermarkInfo, targetElements]);
|
||||
// ============================ Observe =============================
|
||||
const onMutate = (0, _useEvent.default)(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
if ((0, _utils.reRendering)(mutation, isWatermarkEle)) {
|
||||
syncWatermark();
|
||||
} else if (mutation.target === container && mutation.attributeName === 'style') {
|
||||
// We've only force container not modify.
|
||||
// Not consider nest case.
|
||||
const keyStyles = Object.keys(fixedStyle);
|
||||
for (let i = 0; i < keyStyles.length; i += 1) {
|
||||
const key = keyStyles[i];
|
||||
const oriValue = mergedStyle[key];
|
||||
const currentValue = container.style[key];
|
||||
if (oriValue && oriValue !== currentValue) {
|
||||
container.style[key] = oriValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, _mutateObserver.useMutateObserver)(targetElements, onMutate);
|
||||
(0, _react.useEffect)(syncWatermark, [rotate, zIndex, width, height, image, content, color, fontSize, fontWeight, fontStyle, fontFamily, textAlign, gapX, gapY, offsetLeft, offsetTop]);
|
||||
// ============================ Context =============================
|
||||
const watermarkContext = _react.default.useMemo(() => ({
|
||||
add: ele => {
|
||||
setSubElements(prev => {
|
||||
const clone = new Set(prev);
|
||||
clone.add(ele);
|
||||
return getSizeDiff(prev, clone);
|
||||
});
|
||||
},
|
||||
remove: ele => {
|
||||
removeWatermark(ele);
|
||||
setSubElements(prev => {
|
||||
const clone = new Set(prev);
|
||||
clone.delete(ele);
|
||||
return getSizeDiff(prev, clone);
|
||||
});
|
||||
}
|
||||
}), []);
|
||||
// ============================= Render =============================
|
||||
const childNode = inherit ? (/*#__PURE__*/_react.default.createElement(_context.default.Provider, {
|
||||
value: watermarkContext
|
||||
}, children)) : children;
|
||||
return /*#__PURE__*/_react.default.createElement("div", {
|
||||
ref: setContainer,
|
||||
className: (0, _classnames.default)(className, rootClassName),
|
||||
style: mergedStyle
|
||||
}, childNode);
|
||||
};
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Watermark.displayName = 'Watermark';
|
||||
}
|
||||
var _default = exports.default = Watermark;
|
||||
Reference in New Issue
Block a user