add all frontend files

This commit is contained in:
2026-01-17 15:16:36 -05:00
parent ff16ae7858
commit e40287e4aa
25704 changed files with 1935289 additions and 0 deletions

8
node_modules/antd/es/watermark/context.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import * as React from 'react';
export interface WatermarkContextProps {
add: (ele: HTMLElement) => void;
remove: (ele: HTMLElement) => void;
}
declare const WatermarkContext: React.Context<WatermarkContextProps>;
export declare function usePanelRef(panelSelector?: string): (ele: HTMLElement | null) => void;
export default WatermarkContext;

24
node_modules/antd/es/watermark/context.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import * as React from 'react';
import useEvent from "rc-util/es/hooks/useEvent";
function voidFunc() {}
const WatermarkContext = /*#__PURE__*/React.createContext({
add: voidFunc,
remove: voidFunc
});
export function usePanelRef(panelSelector) {
const watermark = React.useContext(WatermarkContext);
const panelEleRef = React.useRef(null);
const panelRef = useEvent(ele => {
if (ele) {
const innerContentEle = panelSelector ? ele.querySelector(panelSelector) : ele;
if (innerContentEle) {
watermark.add(innerContentEle);
panelEleRef.current = innerContentEle;
}
} else {
watermark.remove(panelEleRef.current);
}
});
return panelRef;
}
export default WatermarkContext;

26
node_modules/antd/es/watermark/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import React from 'react';
export interface WatermarkProps {
zIndex?: number;
rotate?: number;
width?: number;
height?: number;
image?: string;
content?: string | string[];
font?: {
color?: CanvasFillStrokeStyles['fillStyle'];
fontSize?: number | string;
fontWeight?: 'normal' | 'light' | 'weight' | number;
fontStyle?: 'none' | 'normal' | 'italic' | 'oblique';
fontFamily?: string;
textAlign?: CanvasTextAlign;
};
style?: React.CSSProperties;
className?: string;
rootClassName?: string;
gap?: [number, number];
offset?: [number, number];
children?: React.ReactNode;
inherit?: boolean;
}
declare const Watermark: React.FC<WatermarkProps>;
export default Watermark;

223
node_modules/antd/es/watermark/index.js generated vendored Normal file
View File

@@ -0,0 +1,223 @@
"use client";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import React, { useEffect } from 'react';
import { useMutateObserver } from '@rc-component/mutate-observer';
import classNames from 'classnames';
import useEvent from "rc-util/es/hooks/useEvent";
import toList from '../_util/toList';
import { useToken } from '../theme/internal';
import WatermarkContext from './context';
import useClips, { FontGap } from './useClips';
import useRafDebounce from './useRafDebounce';
import useSingletonCache from './useSingletonCache';
import useWatermark from './useWatermark';
import { getPixelRatio, reRendering } from './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] = 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.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.useState();
// Used for nest case like Modal, Drawer
const [subElements, setSubElements] = React.useState(() => new Set());
// Nest elements should also support watermark
const targetElements = React.useMemo(() => {
const list = container ? [container] : [];
return [].concat(list, _toConsumableArray(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 = toList(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, _toConsumableArray(sizes.map(size => size[0]))));
defaultHeight = Math.ceil(Math.max.apply(Math, _toConsumableArray(sizes.map(size => size[1])))) * contents.length + (contents.length - 1) * FontGap;
}
return [width !== null && width !== void 0 ? width : defaultWidth, height !== null && height !== void 0 ? height : defaultHeight];
};
const getClips = useClips();
const getClipsCache = useSingletonCache();
const [watermarkInfo, setWatermarkInfo] = React.useState(null);
// Generate new Watermark content
const renderWatermark = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (ctx) {
const ratio = 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 = useRafDebounce(renderWatermark);
// ============================= Effect =============================
// Append watermark to the container
const [appendWatermark, removeWatermark, isWatermarkEle] = useWatermark(markStyle);
useEffect(() => {
if (watermarkInfo) {
targetElements.forEach(holder => {
appendWatermark(watermarkInfo[0], watermarkInfo[1], holder);
});
}
}, [watermarkInfo, targetElements]);
// ============================ Observe =============================
const onMutate = useEvent(mutations => {
mutations.forEach(mutation => {
if (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;
}
}
}
});
});
useMutateObserver(targetElements, onMutate);
useEffect(syncWatermark, [rotate, zIndex, width, height, image, content, color, fontSize, fontWeight, fontStyle, fontFamily, textAlign, gapX, gapY, offsetLeft, offsetTop]);
// ============================ Context =============================
const watermarkContext = React.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.createElement(WatermarkContext.Provider, {
value: watermarkContext
}, children)) : children;
return /*#__PURE__*/React.createElement("div", {
ref: setContainer,
className: classNames(className, rootClassName),
style: mergedStyle
}, childNode);
};
if (process.env.NODE_ENV !== 'production') {
Watermark.displayName = 'Watermark';
}
export default Watermark;

