diff --git a/packages/lab/README.md b/packages/figma/README.md similarity index 100% rename from packages/lab/README.md rename to packages/figma/README.md diff --git a/packages/figma/dev/figma/iOS-Native-Wireframes-Community.fig b/packages/figma/dev/figma/iOS-Native-Wireframes-Community.fig new file mode 100644 index 0000000..e6c3647 Binary files /dev/null and b/packages/figma/dev/figma/iOS-Native-Wireframes-Community.fig differ diff --git a/packages/figma/dev/index.html b/packages/figma/dev/index.html new file mode 100644 index 0000000..860ff53 --- /dev/null +++ b/packages/figma/dev/index.html @@ -0,0 +1,36 @@ + + + + + canvas + + + +
+ + + + diff --git a/packages/figma/dev/main.ts b/packages/figma/dev/main.ts new file mode 100644 index 0000000..ab7667a --- /dev/null +++ b/packages/figma/dev/main.ts @@ -0,0 +1,90 @@ +import type { Data, ElementAssets, Element } from '@idraw/types'; +import { deepClone, getElemenetsAssetIds } from '@idraw/util'; +import { figmaBytesToMap, figmaMapToIDrawData, figmaBytesToIDrawData } from '../src'; +import { iDraw } from '../../idraw'; +// import data from './data'; + +const url = new URLSearchParams(window.location.search); + +async function action(params: { data: Data }) { + const previewDOM = document.querySelector('#canvas-preview') as HTMLDivElement; + + const { data } = params; + const devicePixelRatio = window.devicePixelRatio; + const width = window.innerWidth; + const height = 600; + + const data1 = deepClone(data); + + const idraw = new iDraw(previewDOM, { + devicePixelRatio, + width, + height + }); + idraw.setData(data1); + idraw.centerContent(); +} + +// async function main() { +// if (targetFile) { +// const filePath = `/demo/lab-figma-to-elements/figma/${targetFile}`; +// const figma = await fetch(filePath).then((res) => res.blob()); +// const buffer = await figma.arrayBuffer(); + +// { +// const filePath = `/demo/lab-figma-to-elements/figma/${targetFile}`; +// const figma = await fetch(filePath).then((res) => res.blob()); +// const buff = await figma.arrayBuffer(); +// const bytes = new Uint8Array(buff); +// const figmaMap = await figmaBytesToMap(bytes); +// console.log('figmaMap ===== ', figmaMap); +// const data = await figmaMapToIDrawData(figmaMap); +// console.log('object ===== ', data); +// } + +// let data = await figmaBufferToIDrawData(buffer); +// // console.log('object ====== ', object); + +// // const map = figmaObjectToMap(object); +// // console.log('map ==== ', map); + +// // const tree = figmaObjectToTree(object); +// // console.log('tree ==== ', tree); + +// // let data = figmaObjectToIDrawData(object); +// // TODO +// data = { +// elements: (data.elements[0] as Element<'group'>).detail.children +// }; +// // console.log('data ===== ', data); +// await action({ data }); +// } else { +// list(); +// } +// } + +async function main() { + const filePath = `/dev/figma/iOS-Native-Wireframes-Community.fig`; + console.log('filePath ------ ', filePath); + const figma = await fetch(filePath).then((res) => res.blob()); + const arrayBuffer = await figma.arrayBuffer(); + const buffer = new Uint8Array(arrayBuffer); + + let data: Data = await figmaBytesToIDrawData(buffer); + // // TODO + data = { + elements: (data.elements[0] as Element<'group'>).detail.children, + global: data.elements[0].global + }; + + console.log('data ===== ', data); + await action({ data }); +} + +main() + .then(() => { + console.log('Ok'); + }) + .catch((err) => { + console.log(err); + }); diff --git a/packages/figma/package.json b/packages/figma/package.json new file mode 100644 index 0000000..edad33e --- /dev/null +++ b/packages/figma/package.json @@ -0,0 +1,17 @@ +{ + "name": "@idraw/figma", + "version": "0.4.0-beta.25", + "dependencies": { + "@ant-design/icons": "^5.1.3", + "@idraw/types": "workspace:^0.4.0-beta.25", + "@idraw/util": "workspace:^0.4.0-beta.25", + "kiwi-schema": "^0.5.0", + "matrix-inverse": "^2.0.0", + "pako": "^2.1.0", + "uzip": "^0.20201231.0" + }, + "devDependencies": { + "@types/pako": "^2.0.3", + "@idraw/types": "workspace:^0.4.0-beta.25" + } +} diff --git a/packages/figma/src/common/calc.ts b/packages/figma/src/common/calc.ts new file mode 100644 index 0000000..68c9ea1 --- /dev/null +++ b/packages/figma/src/common/calc.ts @@ -0,0 +1,88 @@ +import type { Element, ElementSize } from '@idraw/types'; +import { rotateElementVertexes } from '@idraw/util'; + +export function calcGroupSize(group: Element<'group'>): ElementSize { + const area: ElementSize = { x: 0, y: 0, w: 0, h: 0 }; + group.detail.children.forEach((elem) => { + const elemSize: ElementSize = { + x: elem.x, + y: elem.y, + w: elem.w, + h: elem.h, + angle: elem.angle + }; + if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) { + const ves = rotateElementVertexes(elemSize); + if (ves.length === 4) { + const xList = [ves[0].x, ves[1].x, ves[2].x, ves[3].x]; + const yList = [ves[0].y, ves[1].y, ves[2].y, ves[3].y]; + elemSize.x = Math.min(...xList); + elemSize.y = Math.min(...yList); + elemSize.w = Math.abs(Math.max(...xList) - Math.min(...xList)); + elemSize.h = Math.abs(Math.max(...yList) - Math.min(...yList)); + } + } + const areaStartX = Math.min(elemSize.x, area.x); + const areaStartY = Math.min(elemSize.y, area.y); + + const areaEndX = Math.max(elemSize.x + elemSize.w, area.x + area.w); + const areaEndY = Math.max(elemSize.y + elemSize.h, area.y + area.h); + + area.x = areaStartX; + area.y = areaStartY; + area.w = Math.abs(areaEndX - areaStartX); + area.h = Math.abs(areaEndY - areaStartY); + }); + return area; +} + +export function resetGroupSize(group: Element<'group'>): Element<'group'> { + const area = { x: 0, y: 0, w: 0, h: 0 }; + if (group.detail.children.length > 0) { + const firstElem = group.detail.children[0]; + area.x = firstElem.x; + area.y = firstElem.y; + area.w = firstElem.w; + area.h = firstElem.h; + } + group.detail.children.forEach((elem) => { + const elemSize: ElementSize = { + x: elem.x, + y: elem.y, + w: elem.w, + h: elem.h, + angle: elem.angle + }; + if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) { + const ves = rotateElementVertexes(elemSize); + if (ves.length === 4) { + const xList = [ves[0].x, ves[1].x, ves[2].x, ves[3].x]; + const yList = [ves[0].y, ves[1].y, ves[2].y, ves[3].y]; + elemSize.x = Math.min(...xList); + elemSize.y = Math.min(...yList); + elemSize.w = Math.abs(Math.max(...xList) - Math.min(...xList)); + elemSize.h = Math.abs(Math.max(...yList) - Math.min(...yList)); + } + } + const areaStartX = Math.min(elemSize.x, area.x); + const areaStartY = Math.min(elemSize.y, area.y); + + const areaEndX = Math.max(elemSize.x + elemSize.w, area.x + area.w); + const areaEndY = Math.max(elemSize.y + elemSize.h, area.y + area.h); + + area.x = areaStartX; + area.y = areaStartY; + area.w = Math.abs(areaEndX - areaStartX); + area.h = Math.abs(areaEndY - areaStartY); + }); + + group.detail.children.forEach((elem) => { + elem.x -= area.x; + elem.y -= area.y; + }); + + group.w = area.w; + group.h = area.h; + + return group; +} diff --git a/packages/figma/src/common/node.ts b/packages/figma/src/common/node.ts new file mode 100644 index 0000000..f3863ed --- /dev/null +++ b/packages/figma/src/common/node.ts @@ -0,0 +1,77 @@ +import type { FigmaGUID, FigmaNode, FigmaNodeType, FigmaParseOptions, FigmaSymbolOverrideItem } from '../types'; + +export function figmaGUIDToID(guid: FigmaGUID): string { + return `${guid.sessionID}:${guid.localID}`; +} + +export function getOverrideNodeMap(node: FigmaNode<'INSTANCE'>): Record> { + const overrideNodeMap: Record> = {}; + const { symbolData, derivedSymbolData } = node; + const { symbolOverrides } = symbolData; + if (Array.isArray(symbolOverrides) && symbolOverrides.length > 0) { + symbolOverrides.forEach((item) => { + const { guidPath, ...restData } = item; + guidPath.guids.forEach((guid) => { + const id = figmaGUIDToID(guid); + if (overrideNodeMap[id]) { + overrideNodeMap[id] = { ...overrideNodeMap[id], ...restData }; + } else { + overrideNodeMap[id] = restData; + } + }); + }); + } + + if (Array.isArray(derivedSymbolData) && derivedSymbolData.length > 0) { + derivedSymbolData.forEach((item) => { + const { guidPath, ...restData } = item; + guidPath.guids.forEach((guid) => { + const id = figmaGUIDToID(guid); + if (overrideNodeMap[id]) { + overrideNodeMap[id] = { ...overrideNodeMap[id], ...restData }; + } else { + overrideNodeMap[id] = restData; + } + }); + }); + } + + return overrideNodeMap; +} + +export function mergeNodeOverrideData( + node: FigmaNode, + opts: FigmaParseOptions +): Partial> | FigmaSymbolOverrideItem { + let overrideData: Partial> = {}; + + const { overrideNodeMap = {}, overrideProperties } = opts; + const { overrideKey } = node; + + if (overrideKey) { + const overrideId = figmaGUIDToID(overrideKey); + if (overrideNodeMap[overrideId]) { + overrideData = { ...overrideData, ...overrideNodeMap[overrideId] } as Partial>; + } + } + if (overrideProperties) { + overrideData = { ...overrideData, ...overrideProperties }; + } + + return overrideData; +} + +export async function uint8ArrayToBase64(u8: Uint8Array, opts: { type: string }): Promise { + const { type } = opts; + return new Promise((resolve, reject) => { + var blob = new Blob([u8], { type }); + var fileReader = new FileReader(); + fileReader.addEventListener('load', () => { + resolve(fileReader.result as string); + }); + fileReader.addEventListener('error', (err) => { + reject(err); + }); + fileReader.readAsDataURL(blob); + }); +} diff --git a/packages/figma/src/config.ts b/packages/figma/src/config.ts new file mode 100644 index 0000000..0074e8d --- /dev/null +++ b/packages/figma/src/config.ts @@ -0,0 +1 @@ +export const figmaImageDir = 'images/'; diff --git a/packages/figma/src/figma-node/base.ts b/packages/figma/src/figma-node/base.ts new file mode 100644 index 0000000..3ca05be --- /dev/null +++ b/packages/figma/src/figma-node/base.ts @@ -0,0 +1,257 @@ +import type { Element, ElementBaseDetail, SVGPathCommand, SVGPathCommandType } from '@idraw/types'; +import { createUUID, rotateVertexes, parseAngleToRadian, calcElementCenterFromVertexes } from '@idraw/util'; +import type { FigmaNode, FigmaNodeType, FigmaNodeFillBase, FigmaNodeStrokeBase, FigmaEffect, FigmaFillPaintImage } from '../types'; +import { figmaPaintsToHexColor, figmaPaintsToColor, figmaColorToHex } from './color'; + +export function nodeToElementBase(node: FigmaNode): Omit { + const { + m00, + m01, + m02, + // m10, + // m11, + m12 + } = node.transform; + const originAngle = Math.round((Math.atan2(m01, m00) * 180) / Math.PI); + const angle = 0 - originAngle; + const elemBase = { + uuid: createUUID(), + name: node.name, + x: m02 || 0, + y: m12 || 0, + w: node?.size?.x || 0, + h: node?.size?.y || 0, + angle + }; + + if (originAngle !== 0) { + let { x, y, w, h } = elemBase; + const rotateCenter = { x, y }; + const v0 = { x, y }; + const v1 = { x: x + w, y }; + const v2 = { x: x + w, y: y + h }; + const v3 = { x, y: y + h }; + const radian = parseAngleToRadian(angle); + const ves = rotateVertexes(rotateCenter, [v0, v1, v2, v3], radian); + const center = calcElementCenterFromVertexes(ves); + elemBase.x = center.x - w / 2; + elemBase.y = center.y - h / 2; + } + return elemBase; +} + +export function nodeToBaseDetail(node: FigmaNode): ElementBaseDetail { + let detail: ElementBaseDetail = {}; + const { + fillPaints, + strokeWeight, + strokePaints, + cornerRadius, + dashPattern, + borderStrokeWeightsIndependent, + borderBottomWeight, + borderLeftWeight, + borderRightWeight, + borderTopWeight, + rectangleCornerRadiiIndependent, + rectangleBottomLeftCornerRadius, + rectangleBottomRightCornerRadius, + rectangleTopLeftCornerRadius, + rectangleTopRightCornerRadius, + strokeAlign, + opacity + } = node as FigmaNode<'ROUNDED_RECTANGLE'>; + const background = figmaPaintsToColor(fillPaints, { + w: node.size.x, + h: node.size.y + }); + if (background) { + detail.background = background; + } + if (cornerRadius > 0) { + detail.borderRadius = cornerRadius; + } else if (rectangleCornerRadiiIndependent === true) { + detail.borderRadius = [ + rectangleTopLeftCornerRadius || 0, + rectangleTopRightCornerRadius || 0, + rectangleBottomRightCornerRadius || 0, + rectangleBottomLeftCornerRadius || 0 + ]; + } + detail.borderDash = dashPattern || []; + detail.boxSizing = 'border-box'; + if (strokeAlign === 'CENTER') { + detail.boxSizing = 'center-line'; + } else if (strokeAlign === 'OUTSIDE') { + detail.boxSizing = 'content-box'; + } + + if (strokePaints?.length === 1 && strokePaints[0].color) { + const hexColor = figmaPaintsToHexColor(strokePaints); + if (hexColor) { + detail.borderColor = hexColor; + } + + if (borderStrokeWeightsIndependent) { + detail.borderWidth = [borderTopWeight || 0, borderRightWeight || 0, borderBottomWeight || 0, borderLeftWeight || 0]; + } else { + detail.borderWidth = strokeWeight; + } + } + + if (typeof opacity === 'number' && opacity >= 0) { + detail.opacity = opacity; + } + + detail = { + ...detail, + ...getShadow(node.effects) + }; + + return detail; +} + +export function getShadow(effects?: FigmaEffect[]): Pick, 'shadowBlur' | 'shadowColor' | 'shadowOffsetX' | 'shadowOffsetY'> { + const shadow = {}; + if (Array.isArray(effects) && effects.length > 0) { + for (let i = 0; i < effects.length; i++) { + const { color, offset, spread = 0, type, visible, radius } = effects[i]; + if (visible === true && type === 'DROP_SHADOW') { + return { + shadowColor: figmaColorToHex(color), + shadowBlur: spread || radius || 0, // TODO + shadowOffsetX: offset.x || 0, + shadowOffsetY: offset.y || 0 + }; + } + } + } + return shadow; +} + +export function getStrokeColor(node: FigmaNodeStrokeBase): string | null { + const { strokePaints } = node; + let stroke: string | null = null; + if (strokePaints?.length > 0) { + const hexColor = figmaPaintsToHexColor(strokePaints); + if (hexColor) { + stroke = hexColor; + } + } + return stroke; +} + +export function getFillColor(node: FigmaNodeFillBase): string | null { + const { fillPaints } = node; + let fill: string | null = null; + if (fillPaints?.length === 1 && fillPaints[0].color && fillPaints[0].type === 'SOLID') { + const hexColor = figmaPaintsToHexColor(fillPaints); + if (hexColor) { + fill = hexColor; + } + } + return fill; +} + +export function getFillPathCommands(node: FigmaNodeFillBase): SVGPathCommand[] { + const pathCmds: SVGPathCommand[] = []; + const { fillGeometry } = node; + if (Array.isArray(fillGeometry) && fillGeometry[0] && Array.isArray(fillGeometry[0]?.commands)) { + const { commands } = fillGeometry[0]; + let pathCmd: SVGPathCommand | null = null; + + commands.forEach((item, i) => { + if (typeof item === 'string') { + if (pathCmd?.type && Array.isArray(pathCmd.params)) { + pathCmds.push(pathCmd); + } + pathCmd = { type: item as SVGPathCommandType, params: [] }; + } else if (typeof item === 'number' && Array.isArray(pathCmd?.params)) { + pathCmd.params.push(item); + } + + if (i === commands.length - 1 && pathCmd) { + pathCmds.push(pathCmd); + pathCmd = null; + } + }); + } + return pathCmds; +} + +export function getFillAttributes(node: FigmaNodeFillBase): { commands: SVGPathCommand[]; fillRule?: string } { + const pathCmds: SVGPathCommand[] = []; + const { fillGeometry } = node; + let fillRule: string | undefined = undefined; + if (Array.isArray(fillGeometry) && fillGeometry[0] && Array.isArray(fillGeometry[0]?.commands)) { + const { commands, windingRule } = fillGeometry[0]; + let pathCmd: SVGPathCommand | null = null; + if (windingRule === 'ODD') { + fillRule = 'evenodd'; + } else if (windingRule === 'NONZERO') { + fillRule = 'nonzero'; + } + + commands.forEach((item, i) => { + if (typeof item === 'string') { + if (pathCmd?.type && Array.isArray(pathCmd.params)) { + pathCmds.push(pathCmd); + } + pathCmd = { type: item as SVGPathCommandType, params: [] }; + } else if (typeof item === 'number' && Array.isArray(pathCmd?.params)) { + pathCmd.params.push(item); + } + + if (i === commands.length - 1 && pathCmd) { + pathCmds.push(pathCmd); + pathCmd = null; + } + }); + } + const attrs: { commands: SVGPathCommand[]; fillRule?: string } = { + commands: pathCmds + }; + if (fillRule) { + attrs.fillRule = fillRule; + } + return attrs; +} + +export function getStrokePathCommands(node: FigmaNodeStrokeBase): SVGPathCommand[] { + const pathCmds: SVGPathCommand[] = []; + const { strokeGeometry } = node; + if (Array.isArray(strokeGeometry) && strokeGeometry[0] && Array.isArray(strokeGeometry[0]?.commands)) { + const { commands } = strokeGeometry[0]; + let pathCmd: SVGPathCommand | null = null; + + commands.forEach((item, i) => { + if (typeof item === 'string') { + if (pathCmd?.type && Array.isArray(pathCmd.params)) { + pathCmds.push(pathCmd); + } + pathCmd = { type: item as SVGPathCommandType, params: [] }; + } else if (typeof item === 'number' && Array.isArray(pathCmd?.params)) { + pathCmd.params.push(item); + } + + if (i === commands.length - 1 && pathCmd) { + pathCmds.push(pathCmd); + pathCmd = null; + } + }); + } + return pathCmds; +} + +export function hasFillImage(node: FigmaNode) { + const { fillPaints } = node; + if (Array.isArray(fillPaints)) { + for (let i = 0; i < fillPaints.length; i++) { + const paint = fillPaints[i]; + if (paint.visible === true && (paint as FigmaFillPaintImage).image) { + return true; + } + } + } + return false; +} diff --git a/packages/figma/src/figma-node/color.ts b/packages/figma/src/figma-node/color.ts new file mode 100644 index 0000000..16f6668 --- /dev/null +++ b/packages/figma/src/figma-node/color.ts @@ -0,0 +1,121 @@ +import { is, calcDistance } from '@idraw/util'; +import { LinearGradientColor, RadialGradientColor } from '@idraw/types'; +import type { FigmaColor, FigmaPaint, FigmaFillPaintSolid, FigmaFillPaintGradientLinear, FigmaFillPaintGradientRadial } from '../types'; +import { parseLinearGradientParamsFromTransform, parseRadialOrDiamondGradientParamsFromTransform } from './gradient'; + +function numToHex(num: number): string { + const unit = 255; + const hexNum = Math.min(Math.max(Math.round(num * unit), 0), unit); + const hex = hexNum.toString(16).toUpperCase().padStart(2, '0'); + return hex; +} + +export function figmaColorToHex(color: FigmaColor, opts?: { opacity?: number }): string { + const { r, g, b, a } = color; + let opacity = 1; + if (is.number(opts?.opacity)) { + opacity = opts?.opacity as number; + } + const list: string[] = ['#', numToHex(r), numToHex(g), numToHex(b)]; + const alpha = a * opacity; + if (alpha < 1) { + list.push(numToHex(alpha)); + } + return list.join(''); +} + +export function figmaPaintsToHexColor(paints: FigmaPaint[]): string { + if (Array.isArray(paints) && paints.length > 0) { + for (let i = 0; i < paints.length; i++) { + const { color, opacity, visible, type } = paints[i] as FigmaFillPaintSolid; + if (visible === true && type === 'SOLID') { + return figmaColorToHex(color, { opacity }); + } + } + } + return 'transparent'; +} + +export function figmaPaintToLinearGradient(paint: FigmaFillPaintGradientLinear, opts: { w: number; h: number }): LinearGradientColor | string { + const { type, transform, stops } = paint; + const { w, h } = opts; + if (type === 'GRADIENT_LINEAR') { + const { start, end } = parseLinearGradientParamsFromTransform(w, h, transform); + const linearGradient: LinearGradientColor = { + type: 'linear-gradient', + start, + end, + stops: stops.map((stop) => { + const { position, color } = stop; + return { + color: figmaColorToHex(color), + offset: position + }; + }) + }; + return linearGradient; + } + return 'transparent'; +} + +export function figmaPaintToRadialGradient(paint: FigmaFillPaintGradientRadial, opts: { w: number; h: number }): RadialGradientColor | string { + const { type, transform, stops } = paint; + const { w, h } = opts; + if (type === 'GRADIENT_RADIAL') { + const { rotation, center, radius } = parseRadialOrDiamondGradientParamsFromTransform(w, h, transform); + const centerPoint = { + x: center[0], + y: center[1] + }; + const radiusPoint = { + x: radius[0], + y: radius[1] + }; + const r = calcDistance(centerPoint, radiusPoint); + const radialGradient: RadialGradientColor = { + type: 'radial-gradient', + angle: rotation, + inner: { + x: centerPoint.x, + y: centerPoint.y, + radius: r + }, + outer: { + x: radiusPoint.x, + y: radiusPoint.y, + radius: r + }, + stops: stops.map((stop) => { + const { position, color } = stop; + return { + color: figmaColorToHex(color), + offset: position + }; + }) + }; + return radialGradient; + } + return 'transparent'; +} + +export function figmaPaintsToColor(paints: FigmaPaint[], opts: { w: number; h: number }): string | LinearGradientColor | RadialGradientColor { + if (Array.isArray(paints) && paints.length > 0) { + for (let i = 0; i < paints.length; i++) { + const { visible, type } = paints[i]; + + if (visible === true) { + if (type === 'SOLID') { + const { color, opacity } = paints[i] as FigmaFillPaintSolid; + return figmaColorToHex(color, { opacity }); + } + if (type === 'GRADIENT_LINEAR') { + return figmaPaintToLinearGradient(paints[i] as FigmaFillPaintGradientLinear, opts); + } + if (type === 'GRADIENT_RADIAL') { + return figmaPaintToRadialGradient(paints[i] as FigmaFillPaintGradientRadial, opts); + } + } + } + } + return 'transparent'; +} diff --git a/packages/figma/src/figma-node/ellipse.ts b/packages/figma/src/figma-node/ellipse.ts new file mode 100644 index 0000000..e1e7006 --- /dev/null +++ b/packages/figma/src/figma-node/ellipse.ts @@ -0,0 +1,27 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, nodeToBaseDetail } from './base'; +import { nodeToOperations } from './operations'; +import { mergeNodeOverrideData } from '../common/node'; +import type { FigmaNode, FigmaParseOptions } from '../types'; + +export function ellipseNodeToCircleElement(figmaNode: FigmaNode<'ELLIPSE'>, opts: FigmaParseOptions<'ELLIPSE'>): Element<'circle'> { + const overrideData = mergeNodeOverrideData<'ELLIPSE'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + + const elemBase = nodeToElementBase(node as FigmaNode); + const { w, h } = elemBase; + const radius = Math.max(w, h) / 2; + const baseDetail = nodeToBaseDetail(node as FigmaNode); + const operations = nodeToOperations(node as FigmaNode); + + const elem: Element<'circle'> = { + ...elemBase, + type: 'circle', + detail: { + ...(baseDetail as Element<'circle'>['detail']), + radius + }, + operations + }; + return elem; +} diff --git a/packages/figma/src/figma-node/gradient.ts b/packages/figma/src/figma-node/gradient.ts new file mode 100644 index 0000000..1e0dafb --- /dev/null +++ b/packages/figma/src/figma-node/gradient.ts @@ -0,0 +1,69 @@ +// import { matrixInverse } from '../common/matrix-inverse'; +// @ts-ignore +import matrixInverse from 'matrix-inverse'; +import type { FigmaTransform } from '../types'; + +// https://github.com/figma-plugin-helper-functions/figma-plugin-helpers/blob/52136d7f7628ca704bb3905dc1e20f7ef50036f7/src/helpers/applyMatrixToPoint.ts +function applyMatrixToPoint(matrix: number[][], point: number[]) { + return [point[0] * matrix[0][0] + point[1] * matrix[0][1] + matrix[0][2], point[0] * matrix[1][0] + point[1] * matrix[1][1] + matrix[1][2]]; +} + +// https://github.com/figma-plugin-helper-functions/figma-plugin-helpers/blob/52136d7f7628ca704bb3905dc1e20f7ef50036f7/src/helpers/extractLinearGradientStartEnd.ts +export function parseLinearGradientParamsFromTransform(shapeWidth: number, shapeHeight: number, figmatTransform: FigmaTransform) { + const { m00, m01, m02, m10, m11, m12 } = figmatTransform; + const t = [ + [m00, m01, m02], + [m10, m11, m12] + ]; + const transform = t.length === 2 ? [...t, [0, 0, 1]] : [...t]; + const mxInv = matrixInverse(transform); + // const mxInv = transform; + const startEnd = [ + [0, 0.5], + [1, 0.5] + ].map((p) => applyMatrixToPoint(mxInv, p)); + return { + start: { + x: startEnd[0][0] * shapeWidth, + y: startEnd[0][1] * shapeHeight + }, + + end: { + x: startEnd[1][0] * shapeWidth, + y: startEnd[1][1] * shapeHeight + } + + // start: { + // x: startEnd[0][0] * shapeWidth, + // y: startEnd[1][1] * shapeHeight + // }, + + // end: { + // x: startEnd[1][0] * shapeWidth, + // y: startEnd[0][1] * shapeHeight + // } + }; +} + +// https://github.com/figma-plugin-helper-functions/figma-plugin-helpers/blob/52136d7f7628ca704bb3905dc1e20f7ef50036f7/src/helpers/extractRadialOrDiamondGradientParams.ts +export function parseRadialOrDiamondGradientParamsFromTransform(shapeWidth: number, shapeHeight: number, figmatTransform: FigmaTransform) { + const { m00, m01, m02, m10, m11, m12 } = figmatTransform; + const t = [ + [m00, m01, m02], + [m10, m11, m12] + ]; + const transform = t.length === 2 ? [...t, [0, 0, 1]] : [...t]; + const mxInv = matrixInverse(transform); + // const mxInv = transform; + const centerPoint = applyMatrixToPoint(mxInv, [0.5, 0.5]); + const rxPoint = applyMatrixToPoint(mxInv, [1, 0.5]); + const ryPoint = applyMatrixToPoint(mxInv, [0.5, 1]); + const rx = Math.sqrt(Math.pow(rxPoint[0] - centerPoint[0], 2) + Math.pow(rxPoint[1] - centerPoint[1], 2)); + const ry = Math.sqrt(Math.pow(ryPoint[0] - centerPoint[0], 2) + Math.pow(ryPoint[1] - centerPoint[1], 2)); + const angle = Math.atan((rxPoint[1] - centerPoint[1]) / (rxPoint[0] - centerPoint[0])) * (180 / Math.PI); + return { + rotation: angle, + center: [centerPoint[0] * shapeWidth, centerPoint[1] * shapeHeight], + radius: [rx * shapeWidth, ry * shapeHeight] + }; +} diff --git a/packages/figma/src/figma-node/image.ts b/packages/figma/src/figma-node/image.ts new file mode 100644 index 0000000..7243a59 --- /dev/null +++ b/packages/figma/src/figma-node/image.ts @@ -0,0 +1,83 @@ +import type { Element, ElementImageDetail } from '@idraw/types'; +import { nodeToElementBase, nodeToBaseDetail, getFillPathCommands } from './base'; +import { nodeToOperations } from './operations'; +import type { FigmaNode, FigmaFillPaint, FigmaFillPaintImage, FigmaParseOptions } from '../types'; +import { figmaImageDir } from '../config'; +import { mergeNodeOverrideData, uint8ArrayToBase64 } from '../common/node'; + +async function getFillImageDetail(fillPaints: FigmaFillPaint[], opts: FigmaParseOptions): Promise { + const { figmaMap } = opts; + const detail: ElementImageDetail = { + src: '' + }; + for (let i = 0; i < fillPaints.length; i++) { + if (fillPaints[i].type === 'IMAGE') { + const fillPaintImage: FigmaFillPaintImage = fillPaints[i] as FigmaFillPaintImage; + const { image, imageScaleMode, originalImageHeight, originalImageWidth } = fillPaintImage; + const hashStr = Array.from(image.hash) + .map((num) => num.toString(16).padStart(2, '0')) + .join(''); + const imageKey = `${figmaImageDir}${hashStr}`; + const imageBuffer = figmaMap[imageKey]; + if (imageBuffer) { + const base64 = await uint8ArrayToBase64(imageBuffer as Uint8Array, { type: 'image/png' }); + detail.src = base64; + } + if (imageScaleMode === 'FILL') { + detail.scaleMode = 'fill'; + } else if (imageScaleMode === 'FIT') { + detail.scaleMode = 'fit'; + } else if (imageScaleMode === 'TILE') { + detail.scaleMode = 'tile'; + } + if (originalImageHeight >= 0) { + detail.originH = originalImageHeight; + } + if (originalImageWidth >= 0) { + detail.originW = originalImageWidth; + } + } + } + return detail; +} + +export async function nodeToImageElement(figmaNode: FigmaNode, opts: FigmaParseOptions): Promise> { + const overrideData = mergeNodeOverrideData(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + + const { fillPaints, fillGeometry } = node; + const elemBase = nodeToElementBase(node); + const elem: Element<'image'> = { + ...elemBase, + type: 'image', + detail: { + src: '' + } + }; + const operations: Required>['operations'] = nodeToOperations(node); + let detail: Element<'image'>['detail'] = nodeToBaseDetail(node) as Element<'image'>['detail']; + let imageDetail = await getFillImageDetail(fillPaints, opts); + detail = { + ...detail, + ...imageDetail + }; + + if (Array.isArray(fillGeometry) && fillGeometry.length > 0) { + const commands = getFillPathCommands(node); + detail.clipPath = { + commands, + originX: 0, + originY: 0, + originW: elemBase.w, + originH: elemBase.h + }; + detail.clipPathStrokeColor = detail.borderColor; + if (typeof detail.borderWidth === 'number') { + detail.clipPathStrokeWidth = detail.borderWidth; + } + } + + elem.operations = operations; + elem.detail = detail as Element<'image'>['detail']; + return elem; +} diff --git a/packages/figma/src/figma-node/line.ts b/packages/figma/src/figma-node/line.ts new file mode 100644 index 0000000..a891f94 --- /dev/null +++ b/packages/figma/src/figma-node/line.ts @@ -0,0 +1,40 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, getStrokeColor, getStrokePathCommands } from './base'; +import { nodeToOperations } from './operations'; +import { mergeNodeOverrideData } from '../common/node'; +import type { FigmaNode, FigmaParseOptions } from '../types'; + +// TODO +export function lineNodeToPathElement(figmaNode: FigmaNode<'LINE'>, opts: FigmaParseOptions<'LINE'>): Element<'path'> { + const overrideData = mergeNodeOverrideData<'LINE'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + + const elemBase = nodeToElementBase(node); + const strokeWidth = node.strokeWeight || 1; + const height = elemBase.h || strokeWidth; + const y = elemBase.h ? elemBase.y : elemBase.y - height / 2; + const elem: Element<'path'> = { + ...elemBase, + y, + h: height, + type: 'path', + detail: { + commands: getStrokePathCommands(node), + // strokeWidth: 1, + originX: 0, + originY: -height, + originW: elemBase.w, + originH: height + } + }; + const strokeColor = getStrokeColor(node); + if (strokeColor) { + // elem.detail.stroke = strokeColor; + elem.detail.fill = strokeColor; + } + const operations: Required>['operations'] = nodeToOperations(node); + // const detail: Required>['detail'] = nodeToBaseDetail(node); + elem.operations = operations; + // elem.detail = detail; + return elem; +} diff --git a/packages/figma/src/figma-node/node.ts b/packages/figma/src/figma-node/node.ts new file mode 100644 index 0000000..92bf8d9 --- /dev/null +++ b/packages/figma/src/figma-node/node.ts @@ -0,0 +1,298 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, nodeToBaseDetail, hasFillImage } from './base'; +import { figmaColorToHex, figmaPaintsToColor } from './color'; +import { textNodeToTextElement } from './text'; +import { nodeToImageElement } from './image'; +import { roundedRectangleNodeToRectElement } from './rectangle'; +import { ellipseNodeToCircleElement } from './ellipse'; +import { regularPolygonNodeToPathElement } from './regular-polygon'; +import { lineNodeToPathElement } from './line'; +import { starNodeToPathElement } from './star'; +import { vectorNodeToPathElement } from './vector'; +import { getOverrideNodeMap, mergeNodeOverrideData } from '../common/node'; +import { nodeToOperations } from './operations'; + +import type { FigmaGUID, FigmaNode, FigmaNodeType, FigmaParseOptions, FigmaSymbolOverrideItem, FigmaInstanceNode } from '../types'; +import { figmaGUIDToID } from '../common/node'; +import { resetGroupSize } from '../common/calc'; + +async function instanceNodeToGroupElement(figmaNode: FigmaNode<'INSTANCE'>, opts: FigmaParseOptions<'INSTANCE'>): Promise> { + const { backupNodeMap } = opts; + const overrideData = mergeNodeOverrideData<'INSTANCE'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + const { derivedSymbolData } = node; + const elemBase = nodeToElementBase(node); + const elem: Element<'group'> = { + ...elemBase, + type: 'group', + detail: { + children: [] + } + }; + const operations: Required>['operations'] = nodeToOperations(node); + const detail: Partial['detail']> = nodeToBaseDetail(node); + elem.detail = { + ...elem.detail, + ...detail + }; + + if (Array.isArray(derivedSymbolData)) { + for (let i = 0; i < derivedSymbolData.length; i++) { + const item = derivedSymbolData[i]; + const { guidPath, ...restProperties } = item; + // const { fillGeometry, strokeGeometry, } = item as Partial>; + + let copyNode: FigmaNode | undefined = undefined; + if (Array.isArray(item.guidPath.guids) && item.guidPath.guids.length > 0) { + // TODO + const id = figmaGUIDToID(item.guidPath.guids[0]); + copyNode = backupNodeMap[id]; + } + + if (copyNode) { + const childNode = { ...copyNode, ...restProperties }; + const chidElem = await figmaNodeToElement(childNode, opts); + elem.detail.children.push(chidElem as Element); + } + + // const baseSize: ElementSize = { + // x: 0, // TODO + // y: 0, // TODO + // w: elemBase.w, + // h: elemBase.h + // }; + // if (restProperties.size) { + // baseSize.w = restProperties.size.x; + // baseSize.h = restProperties.size.y; + // } + } + } + + elem.operations = operations; + + return elem; +} + +async function nestedNodeToGroupElement( + figmaNode: FigmaNode<'CANVAS'> | FigmaNode<'FRAME'> | FigmaNode<'SYMBOL'> | FigmaNode<'BOOLEAN_OPERATION'>, + opts: FigmaParseOptions +): Promise> { + const overrideData = mergeNodeOverrideData(figmaNode as any, opts); + const node: FigmaNode = { ...figmaNode, ...overrideData } as FigmaNode; + const elemBase = nodeToElementBase(node); + let group: Element<'group'> = { + ...elemBase, + type: 'group', + detail: { + children: [], + overflow: 'visible' + }, + operations: nodeToOperations(node) + }; + // const baseDetail = nodeToBaseDetail(treeNode.node); + if ((node as unknown as FigmaNode<'FRAME'>).type === 'FRAME') { + // const background = figmaPaintsToHexColor(node.fillPaints); + const background = figmaPaintsToColor(node.fillPaints, { w: elemBase.w, h: elemBase.h }); + + if (background) { + group.detail.background = background; + } + } + + if (node.backgroundColor) { + if (!group.global) { + group.global = {}; + } + group.global.background = figmaColorToHex(node.backgroundColor); + } + + if (Array.isArray(node.children)) { + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + const elem: Element = (await figmaNodeToElement(child, opts as FigmaParseOptions)) as Element; + group.detail.children.push(elem); + } + + group.detail.children.reverse(); + } + + if (['FRAME', 'BOOLEAN_OPERATION'].includes(node.type)) { + if (group.x === 0 || group.y === 0) { + const size = resetGroupSize(group); + group = { + ...size, + ...group + }; + } + } + + if ((node as unknown as FigmaNode<'FRAME'>).type === 'FRAME') { + const figmaNode = node as unknown as FigmaNode<'FRAME'>; + if (figmaNode.frameMaskDisabled === true) { + group.detail.overflow = 'visible'; + } else { + group.detail.overflow = 'hidden'; + } + } + + return group; +} + +async function canvasNodeToGroupElement(node: FigmaNode<'CANVAS'>, opts: FigmaParseOptions): Promise> { + return await nestedNodeToGroupElement(node, opts); +} + +async function booleanOperationNodeToGroupElement( + node: FigmaNode<'BOOLEAN_OPERATION'>, + opts: FigmaParseOptions<'BOOLEAN_OPERATION'> +): Promise> { + const { overrideNodeMap = {} } = opts; + const overrideProperties: FigmaNode = {} as FigmaNode; + const { fillPaints, strokePaints, fillGeometry, strokeGeometry } = node; + + let useFillGeometry = false; + if (Array.isArray(fillPaints) && fillPaints.length > 0 && Array.isArray(fillGeometry) && fillGeometry.length > 0) { + useFillGeometry = fillPaints.findIndex((p) => p.visible === true) >= 0; + } + + let useStrokeGeometry = false; + if (Array.isArray(strokePaints) && strokePaints.length > 0 && Array.isArray(strokeGeometry) && strokeGeometry.length > 0) { + useStrokeGeometry = strokePaints.findIndex((p) => p.visible === true) >= 0; + } + + if (useFillGeometry === true || useStrokeGeometry === true) { + return await vectorNodeToPathElement(node as unknown as FigmaNode<'VECTOR'>, opts as FigmaParseOptions<'VECTOR'>); + } + + if (Array.isArray(fillPaints) && fillPaints.length > 0) { + overrideProperties.fillPaints = fillPaints; + } + if (Array.isArray(strokePaints) && strokePaints.length > 0) { + overrideProperties.strokePaints = strokePaints; + } + + return await nestedNodeToGroupElement({ ...node, ...overrideNodeMap[figmaGUIDToID(node.guid)] }, { + ...opts, + ...{ overrideProperties: overrideProperties as any } + } as FigmaParseOptions); +} + +async function frameNodeToGroupElement(node: FigmaNode<'FRAME'>, opts: FigmaParseOptions<'FRAME'>): Promise> { + return await nestedNodeToGroupElement(node, opts); +} + +async function symbolNodeToGroupElement(node: FigmaNode<'SYMBOL'>, opts: FigmaParseOptions<'SYMBOL'>): Promise> { + return await nestedNodeToGroupElement(node, opts); +} + +async function instanceNodeToElement(node: FigmaNode<'INSTANCE'>, opts: FigmaParseOptions<'INSTANCE'>): Promise { + const { instanceNodeMap, overrideProperties } = opts; + const overrideNodeMap = { + ...opts.overrideNodeMap, + ...getOverrideNodeMap(node) + }; + const symbolID = figmaGUIDToID(node.symbolData.symbolID); + let symbolNode = instanceNodeMap[symbolID]; + + let newOverrideProperties: Partial = { + ...overrideProperties + }; + + if (symbolNode) { + symbolNode = { + ...symbolNode, + ...{ + visible: node.visible + } + }; + const elemSize = nodeToElementBase(node); + const overrideData = mergeNodeOverrideData<'INSTANCE'>(node, opts); + + // console.log(' -------------- node -------------- ', node.name, figmaGUIDToID(node.guid), symbolID); + // console.log('node =', node); + // console.log('overrideProperties =', overrideProperties); + // console.log('symbolNode = ', symbolNode); + // console.log('instanceNodeMap =', instanceNodeMap); + // console.log('overrideNodeMap =', overrideNodeMap); + // console.log('overrideData =======', node.overrideKey, overrideData); + + if ((overrideData as FigmaSymbolOverrideItem).overriddenSymbolID) { + const overriddenSymbolID = figmaGUIDToID((overrideData as FigmaSymbolOverrideItem).overriddenSymbolID as FigmaGUID); + + if (instanceNodeMap[overriddenSymbolID]) { + const overriddenSymbolNode = instanceNodeMap[overriddenSymbolID]; + symbolNode = { + ...symbolNode, + ...overriddenSymbolNode + }; + } + } else { + // TODO + const { textData } = overrideData as Partial>; + if (textData) { + (newOverrideProperties as unknown as FigmaNode<'TEXT'>).textData = textData; + } + } + + const elem = await figmaNodeToElement(symbolNode, { + ...opts, + ...{ overrideNodeMap, overrideProperties: newOverrideProperties as Record> } + }); + if (elem) { + return { + ...elem, + ...elemSize + }; + } + return elem; + } + return await instanceNodeToGroupElement(node, opts as FigmaParseOptions<'INSTANCE'>); +} + +export async function figmaNodeToElement(node: FigmaNode, opts: FigmaParseOptions): Promise { + if (node.type === 'CANVAS') { + let elem: Element<'group'> = await canvasNodeToGroupElement(node as FigmaNode<'CANVAS'>, opts as FigmaParseOptions<'CANVAS'>); + return elem; + } else if (node.type === 'FRAME') { + const elem: Element<'group'> = await frameNodeToGroupElement(node as FigmaNode<'FRAME'>, opts as FigmaParseOptions<'FRAME'>); + return elem; + } else if (node.type === 'SYMBOL') { + const elem: Element<'group'> = await symbolNodeToGroupElement(node as FigmaNode<'SYMBOL'>, opts as FigmaParseOptions<'SYMBOL'>); + return elem; + } else if (hasFillImage(node as unknown as FigmaNode)) { + const elem: Element<'image'> = await nodeToImageElement(node as unknown as FigmaNode, opts as FigmaParseOptions); + return elem; + } else if (node.type === 'ROUNDED_RECTANGLE') { + const elem: Element<'rect'> = roundedRectangleNodeToRectElement(node as FigmaNode<'ROUNDED_RECTANGLE'>, opts as FigmaParseOptions<'ROUNDED_RECTANGLE'>); + return elem; + } else if (node.type === 'ELLIPSE') { + const elem: Element<'circle'> = ellipseNodeToCircleElement(node as FigmaNode<'ELLIPSE'>, opts as FigmaParseOptions<'ELLIPSE'>); + return elem; + } else if (node.type === 'TEXT') { + const elem: Element<'text'> = textNodeToTextElement(node as FigmaNode<'TEXT'>, opts as FigmaParseOptions<'TEXT'>); + return elem; + } else if (node.type === 'REGULAR_POLYGON') { + const elem: Element<'path'> = regularPolygonNodeToPathElement(node as FigmaNode<'REGULAR_POLYGON'>, opts as FigmaParseOptions<'REGULAR_POLYGON'>); + return elem; + } else if (node.type === 'LINE') { + const elem: Element<'path'> = lineNodeToPathElement(node as FigmaNode<'LINE'>, opts as FigmaParseOptions<'LINE'>); + return elem; + } else if (node.type === 'STAR') { + const elem: Element<'path'> = starNodeToPathElement(node as FigmaNode<'STAR'>, opts as FigmaParseOptions<'STAR'>); + return elem; + } else if (node.type === 'VECTOR') { + const elem: Element<'path'> = vectorNodeToPathElement(node as FigmaNode<'VECTOR'>, opts as FigmaParseOptions<'VECTOR'>); + return elem; + } else if (node.type === 'INSTANCE') { + const elem: Element | null = await instanceNodeToElement(node as FigmaNode<'INSTANCE'>, opts as FigmaParseOptions<'INSTANCE'>); + return elem; + } else if (node.type === 'BOOLEAN_OPERATION') { + const elem: Element | null = await booleanOperationNodeToGroupElement( + node as FigmaNode<'BOOLEAN_OPERATION'>, + opts as FigmaParseOptions<'BOOLEAN_OPERATION'> + ); + return elem; + } + + return null; +} diff --git a/packages/figma/src/figma-node/operations.ts b/packages/figma/src/figma-node/operations.ts new file mode 100644 index 0000000..a92be90 --- /dev/null +++ b/packages/figma/src/figma-node/operations.ts @@ -0,0 +1,18 @@ +import type { ElementOperations } from '@idraw/types'; +import type { FigmaNode, FigmaNodeType } from '../types'; + +export function nodeToOperations(node: FigmaNode): ElementOperations { + const operations: ElementOperations = {}; + const { visible } = node as FigmaNode; + + if (visible === false) { + operations.invisible = true; + } + + // TODO + if (node.mask === true) { + operations.invisible = true; + } + + return operations; +} diff --git a/packages/figma/src/figma-node/rectangle.ts b/packages/figma/src/figma-node/rectangle.ts new file mode 100644 index 0000000..68a76ae --- /dev/null +++ b/packages/figma/src/figma-node/rectangle.ts @@ -0,0 +1,22 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, nodeToBaseDetail } from './base'; +import { nodeToOperations } from './operations'; +import { mergeNodeOverrideData } from '../common/node'; +import type { FigmaNode, FigmaParseOptions } from '../types'; + +export function roundedRectangleNodeToRectElement(figmaNode: FigmaNode<'ROUNDED_RECTANGLE'>, opts: FigmaParseOptions<'ROUNDED_RECTANGLE'>): Element<'rect'> { + const overrideData = mergeNodeOverrideData<'ROUNDED_RECTANGLE'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + + const elemBase = nodeToElementBase(node as FigmaNode); + const elem: Element<'rect'> = { + ...elemBase, + type: 'rect', + detail: {} + }; + const operations: Required>['operations'] = nodeToOperations(node as FigmaNode); + const detail: Required>['detail'] = nodeToBaseDetail(node as FigmaNode); + elem.operations = operations; + elem.detail = detail; + return elem; +} diff --git a/packages/figma/src/figma-node/regular-polygon.ts b/packages/figma/src/figma-node/regular-polygon.ts new file mode 100644 index 0000000..9172423 --- /dev/null +++ b/packages/figma/src/figma-node/regular-polygon.ts @@ -0,0 +1,31 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, getFillColor, getFillPathCommands } from './base'; +import { nodeToOperations } from './operations'; +import { mergeNodeOverrideData } from '../common/node'; +import type { FigmaNode, FigmaParseOptions } from '../types'; + +export function regularPolygonNodeToPathElement(figmaNode: FigmaNode<'REGULAR_POLYGON'>, opts: FigmaParseOptions<'REGULAR_POLYGON'>): Element<'path'> { + const overrideData = mergeNodeOverrideData<'REGULAR_POLYGON'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + const elemBase = nodeToElementBase(node); + const elem: Element<'path'> = { + ...elemBase, + type: 'path', + detail: { + commands: getFillPathCommands(node), + originX: 0, + originY: 0, + originW: elemBase.w, + originH: elemBase.h + } + }; + const fillColor = getFillColor(node); + if (fillColor) { + elem.detail.fill = fillColor; + } + const operations: Required>['operations'] = nodeToOperations(node); + // const detail: Required>['detail'] = nodeToBaseDetail(node); + elem.operations = operations; + // elem.detail = detail; + return elem; +} diff --git a/packages/figma/src/figma-node/star.ts b/packages/figma/src/figma-node/star.ts new file mode 100644 index 0000000..da96147 --- /dev/null +++ b/packages/figma/src/figma-node/star.ts @@ -0,0 +1,32 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase, getFillColor, getFillPathCommands } from './base'; +import { nodeToOperations } from './operations'; +import { mergeNodeOverrideData } from '../common/node'; +import type { FigmaNode, FigmaParseOptions } from '../types'; + +export function starNodeToPathElement(figmaNode: FigmaNode<'STAR'>, opts: FigmaParseOptions<'STAR'>): Element<'path'> { + const overrideData = mergeNodeOverrideData<'STAR'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + + const elemBase = nodeToElementBase(node); + const elem: Element<'path'> = { + ...elemBase, + type: 'path', + detail: { + commands: getFillPathCommands(node), + originX: 0, + originY: 0, + originW: elemBase.w, + originH: elemBase.h + } + }; + const fillColor = getFillColor(node); + if (fillColor) { + elem.detail.fill = fillColor; + } + const operations: Required>['operations'] = nodeToOperations(node); + // const detail: Required>['detail'] = nodeToBaseDetail(node); + elem.operations = operations; + // elem.detail = detail; + return elem; +} diff --git a/packages/figma/src/figma-node/text.ts b/packages/figma/src/figma-node/text.ts new file mode 100644 index 0000000..0000bec --- /dev/null +++ b/packages/figma/src/figma-node/text.ts @@ -0,0 +1,83 @@ +import type { Element } from '@idraw/types'; +import { nodeToElementBase } from './base'; +import { figmaPaintsToHexColor } from './color'; +import { nodeToOperations } from './operations'; +import type { FigmaNode, FigmaParseOptions } from '../types'; +import { mergeNodeOverrideData } from '../common/node'; + +const defaultFontWeight = 400; + +export function textNodeToTextElement(figmaNode: FigmaNode<'TEXT'>, opts: FigmaParseOptions<'TEXT'>): Element<'text'> { + const overrideData = mergeNodeOverrideData<'TEXT'>(figmaNode, opts); + const node = { ...figmaNode, ...overrideData }; + const { textData, fontSize, fillPaints, fontName, textAlignHorizontal, textAlignVertical, textCase, lineHeight } = node; + const { fontMetaData } = textData; + const elemBase = nodeToElementBase(node as FigmaNode); + + const elem: Element<'text'> = { + ...elemBase, + type: 'text', + detail: { + text: textData.characters, + fontFamily: fontName.family, + // fontFamily: 'arial, sans-serif', + fontSize: fontSize, + textAlign: 'left', + verticalAlign: 'top', + wordBreak: 'normal', + overflow: 'visible', + minInlineSize: 'auto' + } + }; + + if (lineHeight.value > 0 && lineHeight.units === 'PIXELS') { + elem.detail.lineHeight = lineHeight.value; + } + + // if (!((elem.detail.lineHeight as number) > 0 && elemBase.h > (elem.detail.lineHeight as number))) { + // elem.detail.minInlineSize = 'maxContent'; + // } + + const color = figmaPaintsToHexColor(fillPaints); + if (color) { + elem.detail.color = color; + } + + if (typeof node.opacity === 'number' && node.opacity >= 0) { + elem.detail.opacity = node.opacity; + } + + if (Array.isArray(fontMetaData) && fontMetaData.length > 0) { + const fontMeta = fontMetaData[0]; + const { fontWeight = defaultFontWeight } = fontMeta; + elem.detail.fontWeight = fontWeight; + // elem.detail.lineHeight = fontLineHeight * fontSize; + } + + if (textAlignHorizontal === 'LEFT') { + elem.detail.textAlign = 'left'; + } else if (textAlignHorizontal === 'RIGHT') { + elem.detail.textAlign = 'right'; + } else if (textAlignHorizontal === 'CENTER') { + elem.detail.textAlign = 'center'; + } + + if (textAlignVertical === 'TOP') { + elem.detail.verticalAlign = 'top'; + } else if (textAlignVertical === 'BOTTOM') { + elem.detail.verticalAlign = 'bottom'; + } else if (textAlignVertical === 'CENTER') { + elem.detail.verticalAlign = 'middle'; + } + + if (textCase === 'UPPER') { + elem.detail.textTransform = 'uppercase'; + } else if (textCase === 'LOWER') { + elem.detail.textTransform = 'lowercase'; + } + + const operations: Required>['operations'] = nodeToOperations(node as FigmaNode); + elem.operations = operations; + + return elem; +} diff --git a/packages/figma/src/figma-node/vector.ts b/packages/figma/src/figma-node/vector.ts new file mode 100644 index 0000000..55c1a74 --- /dev/null +++ b/packages/figma/src/figma-node/vector.ts @@ -0,0 +1,136 @@ +import type { Element, SVGPathCommand } from '@idraw/types'; +import { nodeToElementBase, getStrokeColor, getStrokePathCommands, getFillAttributes, getFillColor, getShadow } from './base'; +import { nodeToOperations } from './operations'; +import type { FigmaNode, FigmaParseOptions, FigmaVectorNode } from '../types'; +import { mergeNodeOverrideData } from '../common/node'; +import { figmaPaintsToColor } from './color'; + +type SVGPathDetail = Pick['detail'], 'commands' | 'stroke' | 'fill' | 'strokeWidth' | 'fillRule'>; + +function getSVGPathDetail(node: FigmaVectorNode, opts: FigmaParseOptions<'VECTOR'>): SVGPathDetail { + const { vectorData, strokeGeometry, fillGeometry, size, strokeWeight } = node; + const { overrideProperties } = opts; + const detail: SVGPathDetail = { + commands: [] + }; + + const fillColor = figmaPaintsToColor(node.fillPaints || [], { w: size.x, h: size.y }); + const strokeColor = getStrokeColor(node); + + // console.log('x --------- ', node.guid); + // console.log('x --------- strokeGeometry ', strokeGeometry); + // console.log('x --------- strokeWeight ', strokeWeight); + // console.log('x --------- strokePaints ', node.strokePaints); + // console.log('x --------- fillGeometry ', fillGeometry); + // console.log('x --------- fillPaints ', node.fillPaints); + + // if (strokeWeight > 0 && fillColor && strokeColor && vectorData?.vectorNetwork) { + // const pathCmds: SVGPathCommand[] = []; + // const { vectorNetwork } = vectorData; + // const { segments, vertices } = vectorNetwork; + // if (Array.isArray(segments) && Array.isArray(vertices)) { + // for (const { start, end } of segments) { + // const from = vertices[start.vertex]; + // const to = vertices[end.vertex]; + // pathCmds.push({ + // type: 'M', + // params: [from.x, from.y] + // }); + // pathCmds.push({ + // type: 'C', + // params: [from.x + start.dx, from.y + start.dy, to.x + end.dx, to.y + end.dy, to.x, to.y] + // }); + // // ctx.moveTo(from.x, from.y); + // // ctx.bezierCurveTo(from.x + start.dx, from.y + start.dy, to.x + end.dx, to.y + end.dy, to.x, to.y); + // } + // } + // detail.commands = pathCmds; + + // detail.stroke = strokeColor; + // detail.strokeWidth = strokeWeight; + // detail.fill = fillColor; + // } + if (Array.isArray(strokeGeometry) && strokeGeometry.length > 0) { + detail.commands = getStrokePathCommands(node); + if (overrideProperties?.fillPaints) { + if (fillColor) { + detail.fill = fillColor; + } + } else { + if (strokeColor) { + detail.fill = strokeColor; + } + } + } else if (Array.isArray(fillGeometry) && fillGeometry.length > 0) { + const { commands, fillRule } = getFillAttributes(node); + detail.commands = commands; + if (fillRule) { + detail.fillRule = fillRule; + } + if (fillColor) { + detail.fill = fillColor; + } + } else if (strokeGeometry) { + detail.commands = getStrokePathCommands(node); + if (strokeColor) { + detail.fill = strokeColor; + } + } else if (vectorData.vectorNetwork) { + const pathCmds: SVGPathCommand[] = []; + const { vectorNetwork } = vectorData; + const { segments, vertices } = vectorNetwork; + if (Array.isArray(segments) && Array.isArray(vertices)) { + for (const { start, end } of segments) { + const from = vertices[start.vertex]; + const to = vertices[end.vertex]; + pathCmds.push({ + type: 'M', + params: [from.x, from.y] + }); + pathCmds.push({ + type: 'C', + params: [from.x + start.dx, from.y + start.dy, to.x + end.dx, to.y + end.dy, to.x, to.y] + }); + // ctx.moveTo(from.x, from.y); + // ctx.bezierCurveTo(from.x + start.dx, from.y + start.dy, to.x + end.dx, to.y + end.dy, to.x, to.y); + } + } + detail.commands = pathCmds; + + if (strokeColor) { + detail.stroke = strokeColor; + detail.strokeWidth = node.strokeWeight || 1; + } + if (fillColor) { + detail.fill = fillColor; + } + } + + return detail; +} + +export function vectorNodeToPathElement(figmaNode: FigmaNode<'VECTOR'>, opts: FigmaParseOptions<'VECTOR'>): Element<'path'> { + const overrideData = mergeNodeOverrideData<'VECTOR'>(figmaNode, opts); + + const node = { ...figmaNode, ...overrideData }; + const elemBase = nodeToElementBase(node as FigmaNode); + const elem: Element<'path'> = { + ...elemBase, + type: 'path', + detail: { + ...getSVGPathDetail(node as FigmaVectorNode, opts), + ...(Array.isArray(node.effects) && node.effects.length > 0 ? getShadow(node.effects) : {}), + // strokeWidth: node.strokeWeight || 1, + originX: 0, + originY: 0, + originW: elemBase.w, + originH: elemBase.h + } + }; + + const operations: Required>['operations'] = nodeToOperations(node as FigmaNode); + // const detail: Required>['detail'] = nodeToBaseDetail(node); + elem.operations = operations; + // elem.detail = detail; + return elem; +} diff --git a/packages/figma/src/figma-object/index.ts b/packages/figma/src/figma-object/index.ts new file mode 100644 index 0000000..868baf9 --- /dev/null +++ b/packages/figma/src/figma-object/index.ts @@ -0,0 +1,88 @@ +import { parse as parseZIP } from 'uzip'; +import type { Data, Element } from '@idraw/types'; +import { parseCanvasFigBytes } from './parser'; +import type { FigmaMap, FigmaParseOptions } from '../types'; +import { figmaNodeToElement } from '../figma-node/node'; +import { figmaGUIDToID } from '../common/node'; +import { resetGroupSize } from '../common/calc'; + +const canvasFileName = 'canvas.fig'; +const metaFileName = 'meta.json'; + +export async function figmaBytesToMap(bytes: Uint8Array): Promise { + const unzipped = parseZIP(bytes); + + const fileKeys = Object.keys(unzipped); + const map: Partial = {}; // TODO + + for (let i = 0; i < fileKeys.length; i++) { + const fileKey = fileKeys[i]; + if (fileKey === canvasFileName) { + const canvasFig = unzipped[canvasFileName] as Uint8Array; + const canvasResult: FigmaMap['canvas.fig'] = parseCanvasFigBytes({ bytes: canvasFig }); + map[fileKey] = canvasResult; + } else if (fileKey === metaFileName) { + const metaJSON = unzipped[metaFileName] as Uint8Array; + const metaResult = JSON.parse(new TextDecoder().decode(metaJSON)); + map[fileKey] = metaResult; + } else { + map[fileKey] = unzipped[fileKey]; + } + } + + return map as FigmaMap; +} + +function figmaMapToParseOptions(figmaMap: FigmaMap): FigmaParseOptions { + const instanceNodeMap: FigmaParseOptions['instanceNodeMap'] = {}; + const canvasFig = figmaMap['canvas.fig']; + const { root, backupNodeMap } = canvasFig; + if (Array.isArray(root.children)) { + root.children.forEach((child) => { + if (child?.type === 'CANVAS' && child.internalOnly === true && Array.isArray(child.children)) { + child.children.forEach((item) => { + const id = figmaGUIDToID(item.guid); + instanceNodeMap[id] = item; + }); + } + }); + } + + const opts: FigmaParseOptions = { + figmaMap, + instanceNodeMap, + backupNodeMap + }; + + return opts; +} + +export async function figmaMapToIDrawData(figmaMap: FigmaMap): Promise { + const data: Data = { elements: [] }; + const canvasFig: FigmaMap['canvas.fig'] = figmaMap['canvas.fig']; + const { root } = canvasFig; + + // // TODO + // console.log('root =', root); + + if (Array.isArray(root.children)) { + for (let i = 0; i < root.children.length; i++) { + const child = root.children[i]; + if (child.internalOnly === true) { + continue; + } + const elem: Element = (await figmaNodeToElement(child, figmaMapToParseOptions(figmaMap))) as Element; + if (elem.type === 'group' && (elem.w === 0 || elem.h === 0)) { + resetGroupSize(elem as Element<'group'>); + } + data.elements.push(elem); + } + } + return data; +} + +export async function figmaBytesToIDrawData(bytes: Uint8Array): Promise { + const figmaMap = await figmaBytesToMap(bytes); + const data = await figmaMapToIDrawData(figmaMap); + return data; +} diff --git a/packages/figma/src/figma-object/parser.ts b/packages/figma/src/figma-object/parser.ts new file mode 100644 index 0000000..72ce924 --- /dev/null +++ b/packages/figma/src/figma-object/parser.ts @@ -0,0 +1,243 @@ +import { compileSchema, decodeBinarySchema } from 'kiwi-schema'; +import pako from 'pako'; +import type { FigmaNode } from '../types'; + +function parseBlob(key: string, opts: { bytes: Uint8Array }) { + const { bytes } = opts; + const view = new DataView(bytes.buffer); + let offset = 0; + + switch (key) { + case 'vectorNetwork': + if (bytes.length < 12) return; + const vertexCount = view.getUint32(0, true); + const segmentCount = view.getUint32(4, true); + const regionCount = view.getUint32(8, true); + const vertices = []; + const segments = []; + const regions = []; + offset += 12; + + for (let i = 0; i < vertexCount; i++) { + if (offset + 12 > bytes.length) return; + vertices.push({ + styleID: view.getUint32(offset + 0, true), + x: view.getFloat32(offset + 4, true), + y: view.getFloat32(offset + 8, true) + }); + offset += 12; + } + + for (let i = 0; i < segmentCount; i++) { + if (offset + 28 > bytes.length) return; + const startVertex = view.getUint32(offset + 4, true); + const endVertex = view.getUint32(offset + 16, true); + if (startVertex >= vertexCount || endVertex >= vertexCount) return; + segments.push({ + styleID: view.getUint32(offset + 0, true), + start: { + vertex: startVertex, + dx: view.getFloat32(offset + 8, true), + dy: view.getFloat32(offset + 12, true) + }, + end: { + vertex: endVertex, + dx: view.getFloat32(offset + 20, true), + dy: view.getFloat32(offset + 24, true) + } + }); + offset += 28; + } + + for (let i = 0; i < regionCount; i++) { + if (offset + 8 > bytes.length) return; + let styleID = view.getUint32(offset, true); + const windingRule = styleID & 1 ? 'NONZERO' : 'ODD'; + styleID >>= 1; + const loopCount = view.getUint32(offset + 4, true); + const loops = []; + offset += 8; + + for (let j = 0; j < loopCount; j++) { + if (offset + 4 > bytes.length) return; + const indexCount = view.getUint32(offset, true); + const indices = []; + offset += 4; + if (offset + indexCount * 4 > bytes.length) return; + for (let k = 0; k < indexCount; k++) { + const segment = view.getUint32(offset, true); + if (segment >= segmentCount) return; + indices.push(segment); + offset += 4; + } + loops.push({ segments: indices }); + } + + regions.push({ styleID, windingRule, loops }); + } + + return { vertices, segments, regions }; + + case 'commands': + const path = []; + while (offset < bytes.length) { + switch (bytes[offset++]) { + case 0: + path.push('Z'); + break; + + case 1: + if (offset + 8 > bytes.length) return; + path.push('M', view.getFloat32(offset, true), view.getFloat32(offset + 4, true)); + offset += 8; + break; + + case 2: + if (offset + 8 > bytes.length) return; + path.push('L', view.getFloat32(offset, true), view.getFloat32(offset + 4, true)); + offset += 8; + break; + + case 3: + if (offset + 16 > bytes.length) return; + path.push( + 'Q', + view.getFloat32(offset, true), + view.getFloat32(offset + 4, true), + view.getFloat32(offset + 8, true), + view.getFloat32(offset + 12, true) + ); + offset += 16; + break; + + case 4: + if (offset + 24 > bytes.length) return; + path.push( + 'C', + view.getFloat32(offset, true), + view.getFloat32(offset + 4, true), + view.getFloat32(offset + 8, true), + view.getFloat32(offset + 12, true), + view.getFloat32(offset + 16, true), + view.getFloat32(offset + 20, true) + ); + offset += 24; + break; + + default: + return; + } + } + return path; + } +} + +export function parseCanvasFigBytesToNodeChanges(opts: { bytes: Uint8Array }) { + const { bytes } = opts; + const header = String.fromCharCode(...bytes.slice(0, 8)); + if (header !== 'fig-kiwi' && header !== 'fig-jam.') { + throw new Error('Invalid header'); + } + + const view = new DataView(bytes.buffer); + const version = view.getUint32(8, true); + const chunks = []; + let offset = 12; + + while (offset < bytes.length) { + const chunkLength = view.getUint32(offset, true); + offset += 4; + chunks.push(bytes.slice(offset, offset + chunkLength)); + offset += chunkLength; + } + + if (chunks.length < 2) throw new Error('Not enough chunks'); + const encodedSchema = pako.inflateRaw(chunks[0]); + const encodedData = pako.inflateRaw(chunks[1]); + const schema = compileSchema(decodeBinarySchema(encodedSchema)); + const { nodeChanges, blobs } = schema.decodeMessage(encodedData); + + // Make blob contents easier to understand + const substituteBlob = (key: string, value: any) => { + if (key.endsWith('Blob') && typeof value === 'number' && value === value >>> 0 && value < blobs.length) { + key = key.slice(0, -4); + value = blobs[value]; + value = parseBlob(key, value) || value; + } + return [key, value]; + }; + + const walkToParseBlob = (obj: any) => { + const propKeys = Object.keys(obj); + propKeys.forEach((propKey: string) => { + const prop = obj[propKey]; + if (propKey.endsWith('Blob')) { + const [newKey, newValue] = substituteBlob(propKey, prop); + obj[newKey] = newValue; + delete obj[propKey]; + } else if (Array.isArray(prop)) { + prop.forEach((item) => { + walkToParseBlob(item); + }); + } else if (Object.prototype.toString.call(prop) === '[object Object]') { + walkToParseBlob(prop); + } + }); + }; + nodeChanges.forEach((node: any) => { + walkToParseBlob(node); + }); + + return { version, blobs, nodeChanges }; +} + +export function parseCanvasFigBytes(opts: { bytes: Uint8Array }) { + const { version, nodeChanges, blobs } = parseCanvasFigBytesToNodeChanges(opts); + const nodeMap: Record = {}; + const originalNodeChanges: FigmaNode[] = nodeChanges.map((node: any) => { + const item = { ...node }; + const id = `${item.guid.sessionID}:${item.guid.localID}`; + nodeMap[id] = item; + return item; + }); + + const nodes = new Map(); + + const orderByPosition = ( + { parentIndex: { position: a } }: { parentIndex: { position: number } }, + { parentIndex: { position: b } }: { parentIndex: { position: number } } + ) => { + // @ts-ignore + return (a < b) - (a > b); + }; + + for (const node of nodeChanges) { + const { sessionID, localID } = node.guid; + nodes.set(`${sessionID}:${localID}`, node); + } + + for (const node of nodeChanges) { + if (node.parentIndex) { + const { sessionID, localID } = node.parentIndex.guid; + const parent = nodes.get(`${sessionID}:${localID}`); + if (parent) { + parent.children ||= []; + parent.children.push(node); + } + } + } + + for (const node of nodeChanges) { + if (node.children) { + node.children.sort(orderByPosition); + } + } + + for (const node of nodeChanges) { + delete node.parentIndex; + } + + const root = nodes.get('0:0'); + + return { version, root, blobs, backupNodeList: originalNodeChanges, backupNodeMap: nodeMap }; +} diff --git a/packages/figma/src/file.ts b/packages/figma/src/file.ts new file mode 100644 index 0000000..be5b505 --- /dev/null +++ b/packages/figma/src/file.ts @@ -0,0 +1,10 @@ +import { pickFile } from '@idraw/util'; + +export function pickFigmaFile(opts: { accept?: string; success: (data: { file: File }) => void; error?: (err: Error | any) => void }) { + const { success, error } = opts; + pickFile({ + accept: '*', + success, + error + }); +} diff --git a/packages/figma/src/index.ts b/packages/figma/src/index.ts new file mode 100644 index 0000000..5288303 --- /dev/null +++ b/packages/figma/src/index.ts @@ -0,0 +1,2 @@ +export { pickFigmaFile } from './file'; +export { figmaBytesToMap, figmaMapToIDrawData, figmaBytesToIDrawData } from './figma-object'; diff --git a/packages/figma/src/types/figma.ts b/packages/figma/src/types/figma.ts new file mode 100644 index 0000000..284c338 --- /dev/null +++ b/packages/figma/src/types/figma.ts @@ -0,0 +1,448 @@ +// https://www.figma.com/developers/api#node-types + +export type FigmaNodeType = + | 'DOCUMENT' + | 'CANVAS' + | 'FRAME' + | 'ROUNDED_RECTANGLE' + | 'ELLIPSE' + | 'TEXT' + | 'VECTOR' + | 'REGULAR_POLYGON' + | 'LINE' + | 'STAR' + | 'SYMBOL' + | 'INSTANCE' + | 'BOOLEAN_OPERATION'; + +export type FigmaNode = FigmaNodeTypeMap[T]; + +export type FigmaColor = { + r: number; + g: number; + b: number; + a: number; +}; + +export type FigmaSize = { + x: number; + y: number; +}; + +export type FigmaObject = { + nodeChanges: FigmaNode[]; +}; + +export type FigmaNodeMap = { + [id: string]: FigmaNode; +}; + +export type FigmaNodeTypeMap = { + DOCUMENT: FigmaDocumentNode; + CANVAS: FigmaCanvasNode; + FRAME: FigmaFrameNode; + ROUNDED_RECTANGLE: FigmaRoundedRectangleNode; + ELLIPSE: FigmaRoundedEllipseNode; + TEXT: FigmaTextNode; + VECTOR: FigmaVectorNode; + REGULAR_POLYGON: FigmaRegularPolygonNode; + LINE: FigmaLineNode; + STAR: FigmaStarNode; + SYMBOL: FigmaSymbolNode; + INSTANCE: FigmaInstanceNode; + BOOLEAN_OPERATION: FigmaBooleanOperationNode; +}; + +export type FigmaGUID = { + localID: number; + sessionID: number; +}; + +export type FigmaTransform = { + m00: number; + m01: number; + m02: number; + m10: number; + m11: number; + m12: number; +}; + +export type FigmaNodeBase = { + opacity: number; + name: string; + guid: FigmaGUID; + parentIndex?: { + guid: FigmaGUID; + position?: string; + }; + transform: FigmaTransform; + visible: boolean; + locked: boolean; + size: FigmaSize; + overrideKey?: FigmaGUID; + effects: FigmaEffect[]; + mask?: boolean; + maskType?: string; // "ALPHA" +}; + +export type FigmaEffect = { + blendMode: string; // 'NORMAL' + color: FigmaColor; + offset: { x: number; y: number }; + radius: number; + showShadowBehindNode: true; + spread: number; + type: string; // 'DROP_SHADOW' + visible: boolean; +}; + +export type FigmaPaint = FigmaFillPaint | FigmaStrokePaint; + +export type FigmaFillPaint = FigmaFillPaintSolid | FigmaFillPaintGradientRadial | FigmaFillPaintGradientLinear | FigmaFillPaintImage; + +export type FigmaFillPaintSolid = { + blendMode: string; + opacity: number; + type: 'SOLID'; + visible: boolean; + color: FigmaColor; +}; + +export type FigmaFillPaintGradientRadial = { + blendMode: string; + opacity: number; + type: 'GRADIENT_RADIAL'; + visible: boolean; + transform: FigmaTransform; + stops: Array<{ + color: FigmaColor; + position: number; + }>; + stopsVar: Array<{ + color: FigmaColor; + colorVar: { + dataType: string; // 'COLOR'; + resolvedDataType: string; // 'COLOR'; + position: number; + value: { + colorValue: FigmaColor; + }; + }; + }>; +}; + +export type FigmaFillPaintGradientLinear = { + blendMode: string; + opacity: number; + type: 'GRADIENT_LINEAR'; + visible: boolean; + transform: FigmaTransform; + stops: Array<{ + color: FigmaColor; + position: number; + }>; + stopsVar: Array<{ + color: FigmaColor; + colorVar: { + dataType: string; // 'COLOR'; + resolvedDataType: string; // 'COLOR'; + position: number; + value: { + colorValue: FigmaColor; + }; + }; + }>; +}; + +export type FigmaFillPaintImage = { + blendMode: string; // 'NORMAL'; + opacity: number; + type: 'IMAGE'; + image: { + hash: Uint8Array; + name: string; + }; + imageScaleMode: string; //'FILL'; + imageShouldColorManage: boolean; + imageThumbnail: { + hash: Uint8Array; + name: string; + }; + originalImageHeight: number; + originalImageWidth: number; + rotation: number; + scale: number; + transform: FigmaTransform; + visible: boolean; + color: FigmaColor; +}; + +export type FigmaFillGeometryItem = { + commandsBlob?: Uint8Array; + commands: Array; + styleID: number; + windingRule: string; // 'NONZERO' | 'ODD' +}; + +export type FigmaNodeFillBase = { + fillGeometry: Array; + fillPaints: Array; +}; + +export type FigmaStrokeGeometryItem = { + commandsBlob?: Uint8Array; + commands: Array; + styleID: number; + windingRule: string; // 'NONZERO'; +}; + +export type FigmaStrokePaint = { + blendMode: string; // 'NORMAL'; + opacity: number; + type: string; // 'SOLID'; + visible: boolean; + color: FigmaColor; +}; + +export type FigmaNodeStrokeBase = { + strokeAlign: 'CENTER' | 'OUTSIDE' | 'INSIDE'; + strokeCap: string; // 'NONE'; + strokeGeometry: Array; + strokeJoin: string; // 'MITER'; + strokePaints: Array; + strokeWeight: number; +}; + +export type FigmaNodeCornerBase = { + cornerRadius: number; + rectangleCornerRadiiIndependent: boolean; + rectangleBottomLeftCornerRadius: number; + rectangleBottomRightCornerRadius: number; + rectangleTopLeftCornerRadius: number; + rectangleTopRightCornerRadius: number; +}; + +export type FigmaNodeBoxBorderBase = FigmaNodeStrokeBase & + FigmaNodeCornerBase & { + borderStrokeWeightsIndependent?: boolean; + borderBottomWeight?: number; + borderLeftWeight?: number; + borderRightWeight?: number; + borderTopWeight?: number; + dashPattern: number[]; + }; + +export type FigmaDocumentNode = FigmaNodeBase & { + type: 'DOCUMENT'; + children: FigmaNode[]; +}; + +export type FigmaCanvasNode = FigmaNodeBase & + FigmaNodeFillBase & + FigmaNodeStrokeBase & { + type: 'CANVAS'; + backgroundColor: FigmaColor; + children?: FigmaNode[]; + internalOnly?: boolean; + }; + +export type FigmaBooleanOperationNode = FigmaNodeBase & + FigmaNodeFillBase & + FigmaNodeStrokeBase & { + type: 'BOOLEAN_OPERATION'; + backgroundColor: FigmaColor; + children?: FigmaNode[]; + internalOnly?: boolean; + }; + +export type FigmaSymbolNode = FigmaNodeBase & + FigmaNodeFillBase & + FigmaNodeStrokeBase & { + type: 'SYMBOL'; + backgroundColor: FigmaColor; + children?: FigmaNode[]; + }; + +// TODO +export type FigmaDerivedSymbolDataItem = Partial & { + guidPath: { + guids: Array; + }; +}; + +export type FigmaDerivedSymbolData = Array; + +export type FigmaSymbolOverrideItem = { + overriddenSymbolID?: FigmaGUID; + guidPath: { + guids: Array; + }; +} & Partial>; + +export type FigmaInstanceNode = FigmaNodeBase & + FigmaNodeFillBase & + FigmaNodeStrokeBase & { + type: 'INSTANCE'; + backgroundColor: FigmaColor; + derivedSymbolData: FigmaDerivedSymbolData; + symbolData: { + symbolID: FigmaGUID; + symbolOverrides: Array; + }; + symbolDescription: string; + }; + +export type FigmaFrameNode = FigmaNodeBase & + FigmaNodeFillBase & { + type: 'FRAME'; + children?: FigmaNode[]; + frameMaskDisabled?: boolean; + }; + +export type FigmaRoundedRectangleNode = FigmaNodeBase & + FigmaNodeBoxBorderBase & + FigmaNodeFillBase & { + type: 'ROUNDED_RECTANGLE'; + }; + +export type FigmaRoundedEllipseNode = FigmaNodeBase & + FigmaNodeBoxBorderBase & + FigmaNodeFillBase & { + type: 'ELLIPSE'; + }; + +export type FigmaTextNode = FigmaNodeBase & + FigmaNodeBoxBorderBase & + FigmaNodeFillBase & { + type: 'TEXT'; + textAlignHorizontal: 'LEFT' | 'RIGHT' | 'CENTER' | 'JUSTIFIED'; + textAlignVertical: 'TOP' | 'CENTER' | 'BOTTOM'; + textAutoResize: string; // 'NONE'; + textBidiVersion: number; + textTracking: number; + textUserLayoutVersion: number; + textCase?: 'UPPER' | 'LOWER'; + textData: { + characters: string; + layoutSize: FigmaSize; + fontMetaData: Array<{ + fontDigest: Uint8Array; + fontLineHeight: number; + fontStyle: string; // NORMAL + fontWeight: number; + key: { + family: string; + style: string; + }; + }>; + glyphs: Array<{ + advance: number; + commandsBlob: number; + firstCharacter: number; + fontSize: number; + position: { x: number; y: number }; + }>; + }; + fontName: { + family: string; + postscript: string; + style: string; + }; + fontSize: number; + fontVariantCaps: string; + fontVariantCommonLigatures: boolean; + fontVariantContextualLigatures: boolean; + fontVariantDiscretionaryLigatures: boolean; + fontVariantHistoricalLigatures: boolean; + fontVariantNumericFigure: string; + fontVariantNumericFraction: string; + fontVariantNumericSpacing: string; + fontVariantOrdinal: boolean; + fontVariantPosition: string; + fontVariantSlashedZero: boolean; + fontVariations: any[]; // TODO + fontVersion: string; + lineHeight: { + units: string; + value: number; + }; + }; + +export type FigmaRegularPolygonNode = FigmaNodeBase & + FigmaNodeStrokeBase & + FigmaNodeFillBase & { + type: 'REGULAR_POLYGON'; + }; + +export type FigmaVectorNode = FigmaNodeBase & + FigmaNodeStrokeBase & + FigmaNodeFillBase & { + type: 'VECTOR'; + vectorData: { + normalizedSize: FigmaSize; + styleOverrideTable: Array<{ + handleMirroring: string; // 'ANGLE_AND_LENGTH'; + styleID: number; + }>; + vectorNetwork: { + regions: any[]; // TODO + segments: Array<{ + start: { + dx: number; + dy: number; + vertex: number; + }; + end: { + dx: number; + dy: number; + vertex: number; + }; + styleID: number; + }>; + vertices: Array<{ + styleID: number; + x: number; + y: number; + }>; + }; + }; + }; + +export type FigmaLineNode = FigmaNodeBase & + FigmaNodeStrokeBase & + FigmaNodeFillBase & { + type: 'LINE'; + }; + +export type FigmaStarNode = FigmaNodeBase & + FigmaNodeStrokeBase & + FigmaNodeFillBase & { + type: 'STAR'; + }; + +export interface FigmaCanvasFigObject { + version: number; + root: FigmaNode<'DOCUMENT'>; + blobs: Array<{ + bytes: Uint8Array; + }>; + backupNodeList: FigmaNode[]; + backupNodeMap: Record; +} + +export type FigmaMap = { + [key: string]: Uint8Array; +} & { + 'canvas.fig': FigmaCanvasFigObject; + 'thumbnail.png': Uint8Array; + 'meta.json': any; + 'images/': Uint8Array; +}; + +export type FigmaParseOptions = { + figmaMap: FigmaMap; + backupNodeMap: Record; + instanceNodeMap: Record; + overrideNodeMap?: Record>>; + overrideProperties?: Partial>; +}; diff --git a/packages/figma/src/types/index.ts b/packages/figma/src/types/index.ts new file mode 100644 index 0000000..d325066 --- /dev/null +++ b/packages/figma/src/types/index.ts @@ -0,0 +1 @@ +export * from './figma'; diff --git a/packages/lab/dev/data/components/button.ts b/packages/lab/dev/data/components/button.ts deleted file mode 100644 index 77f0b21..0000000 --- a/packages/lab/dev/data/components/button.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { createUUID } from '@idraw/util'; -import type { ElementSize } from '@idraw/types'; -import type { LabComponent, LabComponentItem } from '../../../src'; - -function createButtonItem(variantName: string, size?: Partial) { - const componentItem: LabComponentItem = { - uuid: createUUID(), - type: 'component-item', - name: `Button ${variantName}`, - x: 50, - y: 50, - w: 100, - h: 100, - ...(size || {}), - detail: { - bgColor: '#ff98001F', - children: [ - { - uuid: createUUID(), - type: 'group', - x: 8, - y: 8, - w: 80, - h: 50, - detail: { - bgColor: '#0382761F', - children: [ - { - uuid: createUUID(), - type: 'rect', - x: 5, - y: 8, - w: 70, - h: 32, - detail: { - bgColor: '#038276', - borderRadius: 4 - } - }, - { - uuid: createUUID(), - type: 'text', - x: 5, - y: 8, - w: 70, - h: 32, - detail: { - color: '#ffffff', - fontSize: 14, - text: 'Button' - } - } - ] - } - } - - // { - // uuid: createUUID(), - // type: 'circle', - // x: -20, - // y: 0, - // w: 100, - // h: 100, - // detail: { - // bgColor: '#ff9800' - // } - // }, - // { - // uuid: createUUID(), - // type: 'circle', - // x: 0, - // y: 0, - // w: 100, - // h: 100, - // detail: { - // bgColor: '#ffc106' - // } - // }, - // { - // uuid: createUUID(), - // type: 'circle', - // x: 20, - // y: 0, - // w: 100, - // h: 100, - // detail: { - // bgColor: '#cddc39' - // } - // }, - // { - // uuid: createUUID(), - // type: 'circle', - // x: 40, - // y: 0, - // w: 100, - // h: 100, - // detail: { - // bgColor: '#4caf50' - // } - // } - ] - } - }; - return componentItem; -} - -export function createButton(name: string, size?: Partial) { - const button: LabComponent = { - uuid: createUUID(), - type: 'component', - name: `Button ${name}`, - x: 50, - y: 50, - w: 360, - h: 200, - detail: { - bgColor: '#aaaaaa54', - default: createButtonItem('default', { angle: 30 }), - variants: [ - // createButtonItem('primary', { x: 200, y: 50, angle: 30 }), - createButtonItem('primary', { x: 200, y: 50 }), - createButtonItem('secondary', { x: 50, y: 180 }) - ] - }, - ...(size || {}) - }; - return button; -} diff --git a/packages/lab/dev/data/components/checkbox.ts b/packages/lab/dev/data/components/checkbox.ts deleted file mode 100644 index 25b7647..0000000 --- a/packages/lab/dev/data/components/checkbox.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { createUUID } from '@idraw/util'; -import type { ElementSize } from '@idraw/types'; -import type { LabComponent, LabComponentItem } from '../../../src'; - -function createCheckboxItem(variantName: string, size?: Partial) { - const componentItem: LabComponentItem = { - uuid: createUUID(), - type: 'component-item', - name: `Checkbox ${variantName}`, - x: 50, - y: 50, - w: 100, - h: 100, - ...(size || {}), - detail: { - children: [ - { - uuid: createUUID(), - type: 'rect', - x: -40, - y: 0, - w: 100, - h: 100, - detail: { - bgColor: '#f44336' - } - }, - { - uuid: createUUID(), - type: 'rect', - x: -20, - y: 0, - w: 100, - h: 100, - detail: { - bgColor: '#ff9800' - } - }, - { - uuid: createUUID(), - type: 'rect', - x: 0, - y: 0, - w: 100, - h: 100, - detail: { - bgColor: '#ffc106' - } - }, - { - uuid: createUUID(), - type: 'rect', - x: 20, - y: 0, - w: 100, - h: 100, - detail: { - bgColor: '#cddc39' - } - }, - { - uuid: createUUID(), - type: 'rect', - x: 40, - y: 0, - w: 100, - h: 100, - detail: { - bgColor: '#4caf50' - } - } - ] - } - }; - return componentItem; -} - -export function createCheckbox(name: string, size?: Partial) { - const checkbox: LabComponent = { - uuid: createUUID(), - type: 'component', - name: `Checkbox ${name}`, - x: 50, - y: 50, - w: 360, - h: 200, - detail: { - bgColor: '#aaaaaa54', - default: createCheckboxItem('default'), - variants: [createCheckboxItem('primary', { x: 200, y: 50 }), createCheckboxItem('secondary', { x: 50, y: 180 })] - }, - ...(size || {}) - }; - return checkbox; -} diff --git a/packages/lab/dev/data/index.ts b/packages/lab/dev/data/index.ts deleted file mode 100644 index f0cbe3a..0000000 --- a/packages/lab/dev/data/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { LabData } from '../../src'; -import { createButton } from './components/button'; -import { createCheckbox } from './components/checkbox'; - -const data: LabData = { - components: [ - createButton('001', { angle: 45 }), - // createButton('001', {}), - createButton('002', { x: 450 }), - createCheckbox('001', { x: 50, y: 300 }), - createCheckbox('002', { x: 450, y: 300 }) - ], - modules: [], - pages: [] -}; - -export default data; diff --git a/packages/lab/dev/images/building-001.png b/packages/lab/dev/images/building-001.png deleted file mode 100644 index 4b87e78..0000000 Binary files a/packages/lab/dev/images/building-001.png and /dev/null differ diff --git a/packages/lab/dev/images/building-002.png b/packages/lab/dev/images/building-002.png deleted file mode 100644 index c0699ff..0000000 Binary files a/packages/lab/dev/images/building-002.png and /dev/null differ diff --git a/packages/lab/dev/images/building-003.png b/packages/lab/dev/images/building-003.png deleted file mode 100644 index 5391f28..0000000 Binary files a/packages/lab/dev/images/building-003.png and /dev/null differ diff --git a/packages/lab/dev/images/chart.png b/packages/lab/dev/images/chart.png deleted file mode 100644 index 67efe1f..0000000 Binary files a/packages/lab/dev/images/chart.png and /dev/null differ diff --git a/packages/lab/dev/images/computer.png b/packages/lab/dev/images/computer.png deleted file mode 100644 index 01fde93..0000000 Binary files a/packages/lab/dev/images/computer.png and /dev/null differ diff --git a/packages/lab/dev/images/github.png b/packages/lab/dev/images/github.png deleted file mode 100644 index 3d64592..0000000 Binary files a/packages/lab/dev/images/github.png and /dev/null differ diff --git a/packages/lab/dev/images/lena.png b/packages/lab/dev/images/lena.png deleted file mode 100644 index 08e54c5..0000000 Binary files a/packages/lab/dev/images/lena.png and /dev/null differ diff --git a/packages/lab/dev/images/phone.png b/packages/lab/dev/images/phone.png deleted file mode 100644 index 4ffec7f..0000000 Binary files a/packages/lab/dev/images/phone.png and /dev/null differ diff --git a/packages/lab/dev/index.html b/packages/lab/dev/index.html deleted file mode 100644 index 31cadb8..0000000 --- a/packages/lab/dev/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - -
- - - \ No newline at end of file diff --git a/packages/lab/dev/main.tsx b/packages/lab/dev/main.tsx deleted file mode 100644 index 34df3e3..0000000 --- a/packages/lab/dev/main.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { createRoot } from 'react-dom/client'; -import { Lab } from '../src/index'; -import data from './data'; - -const dom = document.querySelector('#lab') as HTMLDivElement; -const root = createRoot(dom); - -const App = () => { - const style = { margin: 0, padding: 0 }; - const [width, setWidth] = useState(window.innerWidth); - const [height, setHeight] = useState(window.innerHeight); - useEffect(() => { - window.addEventListener('resize', () => { - setWidth(window.innerWidth); - setHeight(window.innerHeight); - }); - }, []); - - // const style = { margin: 40 }; - // const width = 800; - // const height = 600; - - return ; -}; - -root.render(); diff --git a/packages/lab/package.json b/packages/lab/package.json deleted file mode 100644 index 5646b7c..0000000 --- a/packages/lab/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@idraw/lab", - "version": "0.4.0-beta.25", - "dependencies": { - "@ant-design/icons": "^5.1.3", - "@idraw/core": "workspace:^0.4.0-beta.25", - "@idraw/util": "workspace:^0.4.0-beta.25", - "antd": "^5.5.0", - "classnames": "^2.3.2", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@idraw/types": "workspace:^0.4.0-beta.25", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.1" - } -} \ No newline at end of file diff --git a/packages/lab/src/context.ts b/packages/lab/src/context.ts deleted file mode 100644 index 6799d88..0000000 --- a/packages/lab/src/context.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { createContext } from 'react'; -import type { Data } from '@idraw/types'; -import { LabData, LabState, LabAction, LabContext, LabDrawDataType } from './types'; -import { parseComponentsToDrawData } from './util/view-data'; - -export function createLabData(): LabData { - return { - components: [], - modules: [], - pages: [] - }; -} - -function parseDrawData(drawDataType: LabDrawDataType, labData: LabData | null): Data { - let drawData: Data = { elements: [] }; - if (drawDataType === 'component') { - drawData = parseComponentsToDrawData(labData?.components || []); - } - return drawData; -} - -export function createLabContextState(opts?: Partial): LabState { - const activeDrawDataType: LabDrawDataType = 'component'; - const labData: LabData = opts?.labData || createLabData(); - const viewDrawData = parseDrawData(activeDrawDataType, labData); - - return { - labData: labData, - activeDrawDataType: activeDrawDataType, - themeMode: opts?.themeMode || 'light', - viewDrawData: viewDrawData, - viewDrawUUID: null - }; -} - -export function createLabReducer(state: LabState, action: LabAction): LabState { - switch (action.type) { - case 'updateThemeMode': { - if (!action?.payload?.themeMode) { - return state; - } - return { - ...state, - ...{ - themeMode: action?.payload?.themeMode - } - }; - } - case 'updateLabData': { - if (!action?.payload?.labData) { - return state; - } - return { - ...state, - ...{ - labData: action?.payload?.labData - } - }; - } - case 'switchDrawDataType': { - if (!action?.payload?.activeDrawDataType) { - return state; - } - const newState = { - ...state, - ...{ - activeDrawDataType: action?.payload.activeDrawDataType, - viewDrawData: parseDrawData(action?.payload?.activeDrawDataType, state.labData) - } - }; - return newState; - } - - default: - return state; - } -} - -export const Context = createContext({ - state: createLabContextState(), - dispatch: () => { - return; - } -}); - -export const Provider = Context.Provider; diff --git a/packages/lab/src/css/icons/index.less b/packages/lab/src/css/icons/index.less deleted file mode 100644 index 5b724ff..0000000 --- a/packages/lab/src/css/icons/index.less +++ /dev/null @@ -1,19 +0,0 @@ -@import '../../css/variable.less'; - -@mod-name: ~'@{prefix}-icon'; - -.@{mod-name} { - font-size: 16; - display: inline-flex; - align-items: center; - justify-content: center; - color: inherit; - font-style: normal; - line-height: 0; - text-align: center; - text-transform: none; - - svg { - justify-content: center; - } -} diff --git a/packages/lab/src/css/index.less b/packages/lab/src/css/index.less deleted file mode 100644 index df57789..0000000 --- a/packages/lab/src/css/index.less +++ /dev/null @@ -1,11 +0,0 @@ -@import './theme/dark.less'; -@import './theme/light.less'; - -@import './icons/index.less'; - -@import './modules/header.less'; -@import './modules/dashboard.less'; -@import './modules/sketch.less'; -@import './modules/toolbar.less'; -@import './modules/panel-layer.less'; -@import './modules/split-pane.less'; diff --git a/packages/lab/src/css/index.ts b/packages/lab/src/css/index.ts deleted file mode 100644 index 488dc5d..0000000 --- a/packages/lab/src/css/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { createPrefixName } from './variable'; diff --git a/packages/lab/src/css/modules/_mod.less b/packages/lab/src/css/modules/_mod.less deleted file mode 100644 index feb3119..0000000 --- a/packages/lab/src/css/modules/_mod.less +++ /dev/null @@ -1,7 +0,0 @@ -@import "../variable.less"; - -@mod-xxx: ~'@{prefix}-mod-xxx'; - -.@{mod-xxx} { - border: 1px solid #f0f0f0; -} \ No newline at end of file diff --git a/packages/lab/src/css/modules/dashboard.less b/packages/lab/src/css/modules/dashboard.less deleted file mode 100644 index e67f7bd..0000000 --- a/packages/lab/src/css/modules/dashboard.less +++ /dev/null @@ -1,65 +0,0 @@ -@import '../variable.less'; - -@mod-dashboard: ~'@{prefix}-mod-dashboard'; - -// @mod-dashboard-header-height: 36px; - -.@{mod-dashboard} { - color: ~'var(--@{prefix}-text-color)'; - background: ~'var(--@{prefix}-bg-color)'; - display: flex; - position: relative; - overflow: hidden; - box-shadow: 0 0 0 1px #0000001a, 0px 0px 0.5px #0000002e, 0px 3px 8px #0000001a, 0px 1px 3px #0000001a; - background: ~'var(--@{prefix}-bg-color)'; - - canvas { - // background: ~'var(--@{prefix}-bg-color)'; - background-image: linear-gradient(#aaaaaa30 1px, transparent 0), linear-gradient(90deg, #aaaaaa30 1px, transparent 0), - linear-gradient(#aaaaaa40 1px, transparent 0), linear-gradient(90deg, #aaaaaa40 1px, transparent 0); - background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px; - } - - // .@{mod-dashboard}-toolbar-position { - // position: absolute; - // bottom: 50px; - // left: 50%; - // max-width: 800px; - // min-width: 400px; - // transform: translateX(-50%); - // } - - .@{mod-dashboard}-header { - position: absolute; - top: 0; - left: 0; - right: 0; - box-sizing: border-box; - border-bottom: 1px solid; - border-color: ~'var(--@{prefix}-border-color)'; - // height: @mod-dashboard-header-height; - } - - .@{mod-dashboard}-content { - position: absolute; - // top: @mod-dashboard-header-height; - bottom: 0; - left: 0; - right: 0; - } - .@{mod-dashboard}-left { - border-right: 1px solid; - border-color: ~'var(--@{prefix}-border-color)'; - height: 100%; - } - - .@{mod-dashboard}-right { - border-left: 1px solid; - border-color: ~'var(--@{prefix}-border-color)'; - height: 100%; - } - - .@{mod-dashboard}-center { - display: block; - } -} diff --git a/packages/lab/src/css/modules/header.less b/packages/lab/src/css/modules/header.less deleted file mode 100644 index d8cf840..0000000 --- a/packages/lab/src/css/modules/header.less +++ /dev/null @@ -1,18 +0,0 @@ -@import '../variable.less'; - -@mod-header: ~'@{prefix}-mod-header'; - -.@{mod-header} { - display: flex; - align-items: center; - justify-content: space-between; - height: 100%; - box-sizing: border-box; - padding: 0 20px; - color: ~'var(--@{prefix}-text-color)'; - background: ~'var(--@{prefix}-bg-color)'; - - .@{mod-header}-theme-switch { - display: flex; - } -} diff --git a/packages/lab/src/css/modules/panel-layer.less b/packages/lab/src/css/modules/panel-layer.less deleted file mode 100644 index c270600..0000000 --- a/packages/lab/src/css/modules/panel-layer.less +++ /dev/null @@ -1,61 +0,0 @@ -@import '../variable.less'; - -@mod-panel-layer: ~'@{prefix}-mod-panel-layer'; - -.@{mod-panel-layer} { - height: 100%; - width: 100%; - display: flex; - flex-flow: column; - - .@{mod-panel-layer}-header { - height: 40px; - box-sizing: border-box; - // border-bottom: 1px solid; - // border-color: ~'var(--@{prefix}-border-color)'; - } - - .@{mod-panel-layer}-content { - flex: 1; - // display: flex; - width: 100%; - overflow: auto; - - // fix antd style - .ant-tree-switcher { - display: flex; - justify-content: center; - align-items: center; - } - - .ant-tree-node-content-wrapper { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - } - - .@{mod-panel-layer}-footer { - height: 32px; - box-sizing: border-box; - border-top: 1px solid; - border-color: ~'var(--@{prefix}-border-color)'; - } - - .@{mod-panel-layer}-tabs { - // width: 100%; - // display: flex; - // padding-bottom: 100px; - - .@{mod-panel-layer}-tab-title { - font-size: 16; - margin: 0 4px; - } - .@{mod-panel-layer}-tab-content { - flex: 1; - width: 100%; - height: 100%; - overflow: auto; - } - } -} diff --git a/packages/lab/src/css/modules/sketch.less b/packages/lab/src/css/modules/sketch.less deleted file mode 100644 index e32d6df..0000000 --- a/packages/lab/src/css/modules/sketch.less +++ /dev/null @@ -1,7 +0,0 @@ -@import '../variable.less'; - -@mod-xxx: ~'@{prefix}-mod-sketch'; - -.@{mod-xxx} { - border: 1px solid #f0f0f0; -} diff --git a/packages/lab/src/css/modules/split-pane.less b/packages/lab/src/css/modules/split-pane.less deleted file mode 100644 index d0e90c2..0000000 --- a/packages/lab/src/css/modules/split-pane.less +++ /dev/null @@ -1,55 +0,0 @@ -// @import '../variable.less'; - -@mod-split-pane: ~'@{prefix}-mod-split-pane'; - -.@{mod-split-pane} { - // background: #000; - opacity: 0.2; - z-index: 1; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - -moz-background-clip: padding; - -webkit-background-clip: padding; - background-clip: padding-box; - - &:hover { - -webkit-transition: all 2s ease; - transition: all 2s ease; - } - - &.horizontal { - height: 11px; - margin: -5px 0; - border-top: 5px solid rgba(255, 255, 255, 0); - border-bottom: 5px solid rgba(255, 255, 255, 0); - cursor: row-resize; - width: 100%; - } - - &.horizontal:hover { - border-top: 5px solid rgba(0, 0, 0, 0.5); - border-bottom: 5px solid rgba(0, 0, 0, 0.5); - } - - &.vertical { - width: 11px; - margin: 0 -6px; - border-left: 5px solid rgba(255, 255, 255, 0); - border-right: 5px solid rgba(255, 255, 255, 0); - cursor: col-resize; - } - - &.vertical:hover { - border-left: 5px solid rgba(0, 0, 0, 0.5); - border-right: 5px solid rgba(0, 0, 0, 0.5); - } - - &.disabled { - cursor: not-allowed; - } - - &.disabled:hover { - border-color: transparent; - } -} diff --git a/packages/lab/src/css/modules/toolbar.less b/packages/lab/src/css/modules/toolbar.less deleted file mode 100644 index c00abbe..0000000 --- a/packages/lab/src/css/modules/toolbar.less +++ /dev/null @@ -1,45 +0,0 @@ -@import '../variable.less'; - -@mod-toolbar: ~'@{prefix}-mod-toolbar'; - -.@{mod-toolbar} { - display: flex; - align-items: center; - justify-content: space-between; - flex-direction: row; - padding: 0 12px; - - // height: 50px; - box-sizing: border-box; - // background: ~'var(--@{prefix}-bg-color)'; - // border-radius: 16px; - // box-shadow: 0 0 0 1px #0000001a, 0px 0px 0.5px #0000002e, 0px 3px 8px #0000001a, 0px 1px 3px #0000001a; - // border: 1px solid; - // border-color: ~'var(--@{prefix}-border-color)'; - - .@{mod-toolbar}-left { - display: flex; - } - .@{mod-toolbar}-right { - display: flex; - } - .@{mod-toolbar}-middle { - display: flex; - margin: 0 12px; - .@{mod-toolbar}-mode-switch { - display: flex; - text-align: center; - vertical-align: middle; - align-items: center; - justify-content: center; - } - } - - // hack style for antd - .ant-radio-button-wrapper { - display: flex; - text-align: center; - justify-content: center; - align-items: center; - } -} diff --git a/packages/lab/src/css/theme/dark.less b/packages/lab/src/css/theme/dark.less deleted file mode 100644 index d24c8cf..0000000 --- a/packages/lab/src/css/theme/dark.less +++ /dev/null @@ -1,9 +0,0 @@ -@import '../variable.less'; - -&.@{prefix}-theme { - &.@{prefix}-theme-dark { - --@{prefix}-bg-color: @gray-9; - --@{prefix}-text-color: @gray-1; - --@{prefix}-border-color: @gray-6; - } -} diff --git a/packages/lab/src/css/theme/light.less b/packages/lab/src/css/theme/light.less deleted file mode 100644 index 55ee4ed..0000000 --- a/packages/lab/src/css/theme/light.less +++ /dev/null @@ -1,7 +0,0 @@ -@import '../variable.less'; - -&.@{prefix}-theme { - --@{prefix}-bg-color: @white; - --@{prefix}-text-color: @gray-10; - --@{prefix}-border-color: @gray-4; -} diff --git a/packages/lab/src/css/variable.less b/packages/lab/src/css/variable.less deleted file mode 100644 index 3004932..0000000 --- a/packages/lab/src/css/variable.less +++ /dev/null @@ -1,153 +0,0 @@ -@prefix: idraw-lab; - -@white: #ffffff; -@black: #000000; - -// https://ant.lab/docs/spec/colors-cn -// https://ant.lab/docs/spec/dark-cn -@gray-1: #f5f5f5; -@gray-2: #f0f0f0; -@gray-3: #d9d9d9; -@gray-4: #bfbfbf; -@gray-5: #8c8c8c; -@gray-6: #595959; -@gray-7: #434343; -@gray-8: #262626; -@gray-9: #1f1f1f; -@gray-10: #141414; -@dark-gray-1: #141414; -@dark-gray-2: #1f1f1f; -@dark-gray-3: #262626; -@dark-gray-4: #434343; -@dark-gray-5: #595959; -@dark-gray-6: #8c8c8c; -@dark-gray-7: #bfbfbf; -@dark-gray-8: #d9d9d9; -@dark-gray-9: #f0f0f0; -@dark-gray-10: #f5f5f5; - -@blue-1: #e6f7ff; -@blue-2: #bae7ff; -@blue-3: #91d5ff; -@blue-4: #69c0ff; -@blue-5: #40a9ff; -@blue-6: #1890ff; -@blue-7: #096dd9; -@blue-8: #0050b3; -@blue-9: #003a8c; -@blue-10: #002766; -@dark-blue-1: #111d2c; -@dark-blue-2: #112a45; -@dark-blue-3: #15395b; -@dark-blue-4: #164c7e; -@dark-blue-5: #1765ad; -@dark-blue-6: #177ddc; -@dark-blue-7: #3c9ae8; -@dark-blue-8: #65b7f3; -@dark-blue-9: #8dcff8; -@dark-blue-10: #b7e3fa; - -@red-1: #fff1f0; -@red-2: #ffccc7; -@red-3: #ffa39e; -@red-4: #ff7875; -@red-5: #ff4d4f; -@red-6: #f5222d; -@red-7: #cf1322; -@red-8: #a8071a; -@red-9: #820014; -@red-10: #5c0011; -@dark-red-1: #2a1215; -@dark-red-2: #431418; -@dark-red-3: #58181c; -@dark-red-4: #791a1f; -@dark-red-5: #a61d24; -@dark-red-6: #d32029; -@dark-red-7: #e84749; -@dark-red-8: #f37370; -@dark-red-9: #f89f9a; -@dark-red-10: #fac8c3; - -@yellow-1: #feffe6; -@yellow-2: #ffffb8; -@yellow-3: #fffb8f; -@yellow-4: #fff566; -@yellow-5: #ffec3d; -@yellow-6: #fadb14; -@yellow-7: #d4b106; -@yellow-8: #ad8b00; -@yellow-9: #876800; -@yellow-10: #614700; -@dark-yellow-1: #2b2611; -@dark-yellow-2: #443b11; -@dark-yellow-3: #595014; -@dark-yellow-4: #7c6e14; -@dark-yellow-5: #aa9514; -@dark-yellow-6: #d8bd14; -@dark-yellow-7: #e8d639; -@dark-yellow-8: #f3ea62; -@dark-yellow-9: #f8f48b; -@dark-yellow-10: #fafab5; - -@green-1: #f6ffed; -@green-2: #d9f7be; -@green-3: #b7eb8f; -@green-4: #95de64; -@green-5: #73d13d; -@green-6: #52c41a; -@green-7: #389e0d; -@green-8: #237804; -@green-9: #135200; -@green-10: #092b00; -@dark-green-1: #162312; -@dark-green-2: #1d3712; -@dark-green-3: #274916; -@dark-green-4: #306317; -@dark-green-5: #3c8618; -@dark-green-6: #49aa19; -@dark-green-7: #6abe39; -@dark-green-8: #8fd460; -@dark-green-9: #b2e58b; -@dark-green-10: #d5f2bb; - -@cyan-1: #e6fffb; -@cyan-2: #b5f5ec; -@cyan-3: #87e8de; -@cyan-4: #5cdbd3; -@cyan-5: #36cfc9; -@cyan-6: #13c2c2; -@cyan-7: #08979c; -@cyan-8: #006d75; -@cyan-9: #00474f; -@cyan-10: #002329; -@dark-cyan-1: #112123; -@dark-cyan-2: #113536; -@dark-cyan-3: #144848; -@dark-cyan-4: #146262; -@dark-cyan-5: #138585; -@dark-cyan-6: #13a8a8; -@dark-cyan-7: #33bcb7; -@dark-cyan-8: #58d1c9; -@dark-cyan-9: #84e2d8; -@dark-cyan-10: #b2f1e8; - -@gold-1: #fffbe6; -@gold-2: #fff1b8; -@gold-3: #ffe58f; -@gold-4: #ffd666; -@gold-5: #ffc53d; -@gold-6: #faad14; -@gold-7: #d48806; -@gold-8: #ad6800; -@gold-9: #874d00; -@gold-10: #613400; -@dark-gold-1: #2b2111; -@dark-gold-2: #443111; -@dark-gold-3: #594214; -@dark-gold-4: #7c5914; -@dark-gold-5: #aa7714; -@dark-gold-6: #d89614; -@dark-gold-7: #e8b339; -@dark-gold-8: #f3cc62; -@dark-gold-9: #f8df8b; -@dark-gold-10: #faedb5; diff --git a/packages/lab/src/css/variable.ts b/packages/lab/src/css/variable.ts deleted file mode 100644 index 55ea1d4..0000000 --- a/packages/lab/src/css/variable.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const PREFIX = 'idraw-lab'; - -export function createPrefixName(modName: string) { - return (...args: string[]) => { - return [PREFIX, modName, ...args].join('-'); - }; -} diff --git a/packages/lab/src/data.ts b/packages/lab/src/data.ts deleted file mode 100644 index 05626ed..0000000 --- a/packages/lab/src/data.ts +++ /dev/null @@ -1,521 +0,0 @@ -import type { Data } from '@idraw/types'; -import { deepClone } from '@idraw/util'; - -const data: Data = { - elements: [ - { - uuid: 'xxx-0003', - type: 'image', - x: 100, - y: 100, - w: 100, - h: 100, - angle: 30, - detail: { - src: './images/lena.png' - } - }, - { - uuid: 'xxxx-0001', - x: -50, - y: -40, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#f44336' - } - }, - { - uuid: 'xxx-0002', - type: 'rect', - x: 50, - y: 50, - w: 100, - h: 100, - detail: { - background: '#2196f3' - } - }, - { - uuid: 'xxx-0004', - type: 'image', - x: 250, - y: 250, - w: 100, - h: 100, - detail: { - src: './images/github.png?t=003' - } - }, - { - uuid: 'xxxx-0005', - x: 0, - y: 300, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#009688' - } - }, - { - uuid: 'xxxx-0006', - x: 300, - y: 300, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#673ab7' - } - }, - { - uuid: 'xxxx-0007', - x: 300, - y: 0, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#ffc107' - } - }, - { - uuid: 'xxxx-0008', - x: 150, - y: 150, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#4caf50' - } - }, - { - uuid: 'xxxx-0009', - x: 0, - y: 150, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#ff9800' - } - }, - { - uuid: 'xxxx-0010', - x: 150, - y: 50, - w: 100, - h: 100, - type: 'circle', - detail: { - background: '#cddc39' - } - }, - { - uuid: 'text-0010', - name: 'text-002', - x: 300, - y: 100, - w: 100, - h: 60, - type: 'text', - detail: { - fontSize: 16, - text: [0, 1, 2, 3, 4].map((i) => `Hello Text ${i}`).join('\r\n'), - // text: [0, 1, 2, 3, 4].map(i => `Hello Text ${i}`).join(''), - fontWeight: 'bold', - color: '#666666', - borderRadius: 30, - borderWidth: 2, - borderColor: '#ff5722' - } - }, - { - uuid: 'xxx-0011', - type: 'svg', - x: 400, - y: 100, - w: 100, - h: 100, - detail: { - svg: `` - } - }, - { - uuid: 'xxx-0012', - x: 400, - y: 200, - w: 150, - h: 100, - type: 'html', - angle: 0, - detail: { - html: ` - -
-
- -
-
- -
-
- ` - } - }, - { - uuid: 'group-001', - x: 400, - y: 400, - w: 100, - h: 100, - type: 'group', - detail: { - background: '#1f1f1f', - children: [ - { - uuid: 'group-001-0014', - type: 'circle', - x: -40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#f44336' - } - }, - { - uuid: 'group-001-0015', - type: 'circle', - x: -20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ff9800' - } - }, - { - uuid: 'group-001-0016', - type: 'circle', - x: 0, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ffc106' - } - }, - { - uuid: 'group-001-0017', - type: 'circle', - x: 20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#cddc39' - } - }, - { - uuid: 'group-001-0018', - type: 'circle', - x: 40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#4caf50' - } - } - ] - } - }, - { - uuid: 'group-003', - x: 550, - y: 50, - w: 173.20508075688775, - // w: 100, - h: 100, - angle: 30, - type: 'group', - detail: { - children: [ - { - uuid: 'group-003-014', - type: 'circle', - x: -40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#f44336' - } - }, - { - uuid: 'group-003-0015', - type: 'circle', - x: -20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ff9800' - } - }, - { - uuid: 'group-003-0016', - type: 'circle', - x: 0, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ffc106' - } - }, - { - uuid: 'group-003-0017', - type: 'circle', - x: 20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#cddc39' - } - }, - { - uuid: 'group-003-0018', - type: 'circle', - x: 40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#4caf50' - } - } - ] - } - }, - { - uuid: 'xxxx-0017', - type: 'image', - x: 100, - y: 300, - w: 100, - h: 100, - angle: 30, - detail: { - src: './images/lena.png?v=0017' - } - }, - { - uuid: 'group-004', - x: 550, - y: 250, - w: 375, - h: 400, - type: 'group', - detail: { - background: '#FFFFFF', - children: [ - { - uuid: 'groud-004-001', - type: 'image', - x: 200, - y: 200, - w: 100, - h: 100, - angle: 30, - detail: { - src: './images/lena.png' - } - }, - { - uuid: 'groud-004-002', - type: 'group', - x: 50, - y: 50, - w: 200, - h: 200, - angle: 30, - detail: { - background: '#f0f0f0', - children: [ - { - uuid: 'group-004-002-014', - type: 'circle', - x: -40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#f44336' - } - }, - { - uuid: 'group-004-001-0015', - type: 'circle', - x: -20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ff9800' - } - }, - { - uuid: 'group-004-002-0016', - type: 'circle', - x: 0, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ffc106' - } - }, - { - uuid: 'group-004-002-0017', - type: 'circle', - x: 20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#cddc39' - } - }, - { - uuid: 'group-004-002-0018', - type: 'circle', - x: 40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#4caf50' - } - }, - { - uuid: 'groud-004-002-xxxx', - type: 'group', - x: 50, - y: 100, - w: 200, - h: 100, - angle: 30, - detail: { - background: '#666666', - children: [ - { - uuid: 'group-004-002-xxx-014', - type: 'circle', - x: -40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#f44336' - } - }, - { - uuid: 'group-004-002-xxx-0015', - type: 'circle', - x: -20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ff9800' - } - }, - { - uuid: 'group-004-002-xxx-0016', - type: 'circle', - x: 0, - y: 0, - w: 100, - h: 100, - detail: { - background: '#ffc106' - } - }, - { - uuid: 'group-004-002-xxx-0017', - type: 'circle', - x: 20, - y: 0, - w: 100, - h: 100, - detail: { - background: '#cddc39' - } - }, - { - uuid: 'group-004-002-xxx-0018', - type: 'circle', - x: 40, - y: 0, - w: 100, - h: 100, - detail: { - background: '#4caf50' - } - } - ] - } - } - ] - } - } - ] - } - } - ] -}; - -export function getData() { - return deepClone(data); -} diff --git a/packages/lab/src/icons/dark.tsx b/packages/lab/src/icons/dark.tsx deleted file mode 100644 index b1a35f9..0000000 --- a/packages/lab/src/icons/dark.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Dark = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - ); -}; - -export default Dark; diff --git a/packages/lab/src/icons/hand.tsx b/packages/lab/src/icons/hand.tsx deleted file mode 100644 index 65b1a41..0000000 --- a/packages/lab/src/icons/hand.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Hand = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - ); -}; - -export default Hand; diff --git a/packages/lab/src/icons/layer.tsx b/packages/lab/src/icons/layer.tsx deleted file mode 100644 index 1ce89eb..0000000 --- a/packages/lab/src/icons/layer.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Layer = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - ); -}; - -export default Layer; diff --git a/packages/lab/src/icons/light.tsx b/packages/lab/src/icons/light.tsx deleted file mode 100644 index 07cbe80..0000000 --- a/packages/lab/src/icons/light.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Light = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - ); -}; - -export default Light; diff --git a/packages/lab/src/icons/more.tsx b/packages/lab/src/icons/more.tsx deleted file mode 100644 index 96625c6..0000000 --- a/packages/lab/src/icons/more.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const More = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - - - - ); -}; - -export default More; diff --git a/packages/lab/src/icons/mouse.tsx b/packages/lab/src/icons/mouse.tsx deleted file mode 100644 index 02013bc..0000000 --- a/packages/lab/src/icons/mouse.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Mouse = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - ); -}; - -export default Mouse; diff --git a/packages/lab/src/icons/pen.tsx b/packages/lab/src/icons/pen.tsx deleted file mode 100644 index abcb3ef..0000000 --- a/packages/lab/src/icons/pen.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Pen = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - - - - ); -}; - -export default Pen; diff --git a/packages/lab/src/icons/scale.tsx b/packages/lab/src/icons/scale.tsx deleted file mode 100644 index 6c327d9..0000000 --- a/packages/lab/src/icons/scale.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Mouse = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - - ); -}; - -export default Mouse; diff --git a/packages/lab/src/icons/setting.tsx b/packages/lab/src/icons/setting.tsx deleted file mode 100644 index 1cf571a..0000000 --- a/packages/lab/src/icons/setting.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { iconClassName } from './util'; -import type { IconProps } from './util'; - -const Setting = (props: IconProps) => { - const { className, style } = props; - return ( - - - - - - - - - ); -}; - -export default Setting; diff --git a/packages/lab/src/icons/util/index.ts b/packages/lab/src/icons/util/index.ts deleted file mode 100644 index 3c24742..0000000 --- a/packages/lab/src/icons/util/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { CSSProperties } from 'react'; -import { createPrefixName } from '../../css'; - -const modName = 'icon'; - -const prefixName = createPrefixName(modName); - -export const iconClassName = prefixName(); - -export interface IconProps { - className?: string; - style?: CSSProperties; -} diff --git a/packages/lab/src/index.tsx b/packages/lab/src/index.tsx deleted file mode 100644 index 7144197..0000000 --- a/packages/lab/src/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useEffect, useReducer } from 'react'; -import ConfigProvider from 'antd/es/config-provider'; -import theme from 'antd/es/theme'; -import classnames from 'classnames'; -import { Dashboard } from './modules'; -import { createPrefixName } from './css'; -import { Provider, createLabContextState, createLabReducer } from './context'; -import type { LabData } from './types'; -import type { DashboardProps } from './modules'; -import './css/index.less'; - -const themeName = 'theme'; -const themePrefixName = createPrefixName(themeName); - -export type LabProps = DashboardProps & { - labData?: LabData; - locale?: string; // TODO - themeMode?: 'light' | 'dark'; -}; - -export const Lab = (props: LabProps) => { - const { width = 1000, height = 600, style, className, labData, themeMode } = props; - - const [state, dispatch] = useReducer(createLabReducer, createLabContextState({ labData, themeMode })); - - useEffect(() => { - if (labData) { - dispatch({ - type: 'updateLabData', - payload: { labData } - }); - } - }, [labData]); - - return ( - - - - - - ); -}; - -export * from './types'; diff --git a/packages/lab/src/modules/_mod/index.tsx b/packages/lab/src/modules/_mod/index.tsx deleted file mode 100644 index 3062a8f..0000000 --- a/packages/lab/src/modules/_mod/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import type { CSSProperties } from 'react'; -import classnames from 'classnames'; -import { createPrefixName } from '../../css'; - -const modName = 'mod-xxx'; - -const prefixName = createPrefixName(modName); - -export interface ModProps { - className?: string; - style?: CSSProperties; -} - -export const Mod = (props: ModProps) => { - const { className, style } = props; - return ( -
- Mod -
- ); -}; diff --git a/packages/lab/src/modules/dashboard/index.tsx b/packages/lab/src/modules/dashboard/index.tsx deleted file mode 100644 index 5c59641..0000000 --- a/packages/lab/src/modules/dashboard/index.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import classnames from 'classnames'; -import { Toolbar } from '../toolbar'; -import { PanelLayer } from '../panel-layer'; -import { Header } from '../header'; -import { Sketch } from '../sketch'; -import type { CSSProperties } from 'react'; -import { createPrefixName } from '../../css'; -import SplitPane from '../split-pane'; - -const modName = 'mod-dashboard'; -const leftSiderDefaultWidth = 240; -const rightSiderDefaultWidth = 200; -const headerHeight = 36; - -const prefixName = createPrefixName(modName); - -export interface DashboardProps { - className?: string; - style?: CSSProperties; - width: number; - height: number; -} - -export const Dashboard = (props: DashboardProps) => { - const { className, style, width, height } = props; - - const [openLeftSider, setOpenLeftSider] = useState(true); - const [openRightSider, setOpenRightSider] = useState(false); - - const [leftWidth, setLeftWidth] = useState(openLeftSider ? leftSiderDefaultWidth : 0); - const [rightWidth, setRightWidth] = useState(openRightSider ? rightSiderDefaultWidth : 0); - const [centerWidth, setCenterWidth] = useState(width - leftWidth - rightWidth); - - useEffect(() => { - const prevWidth = leftWidth + centerWidth + rightWidth; - let newLeftWidth = Math.floor(width * (leftWidth / prevWidth)); - let newRightWidth = Math.floor(width * (rightWidth / prevWidth)); - - newLeftWidth = Math.min(newLeftWidth, leftSiderDefaultWidth); - newRightWidth = Math.min(newRightWidth, rightSiderDefaultWidth); - - const newCenterWidth = width - newLeftWidth - newRightWidth; - setLeftWidth(newLeftWidth); - setRightWidth(newRightWidth); - setCenterWidth(newCenterWidth); - }, [height, width]); - - return ( -
-
-
{ - const open = openLeftSider ? false : true; - - let newLeftWidth = leftWidth; - if (open) { - newLeftWidth = leftSiderDefaultWidth; - } else { - newLeftWidth = 0; - } - setLeftWidth(newLeftWidth); - setCenterWidth(width - newLeftWidth - rightWidth); - setRightWidth(rightWidth); - setOpenLeftSider(open); - }} - onClickToggleSetting={() => { - const open = openRightSider ? false : true; - let newRightWidth = rightWidth; - if (open) { - newRightWidth = rightSiderDefaultWidth; - } else { - newRightWidth = 0; - } - setLeftWidth(leftWidth); - setCenterWidth(width - leftWidth - newRightWidth); - setRightWidth(newRightWidth); - setOpenRightSider(open); - }} - /> -
-
- { - setCenterWidth(px - rightWidth); - setLeftWidth(width - px); - }} - pane1Style={{ - width: leftWidth - }} - pane2Style={{ - width: centerWidth + rightWidth - }} - > -
{openLeftSider && }
-
- -
- Right -
-
-
-
- {/* { - const open = openLeftSider ? false : true; - - let newLeftWidth = leftWidth; - if (open) { - newLeftWidth = leftSiderDefaultWidth; - } else { - newLeftWidth = 0; - } - setLeftWidth(newLeftWidth); - setCenterWidth(width - newLeftWidth - rightWidth); - setRightWidth(rightWidth); - setOpenLeftSider(open); - }} - onClickToggleSetting={() => { - const open = openRightSider ? false : true; - let newRightWidth = rightWidth; - if (open) { - newRightWidth = rightSiderDefaultWidth; - } else { - newRightWidth = 0; - } - setLeftWidth(leftWidth); - setCenterWidth(width - leftWidth - newRightWidth); - setRightWidth(newRightWidth); - setOpenRightSider(open); - }} - /> */} -
- ); -}; diff --git a/packages/lab/src/modules/header/index.tsx b/packages/lab/src/modules/header/index.tsx deleted file mode 100644 index 3ce3c7a..0000000 --- a/packages/lab/src/modules/header/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { useContext } from 'react'; -import type { CSSProperties } from 'react'; -import classnames from 'classnames'; -import Switch from 'antd/es/switch'; -import { createPrefixName } from '../../css'; -import IconDark from '../../icons/dark'; -import IconLight from '../../icons/light'; -import { Context } from '../../context'; -import { Toolbar } from '../toolbar'; -import type { ToolbarProps } from '../toolbar'; - -const modName = 'mod-header'; - -const prefixName = createPrefixName(modName); - -export interface ModProps extends ToolbarProps { - className?: string; - style?: CSSProperties; -} - -export const Header = (props: ModProps) => { - const { className, style, openLeftSider, openRightSider, onClickToggleLayer, onClickToggleSetting } = props; - const { state, dispatch } = useContext(Context); - - return ( -
- @idraw/lab - - } - unCheckedChildren={} - checked={state?.themeMode === 'light'} - onChange={(checked: boolean) => { - dispatch?.({ - type: 'updateThemeMode', - payload: { - themeMode: checked ? 'light' : 'dark' - } - }); - }} - /> -
- ); -}; diff --git a/packages/lab/src/modules/index.tsx b/packages/lab/src/modules/index.tsx deleted file mode 100644 index 5ae7903..0000000 --- a/packages/lab/src/modules/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export { Toolbar } from './toolbar/index'; -export type { ToolbarProps } from './toolbar/index'; - -export { Dashboard } from './dashboard/index'; -export type { DashboardProps } from './dashboard/index'; diff --git a/packages/lab/src/modules/panel-layer/config.ts b/packages/lab/src/modules/panel-layer/config.ts deleted file mode 100644 index 71684e2..0000000 --- a/packages/lab/src/modules/panel-layer/config.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createPrefixName } from '../../css'; - -const modName = 'mod-panel-layer'; -export const prefixName = createPrefixName(modName); diff --git a/packages/lab/src/modules/panel-layer/index.tsx b/packages/lab/src/modules/panel-layer/index.tsx deleted file mode 100644 index 0146aa8..0000000 --- a/packages/lab/src/modules/panel-layer/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { useContext } from 'react'; -import type { CSSProperties } from 'react'; -import classnames from 'classnames'; -import Tabs from 'antd/es/tabs'; -import type { TabsProps } from 'antd'; -import FileOutlined from '@ant-design/icons/FileOutlined'; -import AppstoreOutlined from '@ant-design/icons/AppstoreOutlined'; -import CalculatorOutlined from '@ant-design/icons/CalculatorOutlined'; -import { prefixName } from './config'; -import { LayerTree } from './layer-tree'; -import { Context } from '../../context'; -import { LabDrawDataType } from '../../types'; - -const items: TabsProps['items'] = [ - { - key: 'page', - label: - }, - { - key: 'module', - label: - }, - { - key: 'component', - label: - } -]; - -export interface PanelLayerProps { - className?: string; - style?: CSSProperties; -} - -export const PanelLayer = (props: PanelLayerProps) => { - const { className, style } = props; - const { state, dispatch } = useContext(Context); - - return ( -
-
- { - dispatch({ type: 'switchDrawDataType', payload: { activeDrawDataType: activeKey as LabDrawDataType } }); - }} - /> -
-
- -
-
footer
-
- ); -}; diff --git a/packages/lab/src/modules/panel-layer/layer-tree.tsx b/packages/lab/src/modules/panel-layer/layer-tree.tsx deleted file mode 100644 index 0ab49fc..0000000 --- a/packages/lab/src/modules/panel-layer/layer-tree.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { useEffect, useContext } from 'react'; -import classnames from 'classnames'; -import Tree from 'antd/es/tree'; -import DownOutlined from '@ant-design/icons/DownOutlined'; -import { prefixName } from './config'; -import { Context } from '../../context'; -import { parseComponentViewTree } from '../../util/component'; - -import type { CSSProperties } from 'react'; -import type { DataNode, TreeProps } from 'antd/es/tree'; -import type { LabDrawDataType } from '../../types'; - -const { DirectoryTree } = Tree; -const baseName = 'layer-tree'; - -export interface LayerTreeProps { - className?: string; - style?: CSSProperties; - type: LabDrawDataType; -} - -export const LayerTree = (props: LayerTreeProps) => { - const { className, style, type } = props; - const { state } = useContext(Context); - - const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => { - // TODO - console.log('selected', selectedKeys, info); - }; - - let treeData: DataNode[] = []; - if (type === 'component') { - treeData = parseComponentViewTree(state?.labData || null); - } - - return ( -
- } icon={null} onSelect={onSelect} treeData={treeData} /> -
- ); -}; diff --git a/packages/lab/src/modules/sketch/index.tsx b/packages/lab/src/modules/sketch/index.tsx deleted file mode 100644 index b3d515b..0000000 --- a/packages/lab/src/modules/sketch/index.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React, { useEffect, useRef, useContext } from 'react'; -import classnames from 'classnames'; -import { Core, MiddlewareScroller, MiddlewareSelector, MiddlewareScaler } from '@idraw/core'; -import { calcElementsContextSize } from '@idraw/util'; -import { createPrefixName } from '../../css'; -import { Context } from '../../context'; -import type { CSSProperties } from 'react'; - -const modName = 'mod-sketch'; - -const prefixName = createPrefixName(modName); - -export interface DashboardProps { - className?: string; - style?: CSSProperties; - width: number; - height: number; -} - -export const Sketch = (props: DashboardProps) => { - const ref = useRef(null); - const refCore = useRef(null); - const { className, style, width, height } = props; - const devicePixelRatio = window.devicePixelRatio; - - const { state } = useContext(Context); - - useEffect(() => { - if (ref?.current) { - if (!refCore?.current) { - const options = { - width, - height, - devicePixelRatio - }; - const core = new Core(ref.current, options); - core.use(MiddlewareScroller); - core.use(MiddlewareSelector); - core.use(MiddlewareScaler); - refCore.current = core; - } - } - }, []); - - useEffect(() => { - if (!refCore?.current || !state.viewDrawData) { - return; - } - const core = refCore.current; - const contextSize = calcElementsContextSize(state.viewDrawData.elements, { viewWidth: width, viewHeight: height, extend: true }); - core.resize({ - width, - height, - devicePixelRatio, - ...contextSize - }); - core.setData(state.viewDrawData); - }, [state.viewDrawData, height, width]); - - return
; -}; diff --git a/packages/lab/src/modules/split-pane/index.tsx b/packages/lab/src/modules/split-pane/index.tsx deleted file mode 100644 index 0298c51..0000000 --- a/packages/lab/src/modules/split-pane/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -// Thanks to: https://github.com/tomkp/react-split-pane/blob/master/src/index.js -import SplitPane from './split-pane'; -import Pane from './pane'; - -export default SplitPane; -export { Pane }; diff --git a/packages/lab/src/modules/split-pane/pane.tsx b/packages/lab/src/modules/split-pane/pane.tsx deleted file mode 100644 index 424aef6..0000000 --- a/packages/lab/src/modules/split-pane/pane.tsx +++ /dev/null @@ -1,49 +0,0 @@ -// Thanks to: https://github.com/tomkp/react-split-pane/blob/master/src/Pane.js -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import React from 'react'; - -class Pane extends React.PureComponent { - render() { - const { children, className, split, style: styleProps, size, eleRef } = this.props; - - const classes = ['Pane', split, className]; - - let style = { - flex: 1, - position: 'relative', - outline: 'none' - }; - - if (size !== undefined) { - if (split === 'vertical') { - style.width = size; - } else { - style.height = size; - style.display = 'flex'; - } - style.flex = 'none'; - } - - style = Object.assign({}, style, styleProps || {}); - - return ( -
- {children} -
- ); - } -} - -// Pane.propTypes = { -// className: PropTypes.string.isRequired, -// children: PropTypes.node.isRequired, -// size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// split: PropTypes.oneOf(['vertical', 'horizontal']), -// style: stylePropType, -// eleRef: PropTypes.func, -// }; - -// Pane.defaultProps = {}; - -export default Pane; diff --git a/packages/lab/src/modules/split-pane/resizer.tsx b/packages/lab/src/modules/split-pane/resizer.tsx deleted file mode 100644 index 8f70b6f..0000000 --- a/packages/lab/src/modules/split-pane/resizer.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// Thanks to: https://github.com/tomkp/react-split-pane/blob/master/src/Resizer.js -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import React from 'react'; -import { createPrefixName } from '../../css'; - -const modName = 'mod-split-pane'; - -const prefixName = createPrefixName(modName); - -export const RESIZER_DEFAULT_CLASSNAME = prefixName(); - -class Resizer extends React.Component { - render() { - const { className, onClick, onDoubleClick, onMouseDown, onTouchEnd, onTouchStart, resizerClassName = RESIZER_DEFAULT_CLASSNAME, split, style } = this.props; - const classes = [resizerClassName, split, className]; - - return ( - onMouseDown(event)} - onTouchStart={(event) => { - event.preventDefault(); - onTouchStart(event); - }} - onTouchEnd={(event) => { - event.preventDefault(); - onTouchEnd(event); - }} - onClick={(event) => { - if (onClick) { - event.preventDefault(); - onClick(event); - } - }} - onDoubleClick={(event) => { - if (onDoubleClick) { - event.preventDefault(); - onDoubleClick(event); - } - }} - /> - ); - } -} - -// Resizer.propTypes = { -// className: PropTypes.string.isRequired, -// onClick: PropTypes.func, -// onDoubleClick: PropTypes.func, -// onMouseDown: PropTypes.func.isRequired, -// onTouchStart: PropTypes.func.isRequired, -// onTouchEnd: PropTypes.func.isRequired, -// split: PropTypes.oneOf(['vertical', 'horizontal']), -// style: stylePropType, -// resizerClassName: PropTypes.string.isRequired, -// }; -// Resizer.defaultProps = { -// resizerClassName: RESIZER_DEFAULT_CLASSNAME, -// }; - -export default Resizer; diff --git a/packages/lab/src/modules/split-pane/split-pane.tsx b/packages/lab/src/modules/split-pane/split-pane.tsx deleted file mode 100644 index a141d4b..0000000 --- a/packages/lab/src/modules/split-pane/split-pane.tsx +++ /dev/null @@ -1,374 +0,0 @@ -// Thanks to: https://github.com/tomkp/react-split-pane/blob/master/src/SplitPane.js -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import React from 'react'; -// import PropTypes from 'prop-types'; -// import stylePropType from 'react-style-proptype'; -// import { polyfill } from 'react-lifecycles-compat'; - -import Pane from './pane'; -import Resizer, { RESIZER_DEFAULT_CLASSNAME } from './resizer'; - -function unFocus(document, window) { - if (document.selection) { - document.selection.empty(); - } else { - try { - window.getSelection().removeAllRanges(); - // eslint-disable-next-line no-empty - } catch (e) {} - } -} - -function getDefaultSize(defaultSize, minSize, maxSize, draggedSize) { - if (typeof draggedSize === 'number') { - const min = typeof minSize === 'number' ? minSize : 0; - const max = typeof maxSize === 'number' && maxSize >= 0 ? maxSize : Infinity; - return Math.max(min, Math.min(max, draggedSize)); - } - if (defaultSize !== undefined) { - return defaultSize; - } - return minSize; -} - -function removeNullChildren(children) { - return React.Children.toArray(children).filter((c) => c); -} -class SplitPane extends React.Component { - constructor(props) { - super(props); - - this.onMouseDown = this.onMouseDown.bind(this); - this.onTouchStart = this.onTouchStart.bind(this); - this.onMouseMove = this.onMouseMove.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - // order of setting panel sizes. - // 1. size - // 2. getDefaultSize(defaultSize, minsize, maxSize) - - const { size, defaultSize, minSize, maxSize, primary } = props; - - const initialSize = size !== undefined ? size : getDefaultSize(defaultSize, minSize, maxSize, null); - - this.state = { - active: false, - resized: false, - pane1Size: primary === 'first' ? initialSize : undefined, - pane2Size: primary === 'second' ? initialSize : undefined, - - // these are props that are needed in static functions. ie: gDSFP - instanceProps: { - size - } - }; - } - - componentDidMount() { - document.addEventListener('mouseup', this.onMouseUp); - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('touchmove', this.onTouchMove); - this.setState(SplitPane.getSizeUpdate(this.props, this.state)); - } - - static getDerivedStateFromProps(nextProps, prevState) { - return SplitPane.getSizeUpdate(nextProps, prevState); - } - - componentWillUnmount() { - document.removeEventListener('mouseup', this.onMouseUp); - document.removeEventListener('mousemove', this.onMouseMove); - document.removeEventListener('touchmove', this.onTouchMove); - } - - onMouseDown(event) { - const eventWithTouches = Object.assign({}, event, { - touches: [{ clientX: event.clientX, clientY: event.clientY }] - }); - this.onTouchStart(eventWithTouches); - } - - onTouchStart(event) { - const { allowResize, onDragStarted, split } = this.props; - if (allowResize) { - unFocus(document, window); - const position = split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; - - if (typeof onDragStarted === 'function') { - onDragStarted(); - } - this.setState({ - active: true, - position - }); - } - } - - onMouseMove(event) { - const eventWithTouches = Object.assign({}, event, { - touches: [{ clientX: event.clientX, clientY: event.clientY }] - }); - this.onTouchMove(eventWithTouches); - } - - onTouchMove(event) { - const { allowResize, maxSize, minSize, onChange, split, step } = this.props; - const { active, position } = this.state; - - if (allowResize && active) { - unFocus(document, window); - const isPrimaryFirst = this.props.primary === 'first'; - const ref = isPrimaryFirst ? this.pane1 : this.pane2; - const ref2 = isPrimaryFirst ? this.pane2 : this.pane1; - if (ref) { - const node = ref; - const node2 = ref2; - - if (node.getBoundingClientRect) { - const width = node.getBoundingClientRect().width; - const height = node.getBoundingClientRect().height; - const current = split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; - const size = split === 'vertical' ? width : height; - let positionDelta = position - current; - if (step) { - if (Math.abs(positionDelta) < step) { - return; - } - // Integer division - // eslint-disable-next-line no-bitwise - positionDelta = ~~(positionDelta / step) * step; - } - let sizeDelta = isPrimaryFirst ? positionDelta : -positionDelta; - - const pane1Order = parseInt(window.getComputedStyle(node).order); - const pane2Order = parseInt(window.getComputedStyle(node2).order); - if (pane1Order > pane2Order) { - sizeDelta = -sizeDelta; - } - - let newMaxSize = maxSize; - if (maxSize !== undefined && maxSize <= 0) { - const splitPane = this.splitPane; - if (split === 'vertical') { - newMaxSize = splitPane.getBoundingClientRect().width + maxSize; - } else { - newMaxSize = splitPane.getBoundingClientRect().height + maxSize; - } - } - - let newSize = size - sizeDelta; - const newPosition = position - positionDelta; - - if (newSize < minSize) { - newSize = minSize; - } else if (maxSize !== undefined && newSize > newMaxSize) { - newSize = newMaxSize; - } else { - this.setState({ - position: newPosition, - resized: true - }); - } - - if (onChange) onChange(newSize); - - this.setState({ - draggedSize: newSize, - [isPrimaryFirst ? 'pane1Size' : 'pane2Size']: newSize - }); - } - } - } - } - - onMouseUp() { - const { allowResize, onDragFinished } = this.props; - const { active, draggedSize } = this.state; - if (allowResize && active) { - if (typeof onDragFinished === 'function') { - onDragFinished(draggedSize); - } - this.setState({ active: false }); - } - } - - // we have to check values since gDSFP is called on every render and more in StrictMode - static getSizeUpdate(props, state) { - const newState = {}; - const { instanceProps } = state; - - if (instanceProps.size === props.size && props.size !== undefined) { - return {}; - } - - const newSize = props.size !== undefined ? props.size : getDefaultSize(props.defaultSize, props.minSize, props.maxSize, state.draggedSize); - - if (props.size !== undefined) { - newState.draggedSize = newSize; - } - - const isPanel1Primary = props.primary === 'first'; - - newState[isPanel1Primary ? 'pane1Size' : 'pane2Size'] = newSize; - newState[isPanel1Primary ? 'pane2Size' : 'pane1Size'] = undefined; - - newState.instanceProps = { size: props.size }; - - return newState; - } - - render() { - const { - allowResize, - children, - className, - onResizerClick, - onResizerDoubleClick, - paneClassName, - pane1ClassName, - pane2ClassName, - paneStyle, - pane1Style: pane1StyleProps, - pane2Style: pane2StyleProps, - resizerClassName, - resizerStyle, - split, - style: styleProps - } = this.props; - - const { pane1Size, pane2Size } = this.state; - - const disabledClass = allowResize ? '' : 'disabled'; - const resizerClassNamesIncludingDefault = resizerClassName ? `${resizerClassName} ${RESIZER_DEFAULT_CLASSNAME}` : resizerClassName; - - const notNullChildren = removeNullChildren(children); - - const style = { - display: 'flex', - flex: 1, - height: '100%', - position: 'absolute', - outline: 'none', - overflow: 'hidden', - MozUserSelect: 'text', - WebkitUserSelect: 'text', - msUserSelect: 'text', - userSelect: 'text', - ...styleProps - }; - - if (split === 'vertical') { - Object.assign(style, { - flexDirection: 'row', - left: 0, - right: 0 - }); - } else { - Object.assign(style, { - bottom: 0, - flexDirection: 'column', - minHeight: '100%', - top: 0, - width: '100%' - }); - } - - const classes = ['SplitPane', className, split, disabledClass]; - - const pane1Style = { ...paneStyle, ...pane1StyleProps }; - const pane2Style = { ...paneStyle, ...pane2StyleProps }; - - const pane1Classes = ['Pane1', paneClassName, pane1ClassName].join(' '); - const pane2Classes = ['Pane2', paneClassName, pane2ClassName].join(' '); - - return ( -
{ - this.splitPane = node; - }} - style={style} - > - { - this.pane1 = node; - }} - size={pane1Size} - split={split} - style={pane1Style} - > - {notNullChildren[0]} - - - { - this.pane2 = node; - }} - size={pane2Size} - split={split} - style={pane2Style} - > - {notNullChildren[1]} - -
- ); - } -} - -// SplitPane.propTypes = { -// allowResize: PropTypes.bool, -// children: PropTypes.arrayOf(PropTypes.node).isRequired, -// className: PropTypes.string, -// primary: PropTypes.oneOf(['first', 'second']), -// minSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// maxSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// defaultSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// split: PropTypes.oneOf(['vertical', 'horizontal']), -// onDragStarted: PropTypes.func, -// onDragFinished: PropTypes.func, -// onChange: PropTypes.func, -// onResizerClick: PropTypes.func, -// onResizerDoubleClick: PropTypes.func, -// style: stylePropType, -// resizerStyle: stylePropType, -// paneClassName: PropTypes.string, -// pane1ClassName: PropTypes.string, -// pane2ClassName: PropTypes.string, -// paneStyle: stylePropType, -// pane1Style: stylePropType, -// pane2Style: stylePropType, -// resizerClassName: PropTypes.string, -// step: PropTypes.number -// }; - -// SplitPane.defaultProps = { -// allowResize: true, -// minSize: 50, -// primary: 'first', -// split: 'vertical', -// paneClassName: '', -// pane1ClassName: '', -// pane2ClassName: '' -// }; - -// polyfill(SplitPane); - -export default SplitPane; diff --git a/packages/lab/src/modules/toolbar/index.tsx b/packages/lab/src/modules/toolbar/index.tsx deleted file mode 100644 index 97ef2ac..0000000 --- a/packages/lab/src/modules/toolbar/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { useState } from 'react'; -import type { CSSProperties } from 'react'; -import classnames from 'classnames'; -import Radio from 'antd/es/radio'; -import Button from 'antd/es/button'; -import { createPrefixName } from '../../css'; -import IconMouse from '../../icons/mouse'; -import IconPen from '../../icons/pen'; -import IconHand from '../../icons/hand'; -import IconScale from '../../icons/scale'; -import IconLayer from '../../icons/layer'; -import IconSetting from '../../icons/setting'; -import IconMore from '../../icons/more'; - -const RadioButton = Radio.Button; -const RadioGroup = Radio.Group; -const modName = 'mod-toolbar'; - -const prefixName = createPrefixName(modName); - -export interface ToolbarProps { - className?: string; - style?: CSSProperties; - openLeftSider: boolean; - openRightSider: boolean; - onClickToggleLayer?: () => void; - onClickToggleSetting?: () => void; -} - -export const Toolbar = (props: ToolbarProps) => { - const { className, style, openLeftSider, openRightSider, onClickToggleLayer, onClickToggleSetting } = props; - const [mode, setMode] = useState('select'); - const iconStyle = { fontSize: 20 }; - - return ( -
-
-
- setMode(e.target.value)}> - - - - - - - - - - - - - - - - -
-
-
- ); -}; diff --git a/packages/lab/src/types/context.ts b/packages/lab/src/types/context.ts deleted file mode 100644 index a6c09d3..0000000 --- a/packages/lab/src/types/context.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Dispatch } from 'react'; -import type { Data } from '@idraw/types'; -import { LabData, LabDrawDataType } from './data'; - -export interface LabState { - activeDrawDataType: LabDrawDataType; - labData: LabData; - viewDrawData: Data; - viewDrawUUID: string | null; - themeMode: 'light' | 'dark'; -} - -export type LabActionType = 'updateThemeMode' | 'updateLabData' | 'switchDrawDataType'; - -export type LabAction = { - type: LabActionType; - payload: Partial; -}; - -export type LabDispatch = Dispatch; - -export interface LabContext { - state: LabState; - dispatch: LabDispatch; -} diff --git a/packages/lab/src/types/data.ts b/packages/lab/src/types/data.ts deleted file mode 100644 index e8f48aa..0000000 --- a/packages/lab/src/types/data.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { Element, ElementType, ElementSize, ElementBaseDesc } from '@idraw/types'; - -export type LabItemType = 'component' | 'component-item' | 'module' | 'page'; - -export type LabDrawDataType = 'component' | 'module' | 'page'; - -export type LabComponentItem = ElementSize & { - uuid: string; - type: 'component-item'; - name: string; - detail?: ElementBaseDesc & { - children: Array | LabComponentItem>; - }; -}; - -export type LabComponent = ElementSize & { - uuid: string; - type: 'component'; - name: string; - detail?: ElementBaseDesc & { - default: LabComponentItem; - variants: LabComponentItem[]; - }; -}; - -export type LabModule = ElementSize & { - uuid: string; - type: 'module'; - name: string; - detail?: ElementBaseDesc & { - children: Array; - }; -}; - -export type LabPage = ElementSize & { - uuid: string; - type: 'page'; - name: string; - detail: ElementBaseDesc & { - children: Array; - }; -}; - -export interface LabData { - components: LabComponent[]; - modules: LabModule[]; - pages: LabPage[]; -} diff --git a/packages/lab/src/types/index.ts b/packages/lab/src/types/index.ts deleted file mode 100644 index 11a2f1e..0000000 --- a/packages/lab/src/types/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './data'; -export * from './context'; -export * from './view'; diff --git a/packages/lab/src/types/view.ts b/packages/lab/src/types/view.ts deleted file mode 100644 index ecb5cf2..0000000 --- a/packages/lab/src/types/view.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ElementType } from '@idraw/types'; -import type { LabItemType } from './data'; - -export interface ViewTreeNode { - title: string; - key: string; - type: LabItemType | ElementType; - children?: ViewTreeNode[]; -} diff --git a/packages/lab/src/util/component.ts b/packages/lab/src/util/component.ts deleted file mode 100644 index 2a41fed..0000000 --- a/packages/lab/src/util/component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ViewTreeNode, LabData, LabComponent } from '../types'; -import { parseComponentToViewTreeNode } from './view-tree'; - -export function parseComponentViewTree(labData: LabData | null): ViewTreeNode[] { - const treeNodes: ViewTreeNode[] = []; - labData?.components?.forEach((comp: LabComponent) => { - const node = parseComponentToViewTreeNode(comp); - treeNodes.push(node); - }); - return treeNodes; -} diff --git a/packages/lab/src/util/view-data.ts b/packages/lab/src/util/view-data.ts deleted file mode 100644 index facd2ee..0000000 --- a/packages/lab/src/util/view-data.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { deepClone } from '@idraw/util'; -import type { Data, Element, ElementType, ElementBaseDesc } from '@idraw/types'; -import type { LabComponent, LabComponentItem } from '../types'; - -const baseDescKeys = ['borderWidth', 'borderColor', 'borderRadius', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'shadowBlur', 'color', 'bgColor']; - -function parseElementBaseDesc(elem: LabComponent | LabComponentItem | Element): ElementBaseDesc { - const baseDesc: ElementBaseDesc = {}; - if (elem?.detail) { - Object.keys(elem.detail).forEach((name: string) => { - if (baseDescKeys.includes(name)) { - baseDesc[name as keyof ElementBaseDesc] = (elem.detail as any)?.[name]; - } - }); - } - return baseDesc; -} - -function parseComponentItemToElement(item: LabComponentItem): Element<'group'> { - const elem: Element<'group'> = { - uuid: item.uuid, - name: item.name, - type: 'group', - x: item.x, - y: item.y, - w: item.w, - h: item.h, - angle: item.angle || 0, - detail: { - ...parseElementBaseDesc(item), - ...{ - children: [] - } - } - }; - item.detail?.children?.forEach?.((child) => { - if (child.type === 'component-item') { - const childElem = parseComponentItemToElement(child); - elem.detail.children.push(childElem); - } else { - const childElem = deepClone(child); - elem.detail.children.push(childElem); - } - }); - return elem; -} - -function parseComponentToElement(comp: LabComponent): Element<'group'> { - const elem: Element<'group'> = { - uuid: comp.uuid, - name: comp.name, - type: 'group', - x: comp.x, - y: comp.y, - w: comp.w, - h: comp.h, - angle: comp.angle || 0, - detail: { - ...parseElementBaseDesc(comp), - ...{ - children: [] - } - } - }; - - if (comp?.detail?.default) { - elem.detail.children.push(parseComponentItemToElement(comp.detail.default)); - } - if (comp?.detail?.variants && Array.isArray(comp?.detail?.variants)) { - comp.detail.variants.forEach((item) => { - elem.detail.children.push(parseComponentItemToElement(item)); - }); - } - - return elem; -} - -export function parseComponentsToDrawData(components: LabComponent[]): Data { - const data: Data = { - elements: [] - }; - components.forEach((comp: LabComponent) => { - const elem = parseComponentToElement(comp); - data.elements.push(elem); - }); - return data; -} diff --git a/packages/lab/src/util/view-tree.ts b/packages/lab/src/util/view-tree.ts deleted file mode 100644 index f64eb54..0000000 --- a/packages/lab/src/util/view-tree.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Element, ElementType } from '@idraw/types'; -import { ViewTreeNode, LabComponent, LabComponentItem } from '../types'; - -function parseElementToViewTreeNode(elem: Element): ViewTreeNode | null { - let treeNode: ViewTreeNode | null = null; - if (elem.uuid) { - treeNode = { - key: elem.uuid, - title: elem.name || 'Unamed', - type: elem.type, - children: [] - }; - if (Array.isArray((elem as Element<'group'>)?.detail?.children)) { - (elem as Element<'group'>).detail.children.forEach((child: Element) => { - const childNode = parseElementToViewTreeNode(child); - if (childNode) { - treeNode?.children?.push(childNode); - } - }); - } - } - return treeNode; -} - -function parseComponentItemToViewTreeNode(comp: LabComponentItem): ViewTreeNode { - const treeNode: Required = { - key: comp.uuid, - title: comp.name || 'Unamed', - type: comp.type, - children: [] - }; - - if (comp?.detail?.children && Array.isArray(comp?.detail?.children)) { - comp.detail.children.forEach((child) => { - let childNode: ViewTreeNode | null = null; - if (child.type === 'component') { - childNode = parseComponentToViewTreeNode(child as LabComponent); - } else { - childNode = parseElementToViewTreeNode(child as Element); - } - if (childNode) { - treeNode.children.push(childNode); - } - }); - } - return treeNode; -} - -export function parseComponentToViewTreeNode(comp: LabComponent): ViewTreeNode { - const treeNode: Required = { - key: comp.uuid, - title: comp.name || 'Unamed', - type: comp.type, - children: [] - }; - - if (comp?.detail?.default) { - const node = parseComponentItemToViewTreeNode(comp.detail.default); - treeNode.children.push(node); - } - - if (Array.isArray(comp?.detail?.variants)) { - comp?.detail?.variants?.forEach((child: LabComponentItem) => { - const node = parseComponentItemToViewTreeNode(child); - treeNode.children.push(node); - }); - } - - return treeNode; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0a0298..bd35dcc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -164,6 +164,34 @@ importers: specifier: workspace:^0.4.0-beta.25 version: link:../types + packages/figma: + dependencies: + '@ant-design/icons': + specifier: ^5.1.3 + version: 5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@idraw/types': + specifier: workspace:^0.4.0-beta.25 + version: link:../types + '@idraw/util': + specifier: workspace:^0.4.0-beta.25 + version: link:../util + kiwi-schema: + specifier: ^0.5.0 + version: 0.5.0 + matrix-inverse: + specifier: ^2.0.0 + version: 2.0.0 + pako: + specifier: ^2.1.0 + version: 2.1.0 + uzip: + specifier: ^0.20201231.0 + version: 0.20201231.0 + devDependencies: + '@types/pako': + specifier: ^2.0.3 + version: 2.0.3 + packages/idraw: dependencies: '@idraw/board': @@ -182,40 +210,6 @@ importers: specifier: workspace:^0.4.0-beta.25 version: link:../util - packages/lab: - dependencies: - '@ant-design/icons': - specifier: ^5.1.3 - version: 5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@idraw/core': - specifier: workspace:^0.4.0-beta.25 - version: link:../core - '@idraw/util': - specifier: workspace:^0.4.0-beta.25 - version: link:../util - antd: - specifier: ^5.5.0 - version: 5.17.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: - specifier: ^2.3.2 - version: 2.5.1 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - devDependencies: - '@idraw/types': - specifier: workspace:^0.4.0-beta.25 - version: link:../types - '@types/react': - specifier: ^18.2.0 - version: 18.3.2 - '@types/react-dom': - specifier: ^18.2.1 - version: 18.3.0 - packages/renderer: dependencies: '@idraw/util': @@ -243,12 +237,6 @@ packages: '@ant-design/colors@7.0.2': resolution: {integrity: sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==} - '@ant-design/cssinjs@1.20.0': - resolution: {integrity: sha512-uG3iWzJxgNkADdZmc6W0Ci3iQAUOvLMcM8SnnmWq3r6JeocACft4ChnY/YWvI2Y+rG/68QBla/O+udke1yH3vg==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - '@ant-design/icons-svg@4.4.2': resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} @@ -259,11 +247,6 @@ packages: react: '>=16.0.0' react-dom: '>=16.0.0' - '@ant-design/react-slick@1.1.2': - resolution: {integrity: sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==} - peerDependencies: - react: '>=16.9.0' - '@babel/code-frame@7.24.2': resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} @@ -892,12 +875,6 @@ packages: resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} - '@emotion/hash@0.8.0': - resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} - - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - '@esbuild/aix-ppc64@0.20.2': resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} engines: {node: '>=12'} @@ -1360,54 +1337,6 @@ packages: engines: {node: '>=18'} hasBin: true - '@rc-component/async-validator@5.0.4': - resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} - engines: {node: '>=14.x'} - - '@rc-component/color-picker@1.5.3': - resolution: {integrity: sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - '@rc-component/context@1.4.0': - resolution: {integrity: sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - '@rc-component/mini-decimal@1.1.0': - resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} - engines: {node: '>=8.x'} - - '@rc-component/mutate-observer@1.1.0': - resolution: {integrity: sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - '@rc-component/portal@1.1.2': - resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - '@rc-component/tour@1.14.2': - resolution: {integrity: sha512-A75DZ8LVvahBIvxooj3Gvf2sxe+CGOkmzPNX7ek0i0AJHyKZ1HXe5ieIGo3m0FMdZfVOlbCJ952Duq8VKAHk6g==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - '@rc-component/trigger@2.1.1': - resolution: {integrity: sha512-UjHkedkgtEcgQu87w1VuWug1idoDJV7VUt0swxHXRcmei2uu1AuUzGBPEUlmOmXGJ+YtTgZfVLi7kuAUKoZTMA==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - '@rollup/plugin-json@6.1.0': resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} @@ -1633,8 +1562,8 @@ packages: '@types/node@20.12.12': resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - '@types/prop-types@15.7.12': - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + '@types/pako@2.0.3': + resolution: {integrity: sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==} '@types/qs@6.9.15': resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} @@ -1642,12 +1571,6 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@18.3.0': - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - - '@types/react@18.3.2': - resolution: {integrity: sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==} - '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -1800,12 +1723,6 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - antd@5.17.2: - resolution: {integrity: sha512-LVCR4kKWoNwaOEfYuWuXqwrK24W6YY6jlzROB4dTEEFvb2ovPi/5h9GcEB8U7ZJY/Yuvm1ehvRm9vohxVJzC3A==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - any-base@1.1.0: resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} @@ -1822,9 +1739,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - array-tree-filter@2.1.0: - resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -2033,9 +1947,6 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - compute-scroll-into-view@3.1.0: - resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -2049,9 +1960,6 @@ packages: copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} - copy-to-clipboard@3.3.3: - resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - core-js-compat@3.37.1: resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} @@ -2093,9 +2001,6 @@ packages: resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} engines: {node: '>=8'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - data-uri-to-buffer@6.0.2: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} @@ -2104,9 +2009,6 @@ packages: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} - dayjs@1.11.11: - resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} - debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -2883,9 +2785,6 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json2mq@0.2.0: - resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -2897,6 +2796,10 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kiwi-schema@0.5.0: + resolution: {integrity: sha512-X+FpfU0yTEtc6aTHS7VwbOpvQwRt70+pXXWRI5fd6CvWhe7pSVC854TVo4Zo0x5/wwcWj+/9KUlXpdcP0dY9AA==} + hasBin: true + kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -2976,6 +2879,9 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + matrix-inverse@2.0.0: + resolution: {integrity: sha512-iUZfjmnAEDah54qLlj63PYFnZvcCwW+mhfYgf3KrtDn1ruyVE5vFrEeJ77RfsHaqMN/L3ZLnP+5/O2E7bgKEvQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3157,6 +3063,9 @@ packages: pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -3333,11 +3242,6 @@ packages: pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - qrcode.react@3.1.0: - resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - qs@6.12.1: resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} engines: {node: '>=0.6'} @@ -3355,234 +3259,12 @@ packages: resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} engines: {node: '>= 0.6'} - rc-cascader@3.25.0: - resolution: {integrity: sha512-mBY6/CykOvzAYnIye0rpt5JkMAXJaX8zZawOwSndbKuFakYE+leqBQWIZoN9HIgAptPpTi2Aty3RvbaBmk8SKQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-checkbox@3.2.0: - resolution: {integrity: sha512-8inzw4y9dAhZmv/Ydl59Qdy5tdp9CKg4oPVcRigi+ga/yKPZS5m5SyyQPtYSgbcqHRYOdUhiPSeKfktc76du1A==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-collapse@3.7.3: - resolution: {integrity: sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-dialog@9.4.0: - resolution: {integrity: sha512-AScCexaLACvf8KZRqCPz12BJ8olszXOS4lKlkMyzDQHS1m0zj1KZMYgmMCh39ee0Dcv8kyrj8mTqxuLyhH+QuQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-drawer@7.1.0: - resolution: {integrity: sha512-nBE1rF5iZvpavoyqhSSz2mk/yANltA7g3aF0U45xkx381n3we/RKs9cJfNKp9mSWCedOKWt9FLEwZDaAaOGn2w==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-dropdown@4.2.0: - resolution: {integrity: sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==} - peerDependencies: - react: '>=16.11.0' - react-dom: '>=16.11.0' - - rc-field-form@2.0.1: - resolution: {integrity: sha512-3WK/POHBcfMFKrzScrkmgMIXqoVQ0KgVwcVnej/ukwuQG4ZHCJaTi2KhM+tWTK4WODBXbmjKg5pKHj2IVmSg4A==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-image@7.6.0: - resolution: {integrity: sha512-tL3Rvd1sS+frZQ01i+tkeUPaOeFz2iG9/scAt/Cfs0hyCRVA/w0Pu1J/JxIX8blalvmHE0bZQRYdOmRAzWu4Hg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-input-number@9.0.0: - resolution: {integrity: sha512-RfcDBDdWFFetouWFXBA+WPEC8LzBXyngr9b+yTLVIygfFu7HiLRGn/s/v9wwno94X7KFvnb28FNynMGj9XJlDQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-input@1.4.5: - resolution: {integrity: sha512-AjzykhwnwYTRSwwgCu70CGKBIAv6bP2nqnFptnNTprph/TF1BAs0Qxl91mie/BR6n827WIJB6ZjaRf9iiMwAfw==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - - rc-mentions@2.11.1: - resolution: {integrity: sha512-upb4AK1SRFql7qGnbLEvJqLMugVVIyjmwBJW9L0eLoN9po4JmJZaBzmKA4089fNtsU8k6l/tdZiVafyooeKnLw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-menu@9.13.0: - resolution: {integrity: sha512-1l8ooCB3HcYJKCltC/s7OxRKRjgymdl9htrCeGZcXNaMct0RxZRK6OPV3lPhVksIvAGMgzPd54ClpZ5J4b8cZA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-motion@2.9.1: - resolution: {integrity: sha512-QD4bUqByjVQs7PhUT1d4bNxvtTcK9ETwtg7psbDfo6TmYalH/1hhjj4r2hbhW7g5OOEqYHhfwfj4noIvuOVRtQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-notification@5.4.0: - resolution: {integrity: sha512-li19y9RoYJciF3WRFvD+DvWS70jdL8Fr+Gfb/OshK+iY6iTkwzoigmSIp76/kWh5tF5i/i9im12X3nsF85GYdA==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-overflow@1.3.2: - resolution: {integrity: sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-pagination@4.0.4: - resolution: {integrity: sha512-GGrLT4NgG6wgJpT/hHIpL9nELv27A1XbSZzECIuQBQTVSf4xGKxWr6I/jhpRPauYEWEbWVw22ObG6tJQqwJqWQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-picker@4.5.0: - resolution: {integrity: sha512-suqz9bzuhBQlf7u+bZd1bJLPzhXpk12w6AjQ9BTPTiFwexVZgUKViG1KNLyfFvW6tCUZZK0HmCCX7JAyM+JnCg==} - engines: {node: '>=8.x'} - peerDependencies: - date-fns: '>= 2.x' - dayjs: '>= 1.x' - luxon: '>= 3.x' - moment: '>= 2.x' - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - date-fns: - optional: true - dayjs: - optional: true - luxon: - optional: true - moment: - optional: true - - rc-progress@4.0.0: - resolution: {integrity: sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-rate@2.12.0: - resolution: {integrity: sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-resize-observer@1.4.0: - resolution: {integrity: sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-segmented@2.3.0: - resolution: {integrity: sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - - rc-select@14.13.4: - resolution: {integrity: sha512-nXFsS53RxCP6ePeKhOj3gvgdNpTqdQnNKhipGrV/z+pB3Md5heGfV72YX5Wfb1A7Ca1QkbVTPFLJh+A8WYFOSA==} - engines: {node: '>=8.x'} - peerDependencies: - react: '*' - react-dom: '*' - - rc-slider@10.6.2: - resolution: {integrity: sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-steps@6.0.1: - resolution: {integrity: sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-switch@4.1.0: - resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-table@7.45.6: - resolution: {integrity: sha512-FYsTya3RQzLYct+o3fqHIZQIwrmsvrvhTg/I6hzlJZ1XoVAGoTmgkN1mMilVlYgksZTey9BCNYh94c6yhdjTXQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-tabs@15.0.0: - resolution: {integrity: sha512-7m541VcEiJSpHZmosMZNMIhemxtIN+f0WDhZNyXQ1/cZ40aaWsknlbj0FH6HryLoKEQvBnCI89hgQuT7MBSOBA==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-textarea@1.6.3: - resolution: {integrity: sha512-8k7+8Y2GJ/cQLiClFMg8kUXOOdvcFQrnGeSchOvI2ZMIVvX5a3zQpLxoODL0HTrvU63fPkRmMuqaEcOF9dQemA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-tooltip@6.2.0: - resolution: {integrity: sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - - rc-tree-select@5.20.0: - resolution: {integrity: sha512-zFtkHx5/6PnXSi3oSbBSFbIPiJJQdpSU3qz/joLe75URgvxmTHi989O8MtMgpwyZwrCMOJpGi6L1uy+13uzZPw==} - peerDependencies: - react: '*' - react-dom: '*' - - rc-tree@5.8.7: - resolution: {integrity: sha512-cpsIQZ4nNYwpj6cqPRt52e/69URuNdgQF9wZ10InmEf8W3+i0A41OVmZWwHuX9gegQSqj+DPmaDkZFKQZ+ZV1w==} - engines: {node: '>=10.x'} - peerDependencies: - react: '*' - react-dom: '*' - - rc-upload@4.5.2: - resolution: {integrity: sha512-QO3ne77DwnAPKFn0bA5qJM81QBjQi0e0NHdkvpFyY73Bea2NfITiotqJqVjHgeYPOJu5lLVR32TNGP084aSoXA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - rc-util@5.40.1: resolution: {integrity: sha512-wsYjO59DpyyZdMe1yCSqHiHU8sWjkP1wIfj2mR0aHaNmFFgw727kkOFY7FBukg4rXhIw131549SLxQXQoIB73A==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-virtual-list@3.12.0: - resolution: {integrity: sha512-43+/lr7bImpvEwTFw1FTYwSg42VHzRgO5PiCEEUROj8D2+M2SCvANqGIa9QyhoFLVQtc+2QXvgTB7VPGG7oOoQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -3638,9 +3320,6 @@ packages: requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - resize-observer-polyfill@1.5.1: - resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} - resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -3709,9 +3388,6 @@ packages: scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scroll-into-view-if-needed@3.1.0: - resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} - secure-compare@3.0.1: resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} @@ -3805,9 +3481,6 @@ packages: streamx@2.16.1: resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} - string-convert@0.2.1: - resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} - string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -3851,9 +3524,6 @@ packages: resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} engines: {node: '>=10'} - stylis@4.3.2: - resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} - supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -3891,10 +3561,6 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - throttle-debounce@5.0.0: - resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} - engines: {node: '>=12.22'} - through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -3915,9 +3581,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toggle-selection@1.0.6: - resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} - token-types@4.2.1: resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} engines: {node: '>=10'} @@ -4034,6 +3697,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uzip@0.20201231.0: + resolution: {integrity: sha512-OZeJfZP+R0z9D6TmBgLq2LHzSSptGMGDGigGiEe0pr8UBe/7fdflgHlHBNDASTXB5jnFuxHpNaJywSg8YFeGng==} + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -4205,18 +3871,6 @@ snapshots: dependencies: '@ctrl/tinycolor': 3.6.1 - '@ant-design/cssinjs@1.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - '@emotion/hash': 0.8.0 - '@emotion/unitless': 0.7.5 - classnames: 2.5.1 - csstype: 3.1.3 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - stylis: 4.3.2 - '@ant-design/icons-svg@4.4.2': {} '@ant-design/icons@5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -4229,15 +3883,6 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@ant-design/react-slick@1.1.2(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - json2mq: 0.2.0 - react: 18.3.1 - resize-observer-polyfill: 1.5.1 - throttle-debounce: 5.0.0 - '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.5 @@ -4997,10 +4642,6 @@ snapshots: '@ctrl/tinycolor@3.6.1': {} - '@emotion/hash@0.8.0': {} - - '@emotion/unitless@0.7.5': {} - '@esbuild/aix-ppc64@0.20.2': optional: true @@ -5557,67 +5198,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@rc-component/async-validator@5.0.4': - dependencies: - '@babel/runtime': 7.24.5 - - '@rc-component/color-picker@1.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - '@ctrl/tinycolor': 3.6.1 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@rc-component/context@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@rc-component/mini-decimal@1.1.0': - dependencies: - '@babel/runtime': 7.24.5 - - '@rc-component/mutate-observer@1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@rc-component/portal@1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@rc-component/tour@1.14.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@rc-component/trigger@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@rollup/plugin-json@6.1.0(rollup@4.17.2)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.17.2) @@ -5831,21 +5411,12 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/prop-types@15.7.12': {} + '@types/pako@2.0.3': {} '@types/qs@6.9.15': {} '@types/range-parser@1.2.7': {} - '@types/react-dom@18.3.0': - dependencies: - '@types/react': 18.3.2 - - '@types/react@18.3.2': - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 @@ -6024,63 +5595,6 @@ snapshots: ansi-styles@6.2.1: {} - antd@5.17.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@ant-design/colors': 7.0.2 - '@ant-design/cssinjs': 1.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ant-design/icons': 5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ant-design/react-slick': 1.1.2(react@18.3.1) - '@babel/runtime': 7.24.5 - '@ctrl/tinycolor': 3.6.1 - '@rc-component/color-picker': 1.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/mutate-observer': 1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/tour': 1.14.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - copy-to-clipboard: 3.3.3 - dayjs: 1.11.11 - qrcode.react: 3.1.0(react@18.3.1) - rc-cascader: 3.25.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-checkbox: 3.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-collapse: 3.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-dialog: 9.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-drawer: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-dropdown: 4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-field-form: 2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-image: 7.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-input: 1.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-input-number: 9.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-mentions: 2.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-notification: 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-pagination: 4.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-picker: 4.5.0(dayjs@1.11.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-progress: 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-rate: 2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-segmented: 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-select: 14.13.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-slider: 10.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-steps: 6.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-switch: 4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-table: 7.45.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tabs: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-textarea: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tooltip: 6.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.8.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree-select: 5.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-upload: 4.5.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - scroll-into-view-if-needed: 3.1.0 - throttle-debounce: 5.0.0 - transitivePeerDependencies: - - date-fns - - luxon - - moment - any-base@1.1.0: {} anymatch@3.1.3: @@ -6096,8 +5610,6 @@ snapshots: argparse@2.0.1: {} - array-tree-filter@2.1.0: {} - array-union@2.1.0: {} ast-types@0.13.4: @@ -6334,8 +5846,6 @@ snapshots: commander@2.20.3: {} - compute-scroll-into-view@3.1.0: {} - concat-map@0.0.1: {} content-disposition@0.5.2: {} @@ -6346,10 +5856,6 @@ snapshots: dependencies: is-what: 3.14.1 - copy-to-clipboard@3.3.3: - dependencies: - toggle-selection: 1.0.6 - core-js-compat@3.37.1: dependencies: browserslist: 4.23.0 @@ -6398,8 +5904,6 @@ snapshots: dependencies: cssom: 0.3.8 - csstype@3.1.3: {} - data-uri-to-buffer@6.0.2: {} data-urls@3.0.2: @@ -6408,8 +5912,6 @@ snapshots: whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - dayjs@1.11.11: {} - debug@3.2.7: dependencies: ms: 2.1.3 @@ -7449,10 +6951,6 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - json2mq@0.2.0: - dependencies: - string-convert: 0.2.1 - json5@2.2.3: {} jsonfile@6.1.0: @@ -7465,6 +6963,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kiwi-schema@0.5.0: {} + kleur@3.0.3: {} koa-compose@4.1.0: {} @@ -7553,6 +7053,8 @@ snapshots: dependencies: tmpl: 1.0.5 + matrix-inverse@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -7709,6 +7211,8 @@ snapshots: pako@1.0.11: {} + pako@2.1.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -7879,10 +7383,6 @@ snapshots: pure-rand@6.1.0: {} - qrcode.react@3.1.0(react@18.3.1): - dependencies: - react: 18.3.1 - qs@6.12.1: dependencies: side-channel: 1.0.6 @@ -7895,309 +7395,6 @@ snapshots: range-parser@1.2.0: {} - rc-cascader@3.25.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - array-tree-filter: 2.1.0 - classnames: 2.5.1 - rc-select: 14.13.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.8.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-checkbox@3.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-collapse@3.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-dialog@9.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-drawer@7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-dropdown@4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-field-form@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/async-validator': 5.0.4 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-image@7.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-dialog: 9.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-input-number@9.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/mini-decimal': 1.1.0 - classnames: 2.5.1 - rc-input: 1.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-input@1.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-mentions@2.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-input: 1.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-textarea: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-menu@9.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-motion@2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-notification@5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-overflow@1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-pagination@4.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-picker@4.5.0(dayjs@1.11.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - dayjs: 1.11.11 - - rc-progress@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-rate@2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-resize-observer@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - resize-observer-polyfill: 1.5.1 - - rc-segmented@2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-select@14.13.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-slider@10.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-steps@6.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-switch@4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-table@7.45.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/context': 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-tabs@15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-dropdown: 4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-textarea@1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-input: 1.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-tooltip@6.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - '@rc-component/trigger': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: 2.5.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-tree-select@5.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-select: 14.13.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.8.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-tree@5.8.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-motion: 2.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - rc-upload@4.5.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - rc-util@5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.5 @@ -8205,15 +7402,6 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - rc-virtual-list@3.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.24.5 - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 @@ -8269,8 +7457,6 @@ snapshots: requires-port@1.0.0: {} - resize-observer-polyfill@1.5.1: {} - resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -8352,10 +7538,6 @@ snapshots: dependencies: loose-envify: 1.4.0 - scroll-into-view-if-needed@3.1.0: - dependencies: - compute-scroll-into-view: 3.1.0 - secure-compare@3.0.1: {} semver@5.7.2: @@ -8454,8 +7636,6 @@ snapshots: optionalDependencies: bare-events: 2.2.2 - string-convert@0.2.1: {} - string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -8498,8 +7678,6 @@ snapshots: '@tokenizer/token': 0.3.0 peek-readable: 4.1.0 - stylis@4.3.2: {} - supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -8545,8 +7723,6 @@ snapshots: text-table@0.2.0: {} - throttle-debounce@5.0.0: {} - through@2.3.8: {} timm@1.7.1: {} @@ -8561,8 +7737,6 @@ snapshots: dependencies: is-number: 7.0.0 - toggle-selection@1.0.6: {} - token-types@4.2.1: dependencies: '@tokenizer/token': 0.3.0 @@ -8671,6 +7845,8 @@ snapshots: util-deprecate@1.0.2: {} + uzip@0.20201231.0: {} + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.2.0: diff --git a/scripts/config.ts b/scripts/config.ts index d0f8ac7..7cac7ca 100644 --- a/scripts/config.ts +++ b/scripts/config.ts @@ -13,10 +13,6 @@ const packages = [ dirName: 'renderer', globalName: 'iDrawRenderer' }, - // { - // dirName: 'kernal', - // globalName: 'iDrawKernal', - // }, { dirName: 'core', globalName: 'iDrawCore' @@ -24,6 +20,10 @@ const packages = [ { dirName: 'idraw', globalName: 'iDraw' + }, + { + dirName: 'figma', + globalName: 'iDrawFigma' } ];