8
node_modules/antd/es/watermark/useClips.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import type { WatermarkProps } from '.';
export declare const FontGap = 3;
/**
* Get the clips of text content.
* This is a lazy hook function since SSR no need this
*/
declare const useClips: () => (content: NonNullable<WatermarkProps["content"]> | HTMLImageElement, rotate: number, ratio: number, width: number, height: number, font: Required<NonNullable<WatermarkProps["font"]>>, gapX: number, gapY: number) => [dataURL: string, finalWidth: number, finalHeight: number];
export default useClips;

96
node_modules/antd/es/watermark/useClips.js generated vendored Normal file
View File

@@ -0,0 +1,96 @@
import React from 'react';
import toList from '../_util/toList';
export const FontGap = 3;
const prepareCanvas = (width, height, ratio = 1) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const realWidth = width * ratio;
const realHeight = height * ratio;
canvas.setAttribute('width', `${realWidth}px`);
canvas.setAttribute('height', `${realHeight}px`);
ctx.save();
return [ctx, canvas, realWidth, realHeight];
};
// Get boundary of rotated text
const getRotatePos = (x, y, angle) => {
const targetX = x * Math.cos(angle) - y * Math.sin(angle);
const targetY = x * Math.sin(angle) + y * Math.cos(angle);
return [targetX, targetY];
};
/**
* Get the clips of text content.
* This is a lazy hook function since SSR no need this
*/
const useClips = () => {
// Get single clips
const getClips = (content, rotate, ratio, width, height, font, gapX, gapY) => {
// ================= Text / Image =================
const [ctx, canvas, contentWidth, contentHeight] = prepareCanvas(width, height, ratio);
if (content instanceof HTMLImageElement) {
// Image
ctx.drawImage(content, 0, 0, contentWidth, contentHeight);
} else {
// Text
const {
color,
fontSize,
fontStyle,
fontWeight,
fontFamily,
textAlign
} = font;
const mergedFontSize = Number(fontSize) * ratio;
ctx.font = `${fontStyle} normal ${fontWeight} ${mergedFontSize}px/${height}px ${fontFamily}`;
ctx.fillStyle = color;
ctx.textAlign = textAlign;
ctx.textBaseline = 'top';
const contents = toList(content);
contents === null || contents === void 0 ? void 0 : contents.forEach((item, index) => {
ctx.fillText(item !== null && item !== void 0 ? item : '', contentWidth / 2, index * (mergedFontSize + FontGap * ratio));
});
}
// ==================== Rotate ====================
const angle = Math.PI / 180 * Number(rotate);
const maxSize = Math.max(width, height);
const [rCtx, rCanvas, realMaxSize] = prepareCanvas(maxSize, maxSize, ratio);
// Copy from `ctx` and rotate
rCtx.translate(realMaxSize / 2, realMaxSize / 2);
rCtx.rotate(angle);
if (contentWidth > 0 && contentHeight > 0) {
rCtx.drawImage(canvas, -contentWidth / 2, -contentHeight / 2);
}
let left = 0;
let right = 0;
let top = 0;
let bottom = 0;
const halfWidth = contentWidth / 2;
const halfHeight = contentHeight / 2;
const points = [[0 - halfWidth, 0 - halfHeight], [0 + halfWidth, 0 - halfHeight], [0 + halfWidth, 0 + halfHeight], [0 - halfWidth, 0 + halfHeight]];
points.forEach(([x, y]) => {
const [targetX, targetY] = getRotatePos(x, y, angle);
left = Math.min(left, targetX);
right = Math.max(right, targetX);
top = Math.min(top, targetY);
bottom = Math.max(bottom, targetY);
});
const cutLeft = left + realMaxSize / 2;
const cutTop = top + realMaxSize / 2;
const cutWidth = right - left;
const cutHeight = bottom - top;
// ================ Fill Alternate ================
const realGapX = gapX * ratio;
const realGapY = gapY * ratio;
const filledWidth = (cutWidth + realGapX) * 2;
const filledHeight = cutHeight + realGapY;
const [fCtx, fCanvas] = prepareCanvas(filledWidth, filledHeight);
const drawImg = (targetX = 0, targetY = 0) => {
fCtx.drawImage(rCanvas, cutLeft, cutTop, cutWidth, cutHeight, targetX, targetY, cutWidth, cutHeight);
};
drawImg();
drawImg(cutWidth + realGapX, -cutHeight / 2 - realGapY / 2);
drawImg(cutWidth + realGapX, +cutHeight / 2 + realGapY / 2);
return [fCanvas.toDataURL(), filledWidth / ratio, filledHeight / ratio];
};
return React.useCallback(getClips, []);
};
export default useClips;

4
node_modules/antd/es/watermark/useRafDebounce.d.ts generated vendored Normal file
View File

@@ -0,0 +1,4 @@
/**
* Callback will only execute last one for each raf
*/
export default function useRafDebounce(callback: VoidFunction): () => void;

21
node_modules/antd/es/watermark/useRafDebounce.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import React from 'react';
import useEvent from "rc-util/es/hooks/useEvent";
import raf from "rc-util/es/raf";
/**
* Callback will only execute last one for each raf
*/
export default function useRafDebounce(callback) {
const executeRef = React.useRef(false);
const rafRef = React.useRef(null);
const wrapperCallback = useEvent(callback);
return () => {
if (executeRef.current) {
return;
}
executeRef.current = true;
wrapperCallback();
rafRef.current = raf(() => {
executeRef.current = false;
});
};
}

View File

@@ -0,0 +1,6 @@
export type GetCache<T, R> = (cacheKeys: T, callback: () => R) => R;
/**
* Singleton cache will only take latest `cacheParams` as key
* and return the result for callback matching.
*/
export default function useSingletonCache<T extends any[], R>(): GetCache<T, R>;

17
node_modules/antd/es/watermark/useSingletonCache.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import * as React from 'react';
import isEqual from "rc-util/es/isEqual";
/**
* Singleton cache will only take latest `cacheParams` as key
* and return the result for callback matching.
*/
export default function useSingletonCache() {
const cacheRef = React.useRef([null, null]);
const getCache = (cacheKeys, callback) => {
const filteredKeys = cacheKeys.map(item => item instanceof HTMLElement || Number.isNaN(item) ? '' : item);
if (!isEqual(cacheRef.current[0], filteredKeys)) {
cacheRef.current = [filteredKeys, callback()];
}
return cacheRef.current[1];
};
return getCache;
}

13
node_modules/antd/es/watermark/useWatermark.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import * as React from 'react';
/**
* Base size of the canvas, 1 for parallel layout and 2 for alternate layout
* Only alternate layout is currently supported
*/
export declare const BaseSize = 2;
export declare const FontGap = 3;
export type AppendWatermark = (base64Url: string, markWidth: number, container: HTMLElement) => void;
export default function useWatermark(markStyle: React.CSSProperties): [
appendWatermark: AppendWatermark,
removeWatermark: (container: HTMLElement) => void,
isWatermarkEle: (ele: Node) => boolean
];

44
node_modules/antd/es/watermark/useWatermark.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import * as React from 'react';
import { getStyleStr } from './utils';
/**
* Base size of the canvas, 1 for parallel layout and 2 for alternate layout
* Only alternate layout is currently supported
*/
export const BaseSize = 2;
export const FontGap = 3;
// Prevent external hidden elements from adding accent styles
const emphasizedStyle = {
visibility: 'visible !important'
};
export default function useWatermark(markStyle) {
const watermarkMap = React.useRef(new Map());
const appendWatermark = (base64Url, markWidth, container) => {
if (container) {
if (!watermarkMap.current.get(container)) {
const newWatermarkEle = document.createElement('div');
watermarkMap.current.set(container, newWatermarkEle);
}
const watermarkEle = watermarkMap.current.get(container);
watermarkEle.setAttribute('style', getStyleStr(Object.assign(Object.assign(Object.assign({}, markStyle), {
backgroundImage: `url('${base64Url}')`,
backgroundSize: `${Math.floor(markWidth)}px`
}), emphasizedStyle)));
// Prevents using the browser `Hide Element` to hide watermarks
watermarkEle.removeAttribute('class');
watermarkEle.removeAttribute('hidden');
if (watermarkEle.parentElement !== container) {
container.append(watermarkEle);
}
}
return watermarkMap.current.get(container);
};
const removeWatermark = container => {
const watermarkEle = watermarkMap.current.get(container);
if (watermarkEle && container) {
container.removeChild(watermarkEle);
}
watermarkMap.current.delete(container);
};
const isWatermarkEle = ele => Array.from(watermarkMap.current.values()).includes(ele);
return [appendWatermark, removeWatermark, isWatermarkEle];
}

7
node_modules/antd/es/watermark/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
/** converting camel-cased strings to be lowercase and link it with Separator */
export declare function toLowercaseSeparator(key: string): string;
export declare function getStyleStr(style: React.CSSProperties): string;
/** Returns the ratio of the device's physical pixel resolution to the css pixel resolution */
export declare function getPixelRatio(): number;
/** Whether to re-render the watermark */
export declare const reRendering: (mutation: MutationRecord, isWatermarkEle: (ele: Node) => boolean) => boolean;

24
node_modules/antd/es/watermark/utils.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
/** converting camel-cased strings to be lowercase and link it with Separator */
export function toLowercaseSeparator(key) {
return key.replace(/([A-Z])/g, '-$1').toLowerCase();
}
export function getStyleStr(style) {
return Object.keys(style).map(key => `${toLowercaseSeparator(key)}: ${style[key]};`).join(' ');
}
/** Returns the ratio of the device's physical pixel resolution to the css pixel resolution */
export function getPixelRatio() {
return window.devicePixelRatio || 1;
}
/** Whether to re-render the watermark */
export const reRendering = (mutation, isWatermarkEle) => {
let flag = false;
// Whether to delete the watermark node
if (mutation.removedNodes.length) {
flag = Array.from(mutation.removedNodes).some(node => isWatermarkEle(node));
}
// Whether the watermark dom property value has been modified
if (mutation.type === 'attributes' && isWatermarkEle(mutation.target)) {
flag = true;
}
return flag;
};