Repository: lidojs/canva-clone
Branch: master
Commit: 195c80465814
Files: 55
Total size: 294.7 KB
Directory structure:
gitextract_2xb0w4ev/
├── README.md
├── index.html
├── package.json
├── src/
│ ├── assets/
│ │ └── .gitkeep
│ ├── constant/
│ │ ├── data.ts
│ │ └── text-effects.ts
│ ├── features/
│ │ └── design/
│ │ ├── components/
│ │ │ ├── LidoJSEditor.tsx
│ │ │ ├── editor-content/
│ │ │ │ ├── EditorContent.tsx
│ │ │ │ └── index.ts
│ │ │ ├── editor-header/
│ │ │ │ ├── EditorHeader.tsx
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── layer-settings/
│ │ │ │ ├── LayerSettings.tsx
│ │ │ │ └── index.ts
│ │ │ ├── preview/
│ │ │ │ ├── PreviewModal.tsx
│ │ │ │ └── index.ts
│ │ │ ├── sidebar/
│ │ │ │ ├── DrawContent.tsx
│ │ │ │ ├── FrameContent.tsx
│ │ │ │ ├── GraphicContent.tsx
│ │ │ │ ├── IframeContent.tsx
│ │ │ │ ├── ImageContent.tsx
│ │ │ │ ├── Photo.tsx
│ │ │ │ ├── QrCodeContent.tsx
│ │ │ │ ├── ShapeContent.tsx
│ │ │ │ ├── Sidebar.tsx
│ │ │ │ ├── TableContent.tsx
│ │ │ │ ├── TemplateContent.tsx
│ │ │ │ ├── TextContent.tsx
│ │ │ │ ├── UploadContent.tsx
│ │ │ │ ├── VideoContent.tsx
│ │ │ │ └── index.ts
│ │ │ └── tabs/
│ │ │ ├── TabList.tsx
│ │ │ └── index.ts
│ │ ├── config/
│ │ │ ├── iframe.tsx
│ │ │ ├── line.tsx
│ │ │ ├── qrCode.tsx
│ │ │ └── shape.tsx
│ │ └── pages/
│ │ ├── DesignPage.tsx
│ │ └── index.ts
│ ├── main.tsx
│ ├── pages/
│ │ └── Main.tsx
│ ├── shared/
│ │ ├── components/
│ │ │ ├── index.ts
│ │ │ └── masonry/
│ │ │ ├── Masonry.tsx
│ │ │ └── index.ts
│ │ ├── icons/
│ │ │ └── pencil/
│ │ │ ├── Highlighter.tsx
│ │ │ ├── Marker.tsx
│ │ │ └── Pencil.tsx
│ │ └── theme/
│ │ ├── index.ts
│ │ ├── palette.ts
│ │ └── theme.ts
│ ├── styles.css
│ └── utils/
│ ├── download.ts
│ └── thumbnail.ts
├── tsconfig.json
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# LidoJS - Powerful Design Tool for Creatives
LidoJS is a simple and user-friendly graphic design tool, that helps you create great designs quickly. Whether you need presentations, marketing materials, or social media graphics, LidoJS has what you need to bring your ideas to life.
The tool is developed from scratch with ReactJS, so it's easy to upgrade by yourself.
This code will show you how to integrate LidoJS into an application to make an online design editor application.
Explore the platform at [https://lidojs.com](https://lidojs.com) or meet us at [https://discord.gg/mBj7fqKpEM](https://discord.gg/mBj7fqKpEM).
## **Overview**
LidoJS makes designing simple and fun, offering a variety of tools to help designers, marketers, and content creators reach their goals. From creating slides to making graphics, LidoJS makes the whole process easier.
## **Demo**
[https://demo.lidojs.com](https://demo.lidojs.com).
After creating designs, you can download them in various formats, including PDF, PNG, and JPG. Download feature does not include in the packages, but you can see the output file below
[Open PDF file](https://s3.us-east-2.amazonaws.com/lidojs.com/output-from-templates.pdf)
## **Key Features**
- **Drag-and-Drop Interface:** Simplify the design process with an intuitive editor.
- **Customizable Templates:** Access a vast collection of pre-designed templates for presentations, posters, and social media.
- **Advanced Editing Tools:** Fine-tune your designs with precise editing options, including layering, masking, painting, shapes, frames, and color adjustments.
- **Export Options:** Download designs in various formats suitable for both print (PDF, PNG, JPG) and digital platforms (SVG, WebP).
Technical Highlights
## **Technical Highlights**
- **Proven Technology:** LidoJS uses the same advanced technical solutions as Canva, ensuring a reliable and high-performance design experience.
- **Built from Scratch:** Core features are developed entirely with React.js, without relying on third-party frameworks.
- **Unlimited Customization:** Enjoy total creative freedom with the ability to customize any element to fit your specific needs.
## **Usage Purpose**
LidoJS works for many design tasks, such as:
- **Presentations:** Craft professional slide decks with ease using customizable templates.
- **Marketing Campaigns:** Create eye-catching promotional materials for ads and social media.
- **Branding:** Develop cohesive brand assets such as logos and banners.
- **Content Creation:** Design visually compelling graphics for blogs, websites, and newsletters.
## **Trusted by Leading Brands**
LidoJS is a preferred design tool for top brands and organizations, including:
- **Sendsteps:** Engaging presentation solutions.
- **Menuzen:** Dynamic digital menu creation.
- **Designstripe:** Simplified design experiences.
- **Momentumstack:** Innovative technology and business services.
Start designing with LidoJS and experience the future of creative possibilities. Visit [https://lidojs.com](https://lidojs.com) to learn more and get started today.
## Disclaimer
This source code is developed entirely by our team from scratch. We have not used any third-party resources that require licensing.
Our product is designed to assist users in developing design applications efficiently. However, we do not guarantee any specific outcomes or take responsibility for how this software is used.
Use this code at your own risk. We are not liable for any damages or issues arising from its use.
================================================
FILE: index.html
================================================
LidoJS Design Editor
You need to enable JavaScript to run this app.
<% if(process.env.NODE_ENV !== 'development'){ %>
<% } %>
================================================
FILE: package.json
================================================
{
"name": "@lidojs/react",
"version": "2.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"@duyank/icons": "^0.1.2",
"@emotion/react": "11.14.0",
"@emotion/styled": "11.14.0",
"@lidojs/color-picker": "^2.0.0",
"@lidojs/design-core": "^2.0.0",
"@lidojs/design-editor": "^2.0.0",
"@lidojs/design-layers": "^2.0.0",
"@lidojs/design-screen": "^2.0.0",
"@lidojs/design-utils": "^2.0.0",
"@lidojs/draw": "^2.0.0",
"@lidojs/text-editor": "^2.0.0",
"@mui/material": "^6.4.5",
"axios": "^1.7.9",
"lodash": "^4.17.21",
"react": "^18.3.1",
"react-device-detect": "^2.2.3",
"react-dom": "catalog:",
"react-responsive-masonry": "^2.7.1",
"react-use": "^17.6.0",
"uuid": "^11.0.5"
},
"devDependencies": {
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.5",
"prop-types": "^15.8.1",
"vite-bundle-analyzer": "^0.17.0",
"vite-plugin-environment": "^1.1.3"
}
}
================================================
FILE: src/assets/.gitkeep
================================================
================================================
FILE: src/constant/data.ts
================================================
export const data = [
{
layers: {
ROOT: {
type: { resolvedName: 'RootLayer' },
props: {
boxSize: { width: 1640, height: 924 },
position: { x: 0, y: 0 },
rotate: 0,
color: 'rgb(255, 255, 255)',
image: null,
},
locked: false,
child: [
'd80fa039-b645-4678-89f2-fc0336958989',
'851673f7-8917-4b3e-95d0-3a81b6f638bb',
'af7b69ea-3060-46ff-914e-9833d66ddc1d',
'09a24f96-90bd-4e0d-b610-47d23de11c2b',
'2096d6ab-d78e-4acf-b509-170a3e6b97f5',
],
parent: null,
},
'd80fa039-b645-4678-89f2-fc0336958989': {
type: { resolvedName: 'ShapeLayer' },
props: {
shape: 'rectangle',
position: { x: -41, y: 652 },
boxSize: { width: 1766, height: 296, x: -41, y: 652 },
rotate: 0,
color: 'rgb(253, 235, 207)',
},
locked: false,
child: [],
parent: 'ROOT',
},
'851673f7-8917-4b3e-95d0-3a81b6f638bb': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Agdasima',
fontSize: '42px',
lineHeight: 1.03,
letterSpacing: 0,
textTransform: '',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'color', attrs: { color: 'rgb(0, 0, 0)' } },
],
text: 'LIDOJS',
},
],
},
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Agdasima',
fontSize: '42px',
lineHeight: 1.03,
letterSpacing: 0,
textTransform: '',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'color', attrs: { color: 'rgb(0, 0, 0)' } },
],
text: 'DESIGN EDITOR',
},
],
},
],
},
position: { x: 528.5031977930256, y: 276.6364429758855 },
boxSize: {
width: 536.3009995574356,
height: 144.98254063816975,
x: 523.1390728476821,
y: 259.9867549668875,
},
scale: 1.6664659843467788,
rotate: 0,
fonts: [
{
name: 'Agdasima',
fonts: [
{
urls: [
'https://fonts.gstatic.com/s/agdasima/v4/PN_zRfyxp2f1fUCgAMg6rzjb_-Da.ttf',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [42],
},
locked: false,
child: [],
parent: 'ROOT',
},
'af7b69ea-3060-46ff-914e-9833d66ddc1d': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Oswald',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'bold' },
{ type: 'color', attrs: { color: 'rgb(0, 0, 0)' } },
],
text: 'DEVELOPED WITH REACTJS',
},
],
},
],
},
position: { x: 665.6953642384103, y: 440.2251655629139 },
boxSize: {
width: 261.91666666666606,
height: 25,
x: 660.2715231788078,
y: 440.2251655629139,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Oswald',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [18],
effect: null,
},
locked: false,
child: [],
parent: 'ROOT',
},
'09a24f96-90bd-4e0d-b610-47d23de11c2b': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Oswald',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'bold' },
{ type: 'color', attrs: { color: 'rgb(0, 0, 0)' } },
],
text: 'DISCORD: https://discord.gg/mBj7fqKpEM',
},
],
},
],
},
position: { x: 587.4569536423838, y: 839.8609271523178 },
boxSize: {
width: 379.3868653421627,
height: 25,
x: 587.4569536423838,
y: 839.8609271523178,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Oswald',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [18],
effect: null,
},
locked: false,
child: [],
parent: 'ROOT',
},
'2096d6ab-d78e-4acf-b509-170a3e6b97f5': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Oswald',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'bold' },
{ type: 'color', attrs: { color: 'rgb(0, 0, 0)' } },
],
text: 'CONTACT: DUYANH980@GMAIL.COM',
},
],
},
],
},
position: { x: 634.1125827814567, y: 810.4900662251654 },
boxSize: {
width: 293.4994481236197,
height: 25,
x: 634.1125827814567,
y: 810.4900662251654,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Oswald',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Oswald/Oswald-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [18],
effect: null,
},
locked: false,
child: [],
parent: 'ROOT',
},
},
},
];
================================================
FILE: src/constant/text-effects.ts
================================================
export const addAHeading = {
rootId: 'f2d33316-8857-4496-a0c7-3dcc9c4ff981',
layers: {
'f2d33316-8857-4496-a0c7-3dcc9c4ff981': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Roboto',
fontSize: '68px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: '',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(0, 0, 0)',
},
},
],
text: 'Add a heading',
},
],
},
],
},
position: { x: 525.12102340009, y: 261.582179409994 },
boxSize: {
width: 536.3009995574356,
height: 95,
x: 523.1390728476821,
y: 259.9867549668875,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Roboto',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold_Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
style: 'Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [68],
},
locked: false,
child: [],
parent: 'ROOT',
},
},
};
export const addASubheading = {
rootId: '9cc89a8c-49d5-4f90-9964-f65bbe90db92',
layers: {
'9cc89a8c-49d5-4f90-9964-f65bbe90db92': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Roboto',
fontSize: '38px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: '',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(0, 0, 0)',
},
},
],
text: 'Add a subheading',
},
],
},
],
},
position: { x: 519.12102340009, y: 365.582179409994 },
boxSize: {
width: 536.3009995574356,
height: 53,
x: 523.1390728476821,
y: 259.9867549668875,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Roboto',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold_Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
style: 'Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [38],
},
locked: false,
child: [],
parent: 'ROOT',
},
},
};
export const addABodyText = {
rootId: '3cace409-216f-4e0e-9449-9248901c8c94',
layers: {
'3cace409-216f-4e0e-9449-9248901c8c94': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Roboto',
fontSize: '26px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: '',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'color',
attrs: {
color: 'rgb(0, 0, 0)',
},
},
],
text: 'Add a little bit of body text',
},
],
},
],
},
position: { x: 508.99988653474736, y: 434.903672486454 },
boxSize: {
width: 536.3009995574356,
height: 36,
x: 523.1390728476821,
y: 259.9867549668875,
},
scale: 1,
rotate: 0,
fonts: [
{
name: 'Roboto',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold_Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
style: 'Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)'],
fontSizes: [26],
},
locked: false,
child: [],
parent: 'ROOT',
},
},
};
================================================
FILE: src/features/design/components/LidoJSEditor.tsx
================================================
'use client';
import type { FontData } from '@lidojs/design-core';
import { Editor, type GetFontQuery, PageControl } from '@lidojs/design-editor';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { EditorContent } from './editor-content';
import { EditorHeader } from './editor-header';
import { LayerSettings } from './layer-settings';
import { PreviewModal } from './preview';
import { Sidebar } from './sidebar';
export const LidoJSEditor = ({
googleFontList,
}: { googleFontList: FontData[] }) => {
const leftSidebarRef = useRef(null);
const [openPreview, setOpenPreview] = useState(false);
const getFonts = useCallback(
async (query: GetFontQuery) => {
return googleFontList
.filter((i) => !query.q || i.name.toLowerCase().includes(query.q))
.slice(
Number.parseInt(query?.offset ?? '', 10),
Number.parseInt(query?.offset ?? '', 10) +
Number.parseInt(query?.limit || '', 10),
);
},
[googleFontList],
);
const [viewPortHeight, setViewPortHeight] = useState();
useEffect(() => {
if (!window) return;
const windowHeight = () => {
setViewPortHeight(window.innerHeight);
};
window.addEventListener('resize', windowHeight);
windowHeight();
return () => {
window.removeEventListener('resize', windowHeight);
};
}, []);
const config = useMemo(
() => ({
assetPath: './assets',
frame: {
defaultImage: {
url: './assets/images/frame-placeholder.png',
width: 1200,
height: 800,
},
},
}),
[],
);
const uploadImage = async (file: File) => {
// TODO: to integrate with image manipulation then need update this
return new Promise<{ url: string; thumb: string }>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve({
url: reader.result as string,
thumb: reader.result as string,
});
};
reader.onerror = reject;
});
};
return (
setOpenPreview(true)} />
{openPreview && setOpenPreview(false)} />}
);
};
================================================
FILE: src/features/design/components/editor-content/EditorContent.tsx
================================================
import { DesignFrame } from '@lidojs/design-editor';
import { data } from '../../../../constant/data';
export const EditorContent = () => {
return ;
};
================================================
FILE: src/features/design/components/editor-content/index.ts
================================================
export * from './EditorContent';
================================================
FILE: src/features/design/components/editor-header/EditorHeader.tsx
================================================
import ArrowClockwiseIcon from '@duyank/icons/regular/ArrowClockwise';
import ArrowCounterClockwiseIcon from '@duyank/icons/regular/ArrowCounterClockwise';
import GithubLogoIcon from '@duyank/icons/regular/GithubLogo';
import PlayCircleIcon from '@duyank/icons/regular/PlayCircle';
import { useEditor } from '@lidojs/design-editor';
import {
type ChangeEvent,
type ForwardRefRenderFunction,
forwardRef,
useRef,
} from 'react';
import { downloadObjectAsJson } from '../../../../utils/download';
interface HeaderLayoutProps {
openPreview: () => void;
}
const EditorHeaderForwardRef: ForwardRefRenderFunction<
HTMLDivElement,
HeaderLayoutProps
> = ({ openPreview }, ref) => {
const uploadRef = useRef(null);
const { actions, query } = useEditor();
const handleExport = () => {
downloadObjectAsJson('file', query.serialize());
};
const handleImport = (e: ChangeEvent) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = () => {
const fileContent = JSON.parse(reader.result as string);
actions.setData(fileContent);
};
reader.readAsText(file);
e.target.value = '';
}
};
return (
);
};
export const EditorHeader = forwardRef(EditorHeaderForwardRef);
================================================
FILE: src/features/design/components/editor-header/index.ts
================================================
export * from './EditorHeader';
================================================
FILE: src/features/design/components/index.ts
================================================
export * from './LidoJSEditor';
================================================
FILE: src/features/design/components/layer-settings/LayerSettings.tsx
================================================
import {
LayerSettings as EditorLayerSettings,
useSelectedLayers,
} from '@lidojs/design-editor';
export const LayerSettings = () => {
const { selectedLayerIds } = useSelectedLayers();
return (
0 ? 'flex' : 'none',
justifyContent: 'center',
zIndex: 20,
height: 72,
},
}}
>
);
};
================================================
FILE: src/features/design/components/layer-settings/index.ts
================================================
export * from './LayerSettings';
================================================
FILE: src/features/design/components/preview/PreviewModal.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import { Preview } from '@lidojs/design-editor';
import type { FC } from 'react';
interface PreviewModalProps {
onClose: () => void;
}
export const PreviewModal: FC = ({ onClose }) => {
return (
);
};
================================================
FILE: src/features/design/components/preview/index.ts
================================================
export * from './PreviewModal';
================================================
FILE: src/features/design/components/sidebar/DrawContent.tsx
================================================
import XBoldIcon from '@duyank/icons/bold/XBold';
import { useEditor } from '@lidojs/design-editor';
import { useDraw } from '@lidojs/draw';
import { type FC, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Highlighter } from '../../../../shared/icons/pencil/Highlighter';
import { Marker } from '../../../../shared/icons/pencil/Marker';
import { Pencil } from '../../../../shared/icons/pencil/Pencil';
export const DrawContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const svgRef = useRef(null);
const boxRef = useRef(null);
const penColorRef = useRef('#0571d3');
const penWidthRef = useRef(5);
const scaleRef = useRef(1);
const transparencyRef = useRef(1);
const [size, setSize] = useState({ width: 0, height: 0 });
const { actions, scale, activePage, sidebar } = useEditor((state) => ({
scale: state.scale,
activePage: state.activePage,
sidebar: state.sidebar,
}));
useEffect(() => {
scaleRef.current = scale;
}, [scale]);
useDraw({
options: {
width: penWidthRef.current * scaleRef.current,
minWidth: 33 * scaleRef.current,
minHeight: 33 * scaleRef.current,
},
canStartDraw: (e) => {
const page = document.getElementById(`lidojs-page-${activePage}`);
if (!page) {
throw new Error("Can't find page");
}
const rect = page.getBoundingClientRect();
if (
e.x >= rect.x &&
e.x <= rect.x + rect.width &&
e.y >= rect.y &&
e.y <= rect.y + rect.height &&
!sidebar &&
boxRef.current
) {
boxRef.current.style.pointerEvents = 'auto';
boxRef.current.style.opacity = transparencyRef.current.toString();
return true;
}
return false;
},
onChange: (path) => {
if (!svgRef.current) return;
const svgPath = document.createElementNS(
'http://www.w3.org/2000/svg',
'path',
);
svgPath.setAttributeNS(null, 'd', path);
svgPath.setAttributeNS(null, 'fill', 'none');
svgPath.setAttributeNS(null, 'stroke', penColorRef.current);
svgPath.setAttributeNS(null, 'stroke-linecap', 'round');
svgPath.setAttributeNS(
null,
'stroke-width',
(penWidthRef.current * scaleRef.current).toString(),
);
svgRef.current.appendChild(svgPath);
},
onEnd: (path, boxSize, position) => {
const page = document.getElementById(`lidojs-page-${activePage}`);
if (page) {
const rect = page.getBoundingClientRect();
const p = {
x: (position.x - rect.x) / scaleRef.current,
y: (position.y - rect.y) / scaleRef.current,
};
actions.addDrawLayer(
{ path, color: penColorRef.current, width: penWidthRef.current },
{
width: boxSize.width / scaleRef.current,
height: boxSize.height / scaleRef.current,
},
p,
1 / scaleRef.current,
transparencyRef.current,
);
}
if (boxRef.current) {
boxRef.current.style.pointerEvents = 'none';
}
if (svgRef.current) {
svgRef.current.innerHTML = '';
}
},
});
useEffect(() => {
if (!window) return;
const { innerWidth: width, innerHeight: height } = window;
setSize({ width, height });
}, []);
return (
<>
onClose()}
>
{
penColorRef.current = '#0571d3';
penWidthRef.current = 5;
transparencyRef.current = 1;
}}
>
{
penColorRef.current = '#e7171f';
penWidthRef.current = 10;
transparencyRef.current = 1;
}}
>
{
penColorRef.current = '#fff234';
penWidthRef.current = 20;
transparencyRef.current = 0.8;
}}
>
{createPortal(
,
document.body,
)}
>
);
};
================================================
FILE: src/features/design/components/sidebar/FrameContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { LayerId, LayerType, SerializedLayers } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import axios from 'axios';
import { type FC, useState } from 'react';
import { isMobile } from 'react-device-detect';
import { useAsync } from 'react-use';
interface Frame {
id: string;
img: string;
clipPath: string;
width: number;
height: number;
}
export const FrameContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const [frames, setFrames] = useState ([]);
const [isLoading, setIsLoading] = useState(true);
const { actions, query } = useEditor();
useAsync(async () => {
const response = await axios.get ('/frames');
setFrames(response.data);
setIsLoading(false);
}, []);
const addFrame = async (data: Frame) => {
actions.addFrameLayer(data, data.clipPath);
if (isMobile) {
onClose();
}
};
const handleDrag = (event: React.DragEvent, frame: Frame) => {
const { clientX, clientY } = event;
const pageSize = query.getPageSize(query.activePage());
const ratio = pageSize.width / pageSize.height;
const frameRatio = frame.width / frame.height;
const scale =
ratio > frameRatio
? (pageSize.height * 0.5) / frame.height
: (pageSize.width * 0.5) / frame.width;
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Frame',
data: {
rootId: frame.id,
layers: {
[frame.id]: {
type: {
resolvedName: 'FrameLayer',
},
props: {
clipPath: frame.clipPath,
position: {
x: 0,
y: 0,
},
boxSize: {
width: frame.width * scale,
height: frame.height * scale,
},
rotate: 0,
scale,
},
locked: false,
parent: 'ROOT',
child: [],
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{isLoading &&
Loading...
}
{frames.map((item, index) => (
addFrame(item)}
onDragStart={(e) => handleDrag(e, item)}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/GraphicContent.tsx
================================================
import MagnifyingGlassIcon from '@duyank/icons/regular/MagnifyingGlass';
import XIcon from '@duyank/icons/regular/X';
import { useEventCallback } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import axios from 'axios';
import { type FC, type FormEvent, useEffect, useRef, useState } from 'react';
import { isMobile } from 'react-device-detect';
import { useAsync } from 'react-use';
import Masonry from '../../../../shared/components/masonry/Masonry';
export const GraphicContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const qRef = useRef(null);
const scrollRef = useRef(null);
const dataRef = useRef(false);
const [images, setImages] = useState<
{
id: string;
thumb: string;
downloadUrl: string;
}[]
>([]);
const [isLoading, setIsLoading] = useState(true);
const [keyword, setKeyword] = useState('');
const { actions } = useEditor();
const loadGraphicList = useEventCallback(async (offset: number) => {
dataRef.current = true;
setIsLoading(true);
const params = {
limit: '100',
offset: `${offset}`,
q: keyword,
};
const response = await axios.get<
{
id: string;
thumb: string;
downloadUrl: string;
}[]
>(`/graphics?${new URLSearchParams(params).toString()}`);
if (offset) {
setImages((prevState) => {
prevState.push(...response.data);
return prevState;
});
} else {
setImages(response.data);
}
setIsLoading(false);
if (response.data.length > 0) {
dataRef.current = false;
}
});
useAsync(async () => {
await loadGraphicList(0);
}, [loadGraphicList]);
const handleLoadMore = useEventCallback(async (e: Event) => {
const node = e.target as HTMLDivElement;
if (
node.scrollHeight - node.scrollTop - 80 <= node.clientHeight &&
!dataRef.current
) {
await loadGraphicList(images.length);
}
});
useEffect(() => {
const ele = scrollRef.current;
ele?.addEventListener('scroll', handleLoadMore);
return () => {
ele?.removeEventListener('scroll', handleLoadMore);
};
}, [handleLoadMore]);
const handleSearch = async (e: FormEvent) => {
e.preventDefault();
if (scrollRef.current) {
scrollRef.current.scrollTop = 0;
}
setKeyword(qRef.current?.value || '');
setTimeout(async () => {
await loadGraphicList(0);
});
};
const addGraphic = async (item: {
id: string;
thumb: string;
downloadUrl: string;
}) => {
const res = await axios.get(
`/graphics/download?url=${window.encodeURIComponent(item.downloadUrl)}`,
);
const file = res.data.file;
const parser = new DOMParser();
const ele = parser.parseFromString(file, 'text/xml')
.documentElement as unknown as SVGElement;
const viewBox = ele.getAttribute('viewBox')?.split(' ') || [];
const width =
viewBox.length === 4 ? +viewBox[2] : +(ele.getAttribute('width') || 100);
const height =
viewBox.length === 4 ? +viewBox[3] : +(ele.getAttribute('height') || 100);
const svgBlob = new Blob([ele.outerHTML], {
type: 'image/svg+xml;charset=utf-8',
});
const svgUrl = URL.createObjectURL(svgBlob);
actions.addSvgLayer(svgUrl, { width, height }, ele);
if (isMobile) {
onClose();
}
};
return (
{images.map((item) => (
addGraphic(item)}
>
))}
{isLoading &&
Loading...
}
);
};
================================================
FILE: src/features/design/components/sidebar/IframeContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type {
LayerId,
LayerType,
SerializedLayerTree,
SerializedLayers,
} from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import type { FC } from 'react';
import { isMobile } from 'react-device-detect';
import { iframeList } from '../../config/iframe';
export const IframeContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const { actions } = useEditor();
const addIframe = async (elements: SerializedLayerTree) => {
actions.addLayerTree(elements);
if (isMobile) {
onClose();
}
};
const handleDrag = (
event: React.DragEvent,
elements: SerializedLayerTree,
) => {
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Image',
data: elements,
};
const { clientX, clientY } = event;
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{iframeList.map((item, index) => (
addIframe(item.elements[0])}
onDragStart={(e) => handleDrag(e, item.elements[0])}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/ImageContent.tsx
================================================
import MagnifyingGlassIcon from '@duyank/icons/regular/MagnifyingGlass';
import XIcon from '@duyank/icons/regular/X';
import {
type LayerId,
type LayerType,
type SerializedLayers,
useEventCallback,
} from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import axios from 'axios';
import type React from 'react';
import { type FC, type FormEvent, useEffect, useRef, useState } from 'react';
import { isMobile } from 'react-device-detect';
import Masonry from 'react-responsive-masonry';
import { useAsync } from 'react-use';
import { Photo } from './Photo';
export const ImageContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const qRef = useRef(null);
const scrollRef = useRef(null);
const dataRef = useRef(false);
const [images, setImages] = useState<
{
id: string;
image: string;
thumb: string;
width: number;
height: number;
username: string;
name: string;
}[]
>([]);
const [isLoading, setIsLoading] = useState(true);
const [keyword, setKeyword] = useState('');
const { actions, query } = useEditor((state) => ({
dragNDrop: state.dragNDrop,
}));
const loadImageList = useEventCallback(async (offset = 0) => {
dataRef.current = true;
setIsLoading(true);
const params = {
limit: '40',
page: `${(images.length % 40) + 1}`,
q: keyword,
};
const response = await axios.get<
{
id: string;
image: string;
thumb: string;
width: number;
height: number;
username: string;
name: string;
}[]
>(`/images?${new URLSearchParams(params).toString()}`);
if (offset) {
setImages((prevState) => {
prevState.push(...response.data);
return prevState;
});
} else {
setImages(response.data);
}
setIsLoading(false);
if (response.data.length > 0) {
dataRef.current = false;
}
});
useAsync(async () => {
await loadImageList(0);
}, [loadImageList]);
useEffect(() => {
const handleLoadMore = async (e: Event) => {
const node = e.target as HTMLDivElement;
if (
node.scrollHeight - node.scrollTop - 80 <= node.clientHeight &&
!dataRef.current
) {
await loadImageList(images.length);
}
};
const ele = scrollRef.current;
ele?.addEventListener('scroll', handleLoadMore);
return () => {
ele?.removeEventListener('scroll', handleLoadMore);
};
}, [loadImageList, images]);
const handleSearch = async (e: FormEvent) => {
e.preventDefault();
if (scrollRef.current) {
scrollRef.current.scrollTop = 0;
}
setKeyword(qRef.current?.value || '');
setTimeout(async () => {
await loadImageList(0);
});
};
const addImage = async (item: {
id: string;
image: string;
thumb: string;
width: number;
height: number;
username: string;
name: string;
}) => {
actions.addImageLayer(
{ thumb: item.thumb, url: item.image },
{ width: item.width, height: item.height },
);
axios.put(`/images?id=${item.id}`);
if (isMobile) {
onClose();
}
};
const handleDrag = (
event: React.DragEvent,
item: {
id: string;
image: string;
thumb: string;
width: number;
height: number;
username: string;
name: string;
},
) => {
const { clientX, clientY } = event;
const pageSize = query.getPageSize(query.activePage());
const ratio = pageSize.width / pageSize.height;
const imgRatio = item.width / item.height;
const w =
ratio < imgRatio
? pageSize.width * 0.8
: pageSize.height * imgRatio * 0.8;
const h = w / imgRatio;
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Image',
data: {
rootId: item.id,
layers: {
[item.id]: {
type: {
resolvedName: 'ImageLayer',
},
props: {
image: {
url: item.image,
thumb: item.thumb,
boxSize: {
width: w,
height: h,
},
position: {
x: 0,
y: 0,
},
rotate: 0,
},
position: {
x: 0,
y: 0,
},
boxSize: {
width: w,
height: h,
},
rotate: 0,
},
locked: false,
parent: 'ROOT',
child: [],
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{images.map((item) => (
{
addImage(item);
}}
onDragStart={(e) => handleDrag(e, item)}
/>
))}
{isLoading &&
Loading...
}
);
};
================================================
FILE: src/features/design/components/sidebar/Photo.tsx
================================================
import { type FC, type HTMLProps, memo, useState } from 'react';
type Props = {
image: string;
name: string;
username: string;
} & HTMLProps;
export const Photo: FC = memo(({ image, name, username, ...props }) => {
const [isShow, setIsShow] = useState(false);
return (
setIsShow(false)}
onMouseOver={() => setIsShow(true)}
>
Photo by
{name}
on
unsplash
);
});
================================================
FILE: src/features/design/components/sidebar/QrCodeContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type {
LayerId,
LayerType,
SerializedLayerTree,
SerializedLayers,
} from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import type { FC } from 'react';
import { isMobile } from 'react-device-detect';
import { qrCodeList } from '../../config/qrCode';
export const QrCodeContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const { actions } = useEditor();
const addQrCode = async (elements: SerializedLayerTree) => {
actions.addLayerTree(elements);
if (isMobile) {
onClose();
}
};
const handleDrag = (
event: React.DragEvent,
elements: SerializedLayerTree,
) => {
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Image',
data: elements,
};
const { clientX, clientY } = event;
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{qrCodeList.map((item, index) => (
addQrCode(item.elements[0])}
onDragStart={(e) => handleDrag(e, item.elements[0])}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/ShapeContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { LayerId, LayerType, SerializedLayers } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import type { FC } from 'react';
import { isMobile } from 'react-device-detect';
import { v4 } from 'uuid';
import { type Line, lines } from '../../config/line';
import { type Shape, shapes } from '../../config/shape';
export const ShapeContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const { actions, query } = useEditor();
const addLine = (props: Line['props']) => {
actions.addLineLayer({ props });
};
const addShape = (shape: Shape) => {
actions.addShapeLayer({
type: {
resolvedName: 'ShapeLayer',
},
props: {
shape: shape.type,
position: {
x: 0,
y: 400,
},
boxSize: {
width: shape.width,
height: shape.height,
},
rotate: 0,
color: '#5E6278',
},
});
if (isMobile) {
onClose();
}
};
const handleDrag = (event: React.DragEvent, shape: Shape) => {
const { clientX, clientY } = event;
const id = v4();
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Shape',
data: {
rootId: id,
layers: {
[id]: {
type: {
resolvedName: 'ShapeLayer',
},
locked: false,
parent: 'ROOT',
child: [],
props: {
shape: shape.type,
position: {
x: 0,
y: 400,
},
boxSize: {
width: shape.width,
height: shape.height,
},
rotate: 0,
color: '#5E6278',
},
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
const handleDragLine = (event: React.DragEvent, line: Line) => {
const { clientX, clientY } = event;
const width = query.getPageSize(query.activePage()).width / 2;
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Line',
data: {
rootId: line.id,
layers: {
[line.id]: {
props: {
...line.props,
boxSize: {
width,
height: 4,
},
position: {
x: 0,
y: 0,
},
style: 'solid',
color: 'rgb(0, 0, 0)',
scale: 1,
rotate: 0,
},
type: {
resolvedName: 'LineLayer',
},
locked: false,
parent: 'ROOT',
child: [],
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{lines.map((l, idx) => (
addLine(l.props)}
onDragStart={(e) => handleDragLine(e, l)}
>
{l.icon}
))}
Shape
{shapes.map((shape) => (
addShape(shape)}
onDragStart={(e) => handleDrag(e, shape)}
>
{shape.icon}
))}
);
};
================================================
FILE: src/features/design/components/sidebar/Sidebar.tsx
================================================
import BrowserIcon from '@duyank/icons/regular/Browser';
import FrameCornersIcon from '@duyank/icons/regular/FrameCorners';
import ImageIcon from '@duyank/icons/regular/Image';
import LayoutIcon from '@duyank/icons/regular/Layout';
import PencilIcon from '@duyank/icons/regular/Pencil';
import PiggyBankIcon from '@duyank/icons/regular/PiggyBank';
import QrCodeIcon from '@duyank/icons/regular/QrCode';
import SquareIcon from '@duyank/icons/regular/Square';
import TableIcon from '@duyank/icons/regular/Table';
import TextTIcon from '@duyank/icons/regular/TextT';
import UploadIcon from '@duyank/icons/regular/Upload';
import VideoIcon from '@duyank/icons/regular/Video';
import { useEditor } from '@lidojs/design-editor';
import { useCallback, useState } from 'react';
import { SidebarTab } from '../tabs';
import { DrawContent } from './DrawContent';
import { FrameContent } from './FrameContent';
import { GraphicContent } from './GraphicContent';
import { IframeContent } from './IframeContent';
import { ImageContent } from './ImageContent';
import { QrCodeContent } from './QrCodeContent';
import { ShapeContent } from './ShapeContent';
import { TableContent } from './TableContent';
import { TemplateContent } from './TemplateContent';
import { TextContent } from './TextContent';
import { UploadContent } from './UploadContent';
import { VideoContent } from './VideoContent';
const tabs = [
{
name: 'Template',
icon: ,
},
{
name: 'Text',
icon: ,
},
{
name: 'Shape',
icon: ,
},
{
name: 'Table',
icon: ,
isBusiness: true,
},
{
name: 'Frame',
icon: ,
},
{
name: 'Image',
icon: ,
},
{
name: 'Graphic',
icon: ,
},
{
name: 'QrCode',
icon: ,
isBusiness: true,
},
{
name: 'Widgets',
icon: ,
},
{
name: 'Draw',
icon: ,
isBusiness: true,
},
{
name: 'Video',
icon: ,
},
{
name: 'Upload',
icon: ,
},
];
export const Sidebar = () => {
const { actions } = useEditor();
const [tab, setTab] = useState('Template');
const handleCloseTab = useCallback(() => {
setTab(null);
actions.setSidebar();
}, [actions]);
return (
{
actions.setSidebar();
setTab(tab);
}}
/>
{tab && (
{tab === 'Template' && (
{
setTab(null);
actions.setSidebar();
}}
/>
)}
{tab === 'Text' && }
{tab === 'Frame' && }
{tab === 'Image' && }
{tab === 'Graphic' && }
{tab === 'QrCode' && }
{tab === 'Widgets' && }
{tab === 'Shape' && }
{tab === 'Table' && }
{tab === 'Video' && }
{tab === 'Draw' && }
)}
);
};
================================================
FILE: src/features/design/components/sidebar/TableContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { LayerId, LayerType, SerializedLayers } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import type { FC } from 'react';
import { isMobile } from 'react-device-detect';
import { v4 } from 'uuid';
const tableLayer = {
type: {
resolvedName: 'TableLayer',
},
props: {
position: {
x: 458.2781364561637,
y: 229.60681114551085,
},
boxSize: {
width: 838.5314463859182,
height: 282,
x: 344.41332869685516,
y: 226.56694426649582,
},
rotate: 0,
scale: 1,
format: {
cellSpacing: 0,
cellPadding: 10,
rowHeight: [100, 120, 180, 202.38026124818578],
colWidth: [400, 400, 300, 252.3802612481859],
rows: [
{
index: 1,
height: 70,
},
{
index: 2,
height: 70,
},
{
index: 3,
height: 70,
},
{
index: 4,
height: 70,
},
],
columns: [
{
index: 1,
width: 226.64958360025628,
},
{
index: 2,
width: 209.83984625240237,
},
{
index: 3,
width: 200.19218449711718,
},
{
index: 4,
width: 199.8498320361424,
},
],
},
cells: [
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(84, 84, 84)',
fontFamily: 'Acme',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(84, 84, 84)',
},
},
],
text: 'Header 1',
},
],
},
],
},
row: 1,
col: 1,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(84, 84, 84)',
fontFamily: 'Acme',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(84, 84, 84)',
},
},
],
text: 'Header 1',
},
],
},
],
},
row: 1,
col: 2,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(84, 84, 84)',
fontFamily: 'Acme',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(84, 84, 84)',
},
},
],
text: 'Header 3',
},
],
},
],
},
row: 1,
col: 3,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(84, 84, 84)',
fontFamily: 'Acme',
fontSize: '18px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'bold',
},
{
type: 'color',
attrs: {
color: 'rgb(84, 84, 84)',
},
},
],
text: 'Header 4',
},
],
},
],
},
row: 1,
col: 4,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'color',
attrs: {
color: 'rgb(0, 0, 0)',
},
},
],
text: 'Content For Column 1',
},
],
},
],
},
row: 2,
col: 1,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(228, 5, 5)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 2',
},
],
},
],
},
row: 2,
col: 2,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(96, 25, 211)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{
type: 'color',
attrs: {
color: 'rgb(0, 0, 0)',
},
},
],
text: 'Content For Column 3',
},
],
},
],
},
row: 2,
col: 3,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
row: 2,
col: 4,
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 4',
},
],
},
],
},
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
row: 3,
col: 3,
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 3',
},
],
},
],
},
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
row: 3,
col: 4,
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 4',
},
],
},
],
},
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 1',
},
],
},
],
},
row: 3,
col: 1,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 2',
},
],
},
],
},
row: 3,
col: 2,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 1',
},
],
},
],
},
col: 1,
row: 4,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 2,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
row: 4,
col: 2,
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 2',
},
],
},
],
},
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 2,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
row: 4,
col: 3,
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 3',
},
],
},
],
},
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 2,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
{
value: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(0, 0, 0)',
fontFamily: 'Akatab',
fontSize: '10px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: 'uppercase',
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
text: 'Content For Column 4',
},
],
},
],
},
col: 4,
row: 4,
background: 'rgb(255,255,255)',
border: {
top: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
left: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
right: {
width: 1,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
bottom: {
width: 2,
color: 'rgb(0, 0, 0)',
style: 'solid',
},
},
},
],
fonts: [
{
name: 'Acme',
fonts: [
{
urls: [
'https://fonts.gstatic.com/s/acme/v25/RrQfboBx-C5_bx3Lb23lzLk.ttf',
],
},
],
},
{
name: 'Akatab',
fonts: [
{
style: 'Bold',
urls: [
'https://fonts.gstatic.com/s/akatab/v7/VuJzdNrK3Z7gqJE3gKLdPKNiaRpFvg.ttf',
],
},
{
urls: [
'https://fonts.gstatic.com/s/akatab/v7/VuJwdNrK3Z7gqJEPWIz5NIh-YA.ttf',
],
},
],
},
],
},
};
export const TableContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const { actions } = useEditor();
const addTable = () => {
actions.addLayer(tableLayer);
if (isMobile) {
onClose();
}
};
const handleDrag = (event: React.DragEvent) => {
const { clientX, clientY } = event;
const id = v4();
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Table',
data: {
rootId: id,
layers: {
[id]: {
...tableLayer,
locked: false,
parent: 'ROOT',
child: [],
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
);
};
================================================
FILE: src/features/design/components/sidebar/TemplateContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { SerializedPage } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import axios from 'axios';
import { type FC, useState } from 'react';
import { isMobile } from 'react-device-detect';
import { useAsync } from 'react-use';
interface Template {
img: string;
elements: SerializedPage;
}
export const TemplateContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const [templates, setTemplates] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const { actions, activePage } = useEditor((state) => ({
activePage: state.activePage,
}));
useAsync(async () => {
const response = await axios.get('/templates');
setTemplates(response.data);
setIsLoading(false);
}, []);
const addPage = async (data: SerializedPage) => {
actions.setPage(activePage, data);
if (isMobile) {
onClose();
}
};
return (
{isLoading &&
Loading...
}
{templates.map((item, index) => (
addPage(item.elements)}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/TextContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { LayerId, SerializedLayers } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import axios from 'axios';
import { type FC, useState } from 'react';
import { isMobile } from 'react-device-detect';
import { useAsync } from 'react-use';
import {
addABodyText,
addAHeading,
addASubheading,
} from '../../../../constant/text-effects';
import { getThumbnail } from '../../../../utils/thumbnail';
interface Text {
img: string;
elements: {
rootId: LayerId;
layers: SerializedLayers;
};
}
export const TextContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const { actions } = useEditor();
const [texts, setTexts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useAsync(async () => {
const response = await axios.get('/texts');
setTexts(response.data);
setIsLoading(false);
}, []);
const handleAddText = (data: {
rootId: LayerId;
layers: SerializedLayers;
}) => {
actions.addTextLayer(data);
if (isMobile) {
onClose();
}
};
const handleDrag = (
event: React.DragEvent,
data: { rootId: LayerId; layers: SerializedLayers },
) => {
const { clientX, clientY } = event;
actions.startDragNDrop({ layer: 'Text', data }, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData(
'text/plain',
JSON.stringify({ layer: 'Text', data }),
);
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
handleAddText(addAHeading)}
onDragStart={(e) => handleDrag(e, addAHeading)}
>
Add a heading
handleAddText(addASubheading)}
onDragStart={(e) => handleDrag(e, addASubheading)}
>
Add a subheading
handleAddText(addABodyText)}
onDragStart={(e) => handleDrag(e, addABodyText)}
>
Add a little bit of body text
{isLoading &&
Loading...
}
{texts.map(({ img, elements }, idx) => (
handleAddText(elements)}
onDragStart={(e) => handleDrag(e, elements)}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/UploadContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import { useEditor } from '@lidojs/design-editor';
import { fetchSvgContent } from '@lidojs/design-utils';
import { type ChangeEvent, type FC, useRef, useState } from 'react';
import { isMobile } from 'react-device-detect';
interface UploadContentProps {
visibility: boolean;
onClose: () => void;
}
export const UploadContent: FC = ({
visibility,
onClose,
}) => {
const inputFileRef = useRef(null);
const { actions } = useEditor();
const [images, setImages] = useState<
{ url: string; type: 'svg' | 'image' }[]
>([]);
const addImage = async (url: string) => {
if (!window) return;
const img = new Image();
img.onerror = (err) => window.alert(err);
img.src = url;
img.crossOrigin = 'anonymous';
img.onload = () => {
actions.addImageLayer(
{ url, thumb: url },
{ width: img.naturalWidth, height: img.naturalHeight },
);
if (isMobile) {
onClose();
}
};
};
const addSvg = async (url: string) => {
const ele = await fetchSvgContent(url);
const viewBox = ele.getAttribute('viewBox')?.split(' ') || [];
const width =
viewBox.length === 4 ? +viewBox[2] : +(ele.getAttribute('width') || 100);
const height =
viewBox.length === 4 ? +viewBox[3] : +(ele.getAttribute('height') || 100);
actions.addSvgLayer(url, { width, height }, ele);
if (isMobile) {
onClose();
}
};
const handleUpload = (e: ChangeEvent) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setImages((prevState) => {
return prevState.concat([
{
url: reader.result as string,
type: file.type === 'image/svg+xml' ? 'svg' : 'image',
},
]);
});
};
reader.readAsDataURL(file);
}
};
return (
inputFileRef.current?.click()}
>
Upload
{images.map((item, idx) => (
item.type === 'image' ? addImage(item.url) : addSvg(item.url)
}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/VideoContent.tsx
================================================
import XIcon from '@duyank/icons/regular/X';
import type { LayerId, LayerType, SerializedLayers } from '@lidojs/design-core';
import { useEditor } from '@lidojs/design-editor';
import { type FC, useState } from 'react';
import { isMobile } from 'react-device-detect';
import { useAsync } from 'react-use';
import { v4 } from 'uuid';
export const VideoContent: FC<{ onClose: () => void }> = ({ onClose }) => {
const [videos] = useState<
{ img: string; url: string; width: number; height: number }[]
>([
{
img: 'https://template.canva.com/EAFaarkqz_0/2/0/400w-IVVQCZOr1K4.jpg',
url: 'https://template.canva.com/EAFaarkqz_0/2/0/400w-xadNArxL6gA.mp4',
width: 400,
height: 334,
},
]);
const [isLoading] = useState(false);
const { actions, query } = useEditor();
useAsync(async () => {
//const response = await axios.get<{ img: string; url: string; width: number; height: number }[]>('/videos');
//setVideos(response.data);
//setIsLoading(false);
}, []);
const addVideo = ({
url,
width,
height,
}: {
url: string;
width: number;
height: number;
}) => {
actions.addVideoLayer({ url }, { width, height });
if (isMobile) {
onClose();
}
};
const handleDrag = (
event: React.DragEvent,
{ url, width, height }: (typeof videos)[number],
) => {
const { clientX, clientY } = event;
const pageSize = query.getPageSize(query.activePage());
const ratio = pageSize.width / pageSize.height;
const imgRatio = width / height;
const w =
ratio < imgRatio
? pageSize.width * 0.4
: pageSize.height * imgRatio * 0.4;
const h = w / imgRatio;
const id: LayerId = v4();
const data: {
layer: LayerType;
data: { rootId: LayerId; layers: SerializedLayers };
} = {
layer: 'Video',
data: {
rootId: id,
layers: {
[id]: {
type: {
resolvedName: 'VideoLayer',
},
props: {
video: {
url: url,
boxSize: {
width: w,
height: h,
},
position: {
x: 0,
y: 0,
},
rotate: 0,
},
position: {
x: 0,
y: 0,
},
boxSize: {
width: w,
height: h,
},
rotate: 0,
},
locked: false,
parent: 'ROOT',
child: [],
},
},
},
};
actions.startDragNDrop(data, { x: clientX, y: clientY });
event.dataTransfer.clearData('text/plain');
event.dataTransfer.setData('text/plain', JSON.stringify(data));
event.dataTransfer.setDragImage(new Image(), 0, 0);
};
return (
{isLoading &&
Loading...
}
{videos.map((item, idx) => (
addVideo(item)}
draggable={true}
onDragStart={(e) => handleDrag(e, item)}
>
))}
);
};
================================================
FILE: src/features/design/components/sidebar/index.ts
================================================
export * from './Sidebar';
================================================
FILE: src/features/design/components/tabs/TabList.tsx
================================================
import type { FC, ReactNode } from 'react';
interface SidebarTabProps {
tabs: {
name: string;
icon: ReactNode;
isBusiness?: boolean;
}[];
active: string | null;
onChange: (e: React.MouseEvent, tab: string) => void;
}
export const SidebarTab: FC = ({ tabs, active, onChange }) => {
const activeIdx = tabs.findIndex((tab) => tab.name === active);
return (
{activeIdx >= 0 && (
)}
{tabs.map((tab, idx) => (
onChange(e, tab.name)}
>
{tab.icon}
{tab.name}
{tab.isBusiness && (
Business
)}
))}
);
};
================================================
FILE: src/features/design/components/tabs/index.ts
================================================
export * from './TabList';
================================================
FILE: src/features/design/config/iframe.tsx
================================================
import type { LayerId, SerializedLayers } from '@lidojs/design-core';
export type IframeItem = {
elements: [
{
rootId: LayerId;
layers: SerializedLayers;
},
];
img: string;
};
export const iframeList: IframeItem[] = [
{
elements: [
{
rootId: '3f39efa2-4017-4c77-b3a9-c98456c629f0',
layers: {
'3f39efa2-4017-4c77-b3a9-c98456c629f0': {
type: { resolvedName: 'IframeLayer' },
props: {
url: 'https://api.wo-cloud.com/content/widget/?geoObjectKey=6112695&language=en®ion=US&timeFormat=HH:mm&windUnit=mph&systemOfMeasurement=imperial&temperatureUnit=fahrenheit',
position: { x: 45.586770981507925, y: 121.96449211646916 },
boxSize: {
width: 350.8264580369844,
height: 350.8264580369844,
},
rotate: 0,
scale: 1,
},
locked: false,
child: [],
parent: 'ROOT',
},
},
},
],
img: '/assets/images/weather/1.png',
},
];
================================================
FILE: src/features/design/config/line.tsx
================================================
import type { LayerId } from '@lidojs/design-core';
import type { DeepPartial, LineLayerProps } from '@lidojs/design-editor';
import type { ReactElement } from 'react';
import { v4 } from 'uuid';
export type Line = {
id: LayerId;
props: DeepPartial;
icon: ReactElement;
};
export const lines: Line[] = [
{
id: v4(),
props: {
style: 'solid',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'shortDashes',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'dots',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'bar',
arrowEnd: 'bar',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'dots',
arrowStart: 'none',
arrowEnd: 'arrow',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'arrow',
arrowEnd: 'arrow',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'outlineDiamond',
arrowEnd: 'outlineDiamond',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'diamond',
arrowEnd: 'diamond',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'none',
arrowEnd: 'arrow',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'none',
arrowEnd: 'triangle',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'circle',
arrowEnd: 'circle',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'square',
arrowEnd: 'square',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'outlineSquare',
arrowEnd: 'outlineSquare',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'dots',
arrowStart: 'triangle',
arrowEnd: 'triangle',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
{
id: v4(),
props: {
style: 'solid',
arrowStart: 'outlineCircle',
arrowEnd: 'outlineCircle',
boxSize: {
height: 4,
},
color: 'rgb(94, 98, 120)',
},
icon: (
),
},
];
================================================
FILE: src/features/design/config/qrCode.tsx
================================================
import type { LayerId, SerializedLayers } from '@lidojs/design-core';
export type QrCodeItem = {
elements: [
{
rootId: LayerId;
layers: SerializedLayers;
},
];
img: string;
};
export const qrCodeList: QrCodeItem[] = [
{
elements: [
{
rootId: '3f39efa2-4017-4c77-b3a9-c98456c629f0',
layers: {
'3f39efa2-4017-4c77-b3a9-c98456c629f0': {
type: { resolvedName: 'QrCodeLayer' },
props: {
text: 'https://lidojs.com',
position: { x: 45.586770981507925, y: 121.96449211646916 },
boxSize: {
width: 350.8264580369844,
height: 350.8264580369844,
},
rotate: 0,
bgColor: 'rgb(255, 255, 255)',
textColor: 'rgb(30, 30, 45)',
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAYAAAB/HSuDAAAACXBIWXMAAC4jAAAuIwF4pT92AABbQ0lEQVR4nO3defzVc/7//8f73UJ7qBSpLNWEZBlqjKWyFJEYYxnrxzKYGR/MMGMZzAyGMZbMxzbMIDvjVyGERGRG2cmSCElpIS1apN6/P2bM12c+ltQ553nOeV6vl4t/Phc9X3cfb03nds55vWrq6urqAgAAAKhqtakHAAAAAMUnAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIQP3UA4CV8/7778cf//jH1DOK5sgjj4zu3bunngEAAFVDAIAKNWvWrLjssstSzyia3r17CwAAAFBAvgIAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyED91AMAAAAKZenSpTF58uR48803Y+rUqTF9+vSYPn16zJo1K+bOnfvvv5YuXRrLli2L+fPn//vXNm7cOBo2bBgREY0aNYpmzZr9+68111wzWrduHW3atIl27dpFmzZtolOnTtGxY8do0KBBqn9c+FYEAAAAoCJ98MEHMX78+HjhhRfi2WefjQkTJsS7774by5YtW6nz5s6d+61/TW1tbay33nqxwQYbRLdu3WKzzTaLzTbbLDbddNNo1qzZSu2AYhEAqshVV10VS5YsST2j4DbeeOPYddddU88AIuLee++Nt956K/WMotlwww1jzz33TD0DKIHBgwennlA0xx13XKy22mqpZxTFhx9+GCNHjoxHH300xowZE2+++WbqSbF8+fJ499134913341HH3303//3mpqa6NatW3z/+9//918bbbRRwqUQUVNXV1eXegSF0bJly5WqluXusMMOixtuuCH1jLLzwgsvxBZbbJF6RtEMGzYsBg0alHoG/2HQoEFx9913p55RNHvttVcMHz489QygBGpqalJPKJo5c+ZEy5YtU88omClTpsTtt98e9957b/z973+P5cuXp5600tZff/3Yfffdo3///rHTTjtFo0aNUk8iMz4BAAAAlJWFCxfGbbfdFjfddFM8/vjjUS3vWb799ttxxRVXxBVXXBFNmjSJPffcM370ox/FrrvuWrWf2qC8eAoAAABQFiZPnhw///nPY911142jjjoqxowZUzUv/v/TJ598ErfffnsMHDgw2rVrFyeddFK88cYbqWdR5QQAAAAgqYkTJ8bhhx8eXbp0iUsvvTQ+/vjj1JNKas6cOTF48ODo2rVr7LLLLjFy5MjUk6hSAgAAAJDE+++/H4cffnh069YthgwZstJ3768mo0aNit122y169uwZw4cPr9pPQJCGAAAAAJTU4sWL45xzzokuXbrEkCFDvMj9EuPHj4+99947tttuuxg/fnzqOVQJAQAAACiZJ598MjbffPM466yzYuHChannlL2///3v0bNnzzj44INj1qxZqedQ4QQAAACg6JYsWRK/+MUvYvvtt4+JEyemnlNxbrnllujWrVvccsstqadQwQQAAACgqN58883Ydttt45JLLvFx/1Xw4YcfxsEHHxw/+MEPYs6cOannUIEEAAAAoGjuu+++2HLLLeO5555LPaVqDB06NL773e/Gs88+m3oKFUYAAAAAiuLiiy+OgQMHxvz581NPqTqTJ0+O73//+3HrrbemnkIFEQAAAICCqqurixNOOCFOPvnkWL58eeo5VWvJkiVx0EEHxQUXXJB6ChVCAAAAAApm2bJlceSRR8af/vSn1FOycdppp8Xxxx/v/gp8IwEAAAAoiLq6ujj88MPj+uuvTz0lO5dffnmceuqpqWdQ5gQAAACgIH72s5/FzTffnHpGti688MI444wzUs+gjAkAAADAKvvd734XV155ZeoZ2fv9738f11xzTeoZlCkBAAAAWCV33HFHnH322aln8C8//elP45FHHkk9gzIkAAAAACvtmWeeif/6r/9KPYMv+Oyzz+KHP/xhvPfee6mnUGYEAAAAYKXMnTs39t9//1i0aFHqKfyHOXPmxIEHHhifffZZ6imUEQEAAABYKUcddVRMnjw59Qy+wpNPPhm/+93vUs+gjAgAAADAt3bDDTfEXXfdlXoG3+D3v/99PPfcc6lnUCYEAAAA4Fv54IMP4sQTT0w9gxWwbNmyOPLII30VgIgQAAAAgG/puOOOi7lz56aewQp64YUX4pJLLkk9gzIgAAAAACts5MiRMXz48NQz+JbOPffcmDFjRuoZJCYAAAAAK+Szzz6Lk046KfUMVsL8+fPj17/+deoZJFY/9QBg5ay55ppx2GGHpZ5RNB06dEg9AQD4D1deeWW8/vrrqWewkv7617/GSSedFBtvvHHqKSQiAECF6tChQ9xwww2pZwAAmVi0aFGcf/75qWewCurq6uJ3v/td3H777amnkIivAAAAAN/oz3/+c3zwwQepZ7CK7rzzznj11VdTzyARAQAAAPhaixcvjvPOOy/1DAqgrq7Ov8uMCQAAAMDXuvnmm2P27NmpZ1Agd955Z7z//vupZ5CAAAAAAHylurq6GDx4cOoZFNBnn30WV1xxReoZJCAAAAAAX2n06NHxyiuvpJ5Bgf35z3+OxYsXp55BiQkAAADAV/rLX/6SegJF8NFHH8Xw4cNTz6DEBAAAAOBLzZkzJ4YNG5Z6BkVy3XXXpZ5AiQkAAADAl7r11ltjyZIlqWdQJKNGjYopU6aknkEJCQAAAMCXuvPOO1NPoIjq6ur8O86MAAAAAPwfM2fOjLFjx6aeQZHdddddqSdQQvVTDwDIxfLly+Pdd9+Nt99+O955552YMWNGfPTRR/HRRx/FsmXL4uOPP46IiNVWWy0aNWoU9erVi2bNmkWrVq2idevW0aZNm1h33XWjS5cu0bJly6T/LPC5uXPnxrRp0+L999+PGTNmxIcffhhz5879919Lly6Nurq6mDt37r9/TZMmTaJBgwYREdGyZcto0aLFv/9q165dtGvXLtZZZ51o06ZN1NTUpPpHg+wNHTo0li9fnnoGRTZu3LiYMmVKdOjQIfUUSkAAACiSmTNnxuOPPx6PPfZYPPvss/Hyyy/HJ598UpCz11577fjOd74TW265ZWy33Xax3XbbRZs2bQpyNnyZyZMnx/PPPx8vvfRSvPnmmzFx4sSYNGlSzJs3r2jXbNCgQWywwQbRtWvX2GijjWLjjTeOLbbYIjbddNNo2LBh0a4L/NOIESNST6BEhg4dGieeeGLqGZSAAAAVatGiRTFx4sTUM4pm/fXXjxYtWqSe8a299957ceutt8bw4cNj3LhxUVdXV5TrzJgxI2bMmBFjxoyJSy+9NCIiNt5449hnn31in332iS222KIo1yUPixcvjqeeeirGjBkTY8eOjaeffvp/vYNfKkuXLo2JEyf+n9/r6tevH927d49tt902dtxxx9h+++2jbdu2Jd8H1WzJkiXx6KOPpp5BiTzwwAMCQCYEAKhQEydOrOoXecOGDYtBgwalnrFC6urq4oEHHoj/+Z//iQcffLBoL/q/yauvvhqvvvpqnHvuudG5c+f46U9/GkcccUQ0a9YsyR4qy9tvvx333ntvjBgxIh5//PGyvuv3Z599Fs8//3w8//zzccUVV0RExCabbBIDBgyIPfbYI7bddtuoV69e4pVQ2caOHRsLFy5MPYMSGTNmTCxatCgaNWqUegpF5iaAAKtg+PDhsfnmm8eAAQNi5MiRyV78/6dJkybFiSeeGOuuu2788pe//Pf9BeCL3nvvvbjwwgtj8803jw022CBOOOGEePjhh8v6xf9XeeWVV+LCCy+MHXbYIdq0aRPHHntsjB07tmz+m4RKM2rUqNQTKKElS5bEY489lnoGJSAAAKyECRMmxI477hh77713vPTSS6nnfKX58+fHH//4x9hwww3jsssui88++yz1JBL77LPP4q677oq+fftGx44d41e/+lW8+OKLqWcV1EcffRR//vOfY/vtt49OnTrFueeeGx988EHqWVBRnnzyydQTKLFHHnkk9QRKQAAA+BaWLVsW55xzTmy11Vbx+OOPp56zwj766KM48cQTo1evXvHqq6+mnkMCc+bMiXPOOSc6duwYP/zhD+PRRx/N4t3xKVOmxJlnnhkdOnSIAw44IJ555pnUk6DsffrppzF+/PjUMyixSvpzDStPAABYQR988EHsvPPOcdZZZ8Wnn36aes5KefbZZ2PrrbeOm2++OfUUSmTGjBlx6qmnxnrrrRdnnXVWTJs2LfWkJJYuXRp33HFHbL311tG/f/8YM2ZM6klQtp555pmK/CoQq+a5556LBQsWpJ5BkQkAACvg5Zdfjq233roqvh+3cOHCOOSQQ+LMM8/M4h3gXC1YsCDOPvvs2GCDDeIPf/hDwR5BWQ0efPDB6N27d/Tr16+sv8IDqTz33HOpJ5DAsmXL4qmnnko9gyITAAC+wdixY2O77baLqVOnpp5SUOeee24cdthhsWzZstRTKKC6urr461//Gp07d47f/e537uL9NR566KHYfPPN44gjjoiZM2emngNl4/nnn089gUTGjRuXegJF5jGAAF9j3LhxMWDAgJg3b17qKUVx0003xbJly+LGG2/02LQq8Nprr8WPf/zjGDt2bOopFaOuri6uv/76GD58eFx44YVx5JFHRk1NTepZkFQuAaBt27ax4447Rvfu3aNTp07RpEmTiPjnPRDee++9ePHFF2P06NHx/vvvJ15aOs8++2zqCRSZAADwFSZOnBj9+vWr2hf/n7v11lujtrY2brzxRi98KtSyZcvi/PPPj3POOadi70+R2pw5c+Loo4+Om266KYYMGRKdOnVKPQmSWLZsWbzyyiupZxTV7rvvHieffHLsuOOOUVv79R+IrqurizFjxsR5552XxaMR3Si1+vkKAMCXmDNnTgwcODDmzp2bekpJ3HzzzXHGGWeknsFKeOedd6J3795x5plnevFfAI8//nj06NEjbr311tRTIIl33nmnan8vadGiRQwdOjTuu+++6NOnzze++I+IqKmpid69e8fDDz8ct912WzRt2rQES9N57733YtasWalnUEQCAMCXOPzww+ONN95IPaOkzj///LjuuutSz+BbuOeee6JHjx4+8l9g8+bNi4MOOij+67/+KxYvXpx6DpTUxIkTU08oipYtW8YTTzwRe++990qfccABB8SYMWOiefPmBVxWfl5++eXUEygiAQDgP1x99dVxzz33pJ6RxHHHHef7fxWgrq4ufvOb38Ree+1V9V9RSemGG26I7bffPt57773UU6BkqjV+33rrrdG9e/dVPmfLLbeMu+66qwCLyle1fwUkdwIAwBe89957ccopp6Sekcynn34a++23XzZffahECxcujB/84Afx29/+NvWULDzzzDPx3e9+152xycZbb72VekLBHXHEEbHbbrsV7LxddtkljjzyyIKdV25ef/311BMoIgEA4AtOOOGEWLBgQeoZSU2ePDlOOOGE1DP4EnPmzIldd901hg0blnpKVmbOnBl9+vSJ+++/P/UUKLpqe+RtgwYN4uyzzy74uWeeeeYK3UOgEr322mupJ1BE1flTC7ASRo8e7YXVvwwZMiQefPDB1DP4gqlTp8Z2220XTz75ZOopWVq0aFEMHDgwbrnlltRToKimTJmSekJBDRo0KDp06FDwczt27Bh9+/Yt+LnloFrvA8E/CQAA8c/vVP/yl79MPaOsHH300fHJJ5+knkH888V/796949VXX009JWvLli2LQw89VASgqlXbJwD233//op3dr1+/op2d0rRp02LJkiWpZ1AkAgBARNx9991ufvcf3nvvvfjDH/6Qekb2pk2bFr17967K7+VWouXLl4sAVK1ly5bFzJkzU88oqB133LFoZ2+11VZFOzu1d999N/UEikQAALJXV1fnhmpf4aKLLqq6d4Mqydy5c2O33Xbz4r/MfB4BRowYkXoKFNSHH36YekJBrbPOOtGqVauind++ffuinZ3a22+/nXoCRSIAANm7//7744UXXkg9oywtWrQozjzzzNQzsvTpp5/GPvvsEy+99FLqKXyJ5cuXx3777Rf/+Mc/Uk+Bgqm2AFCM7/5/0ZprrlnU81MSAKqXAABkb/DgwaknlLWbbrop3nzzzdQzsnPEEUfE6NGjU8/ga3x+Y8DJkyenngIFMXv27NQTCmqNNdYo6vn16tUr6vkpTZ8+PfUEikQAALI2YcKEGDVqVOoZZW3ZsmVx0UUXpZ6RlYsvvth3zCvE7NmzY9CgQW6YSVX46KOPUk8oqIYNG6aeULE++OCD1BMoEgEAyNq1116bekJFuO6662LatGmpZ2ThkUce8USKCvPyyy/HEUccEXV1damnwCqptpA1b9681BMqlk8AVC8BAMjW4sWL46abbko9oyIsXbo0rrnmmtQzqt706dPjwAMPjOXLl6eewrd05513xhVXXJF6BqyShQsXpp5QUNX2lYZSmjFjRuoJFIkAAGRrxIgRMWfOnNQzKsY111wTS5cuTT2jatXV1cXhhx8es2bNSj2FlXTyySfHhAkTUs+AlbZgwYLUEwrqnXfe8cmclVRtj4Pk/xEAgGzdeuutqSdUlOnTp8djjz2WekbVGjx4cDz00EOpZ7AKlixZEgceeGAsWbIk9RRYKfPnz089oaDmz5/vMaorqdruB8H/IwAAWVqwYEHcd999qWdUnGr7eGi5ePPNN+OMM85IPYMCmDBhQpx77rmpZ8BKWbZsWeoJBff888+nnlCR5s2b5+toVUoAALL0wAMPxKeffpp6BkRdXV0cc8wxsWjRotRTKJALLrjAVwGgTPz9739PPaFi+ZpkdRIAgCzdfffdqSdAREQMGTIkRo8enXoGBfTZZ5/FUUcd5bvHUAb87/3K+/jjj1NPoAgEACA7y5cvjwcffDD1DIgFCxbEaaedlnoGRTBu3Li45ZZbUs+A7L399ts+kbOSqu2eEPyTAABk5/nnn/doIMrC+eefHx988EHqGRTJqaee6r4ZUAb+9re/pZ5Qkfz+VZ0EACA7Dz/8cOoJEFOmTIlLLrkk9QyK6P3334+LLroo9QxYYbW11fnS4Nprr43PPvss9YyK415J1ak6/ysH+Bpjx45NPQHi97//fSxevDj1DIrskksu8T1aKkbz5s1TTyiK6dOnx/Dhw1PPqDhz585NPYEiEACArCxfvtwdgUluypQpcd1116WeQQnMnTs3Bg8enHoGrJBq/QRARMSf/vSn1BMqjk8AVKfq/a8c4EtMmjTJY21I7g9/+EMsXbo09QxKZPDgwbFgwYLUM+AbtWrVKvWEonniiSfiscceSz2jonzyySepJ1AEAgCQlRdeeCH1BDI3Z86cGDJkSOoZlNDcuXPj+uuvTz0DvtFaa62VekJRnXbaaR7PSfYEACArL774YuoJZO4vf/mLd1UydNlll8Xy5ctTz4CvVe0B4KmnnhLjyJ4AAGTFJwBIafny5XH55ZennkECb731Vtx///2pZ8DXatu2beoJRffLX/7S41fJWv3UAwBKSQAgpYceeiimTJmSegaJ/OUvf4k99tgj9Qz4Sm3bto369etX9SPzPvzwwzj66KPj3nvvXeWz6tWrFz169CjAqvLUsmXL1BMoAgEAyMbs2bNj+vTpqWeQsRtuuCH1BBK67777YubMmdGmTZvUU+BL1a9fPzp06BCTJ09OPaWoRowYEZdddlmccMIJq3ROs2bNvLFAxfEVACAbb775ZuoJZGzOnDkxbNiw1DNI6LPPPotbbrkl9Qz4WhtssEHqCSVxyimnxLhx41LPgJLzCQAgG++8807qCck0adIkdtppp9hiiy2ic+fO0bx582jcuHHMmTMnpk2bFk8//XQ89NBDMXPmzNRTq9bw4cOze6Zy+/bto3///rHZZpvFeuutFy1atIgFCxbErFmz4pVXXolHHnkkuxtz3nHHHXHSSSelngFfaaONNopRo0alnlF0S5cujUGDBsXTTz8d7du3Tz0HSkYAALKRYwDo1KlTnH322bH//vtHo0aNvvbvXbp0aQwbNixOPfXUePvtt0u0MB9Dhw5NPaFkttpqqzjnnHOif//+UVNT87V/78svvxznnXde3HHHHSVal9a4ceNiypQp0aFDh9RT4EttuummqSeUzAcffBADBw6MsWPHRuPGjVPPgZLwFQAgG7kFgJNOOikmTpwYhx9++De++I+IaNCgQey3337xyiuvxOGHH178gRmZO3duPPTQQ6lnFF1NTU2ce+65MX78+Nhtt92+8cV/RET37t3j9ttvj/vuuy+bG04NHz489QT4SptvvnnqCSX1/PPPx7777htLly5NPQVKQgAAspFTADjvvPPikksuiYYNG37rX9uoUaO47rrr4tBDDy3Csjw9/PDDWXz8/4Ybbogzzjgjamu//R8vdt9993j88cdjzTXXLMKy8nL33XenngBfqUePHisU76rJAw88EEcffXTU1dWlngJFJwAA2cglAOy7775x+umnr9IZNTU18ec//zm6d+9eoFV5e/DBB1NPKLozzzxzlaNR9+7d429/+9tKBYRK8uSTT8bChQtTz4Av1bRp0+jcuXPqGSU3ZMiQ+MlPfiICUPWq+39hAb7go48+Sj2h6Bo3bhyDBw8uyFmrr756XHbZZQU5K3fV/vH/LbfcMs4+++yCnNW3b99VfjRXuVuyZEk8/vjjqWfAV9p+++1TT0ji6quvjlNPPTX1DCgqAQDIRg4B4Mgjj4x11123YOf16dMn+vTpU7DzcjRp0qSYMmVK6hlFdfHFF0e9evUKdt5ZZ50Va621VsHOK0c53GWdytW7d+/UE5K58MIL45RTTvFJAKqWAABkYd68ebFs2bLUM4ruiCOOKPiZbgi4ap588snUE4qqZ8+eBX+x0LJlyzjmmGMKema5GTt2bOoJ8JVy/QTA5y666CJfB6BqCQBAFmbNmpV6QtF16NChKHdv3nvvvaN+fU+NXVn/+Mc/Uk8oqmOPPbYo5/74xz8uyrnl4rnnnovFixenngFfqmPHjtGpU6fUM5K6+uqr45hjjsnizQPyIgAAWcjh4/99+/YtyrnNmjWLnj17FuXsHFRzAGjQoEHsvffeRTm7Y8eOVf1zt3Tp0njuuedSz4CvNHDgwNQTkrv22mvj0EMPFQGoKgIAkIUcAsBOO+1UtLN33nnnop1dzRYuXBivvPJK6hlFs80220SLFi2Kdn7//v2LdnY5ePrpp1NPgK8kAPzTrbfeGvvuu28Wj3IlDwIAkIVFixalnlB0xQwAxfp0QbV79dVXY/ny5alnFM2OO+5Y0een9tJLL6WeAF9phx12KGrgqyTDhw+Pfffd1+M7qQoCAEAVaNeuXbRr165o5/fq1ct9AFZCtb/A++53v1vU87faaquinp/ayy+/nHoCfKUGDRrEnnvumXpG2bj33ntjjz32EAGoeAIAkIV58+alnlBU3bt3L+r5DRs2jE022aSo16hG1R4Aiv1z17x58+jYsWNRr5HShAkTqvoTIlS+Qw45JPWEsvLoo4/GLrvsEnPnzk09BVaaAABkodr/kL3ZZpsV/Ro9evQo+jWqzZtvvpl6QtHU1NSU5MX5+uuvX/RrpLJo0aJ4//33U8+Ar7TTTjsV9dNllejvf/977LrrrlncW4jqJAAAWaj2AFDsd2IjoiiPGKx2kydPTj2haNq2bRsNGjQo+nU6dOhQ9GukVM0/I1S+evXqxcEHH5x6RtkZP3587Ljjjlk8YpjqIwAAWaj2rwCU4l3Sbt26Ff0a1aSuri7eeuut1DOKZu211y7JdVq3bl2S66QiAFDujjjiiNQTytKECRNihx12iKlTp6aeAt+KAABQBUrxEc1q/i52MUyfPr2qHxu1xhprVNV1UhEAKHff+c53ol+/fqlnlKXXX389evfuHVOmTEk9BVaYAABQBdq3b18V16gm1f7d7ubNm5fkOk2aNCnJdVKZMWNG6gnwjf77v/879YSy9dZbb8W2225b1fd8oboIAAAVbo011ojVV1+96Ndp1qxZyV70VQPfDS2Man/8ZLWHIqpD//79o3PnzqlnlK33338/dtxxR4/2pCIIAAAVrpQvytu2bVuya1W6adOmpZ5QFZo2bZp6QlEJRVSC2tra+NWvfpV6RlmbNm1a9O3bt+of/0rlEwAAKlyLFi1Kdq1GjRqV7FqVzgs7VoSfEyrFIYccEuutt17qGWVt9uzZsf3228e4ceNST4GvJAAAVLiampqSXava340tpGp/8gSFMWfOnNQTYIU0bNgwTj/99NQzyt68efNi1113jcceeyz1FPhSAgBAhWvZsmXJrlXt38cuJAGAFeHnhEpyxBFHeCLMCpg3b17svvvuMXr06NRT4P8QAABYYaWMDZVu/vz5qSdQAerq6mLBggWpZ8AKadiwYVxwwQWpZ1SERYsWRf/+/eOee+5JPQX+FwEAAIrAO7usqMWLF6eeACts//33j169eqWeURGWLl0a++67b9x5552pp8C/CQAAAAn5BACVpKamJi699NLUMyrG0qVL48ADD4xbbrkl9RSICAEAAIpiyZIlqScAFEWvXr3ikEMOST2jYixfvjwOPvjguOqqq1JPAQEAAIph0aJFqScAFM0ll1wSrVq1Sj2jovzkJz+JwYMHp55B5gQAAICEPvnkk9QT4Ftr1apVXHzxxalnVJyTTjrJjRRJSgAAAEho6dKlqSfASjn00ENj5513Tj2j4px22mlx2mmnpZ5BpgQAAABgpVx//fUeEbsSLrjggvjFL34RdXV1qaeQGQEAAABYKe3bt4+rr7469YyKdMkll8RPfvITEYCSEgAAAICVtv/++8fBBx+cekZFuvrqq+PQQw+NZcuWpZ5CJgQAAABglVx55ZXRuXPn1DMq0s033xwHH3xwfPrpp6mnkAEBAAAAWCXNmjWLoUOHRuPGjVNPqUi333577LvvviIARScAAAAAq2zTTTeNa6+9NvWMinXvvffGgAEDYuHChamnUMUEAAAAoCB+9KMfxfHHH596RsUaNWpU7LHHHjFv3rzUU6hSAgAAAFAwl156afTr1y/1jIr16KOPxi677BJz585NPYUqJAAAAAAFU69evbjzzjuje/fuqadUrPHjx8euu+4qAlBwAgAAAFBQzZs3jxEjRkTbtm1TT6lYIgDFIAAAAAAF16FDhxg5cmQ0b9489ZSKNX78+OjTp0/MmjUr9RSqhAAAAAAURY8ePeKBBx6IRo0apZ5SsZ5//vno27evCEBBCAAAAEDRbLvttjFs2LBo0KBB6ikVa8KECTFgwABfB2CVCQAAAEBR9evXL+666y4RYBU8/fTTMXDgwFi4cGHqKVQwAQAAACi6gQMHigCr6PHHH4999tknPv3009RTqFACAAAAUBIiwKp78MEH44ADDohly5alnkIFEgAAAICSGThwYAwdOtSNAVfBsGHD4qijjoq6urrUU6gwAgAAAFBSe+yxR4wYMSKaNWuWekrFuuGGG+Lss89OPYMKIwAAAAAl17dv33j44YejRYsWqadUrHPOOSf+8pe/pJ5BBREAAACAJHr27BlPPPFEtGrVKvWUinXMMcfEAw88kHoGFUIAAAAAkunevXv8/e9/j3XXXTf1lIq0fPny2HfffePZZ59NPYUKIAAAAABJde7cOcaOHRsbbrhh6ikVaeHChTFgwICYOnVq6imUOQEAAABIrlOnTvHYY4/FpptumnpKRZoxY0bstddesXDhwtRTKGMCAAAAUBbat28fo0ePjq222ir1lIr03HPPxZFHHunxgHwlAQAAACgbrVu3jkceeSS23Xbb1FMq0u233x7nn39+6hmUKQEAAAAoKy1atIiHH344dtppp9RTKtKvf/3ruOeee1LPoAwJAAAAQNlp3Lhx3H///bHnnnumnlJx6urq4qCDDopJkyalnkKZEQAAAICy1LBhwxg6dGj86Ec/Sj2l4ixYsCB++MMfxuLFi1NPoYwIAAAAQNmqX79+3HjjjfHjH/849ZSK8+KLL8bxxx+fegZlRAAAAADKWr169eLqq6+On//856mnVJy//OUv7gfAvwkAAABA2aupqYmLL744zjrrrNRTKs7RRx8ds2bNSj2DMiAAAAAAFeO3v/1t/PGPf0w9o6LMnDkzfvKTn6SeQRmon3oAAAAr5+OPP47BgwennlFwbdu2jWOPPTb1DMrYySefHE2aNImf/exnsXz58tRzKsJdd90V9957r6cqZE4AAACoUB9//HH89re/TT2j4Hr06CEA8I2OO+64aN68eRx66KEiwAr66U9/Gn369ImmTZumnkIivgIAAABUpIMOOiiGDRsWDRo0SD2lIrz33ntxzjnnpJ5BQgIAAABQsQYOHBj33XdfNGrUKPWUijB48OCYPHly6hkkIgAAAAAVbZdddokHH3wwmjdvnnpK2fv000/j5JNPTj2DRAQAAACg4m2//fYxatSoaNWqVeopZW/YsGHx1FNPpZ5BAgIAAABQFbbeeusYPXp0tGvXLvWUsnfaaaelnkACAgAAAFA1unfvHo8//nh06NAh9ZSy9thjj8UjjzySegYlJgAAAABVZaONNoonn3wyNtxww9RTyponAuRHAAAAAKpO+/bt47HHHotu3bqlnlK2xowZ414AmREAAACAqtS+ffsYM2ZMbLrppqmnlK3f//73qSdQQgIAAABQtVq3bh2jR4+O7373u6mnlKURI0bEpEmTUs+gRAQAAACgqrVu3TpGjRoV22yzTeopZaeuri4uv/zy1DMoEQEAAACoei1atIiHHnpIBPgS119/fSxYsCD1DEpAAAAAALLweQTwdYD/bf78+XHbbbelnkEJCAAAAEA2WrRoEffff78bA/6Hv/71r6knUAICAAAAkJXPbwwoAvw/48aNi1dffTX1DIpMAAAAALLzeQTYaKONUk8pGzfeeGPqCRSZAAAAAGSpdevW8fDDD8c666yTekpZ+Nvf/pZ6AkUmAAAAANnq1KlTjBw5Mlq0aJF6SnKTJ0+OZ599NvUMikgAAAAAsta9e/e47777olGjRqmnJHfXXXelnkARCQAAAED2vv/978edd94ZtbV5v0QaOXJk6gkUUd4/3QAAAP+yxx57xGWXXZZ6RlIvvPBCzJw5M/UMikQAAAAA+Jef/exncdxxx6WekdTDDz+cegJFIgAAAAB8wZ/+9KfYZZddUs9IZvTo0aknUCQCAAAAwBfUr18/7rzzzujatWvqKUn84x//SD2BIhEAAAAA/kPLli3j//v//r9o3Lhx6ikl9/rrr8fHH3+cegZFUD/1AAAAIL3BgwfH4MGDU88ouIsuuij23Xfflfq1m2yySfz5z3+OQw45pMCryltdXV2MHz8+dt1119RTKDABAAAAiI8//jjefffd1DMKbsGCBav06w8++OAYMWJE3HHHHQVaVBmee+45AaAK+QoAAADA17jqqquiXbt2qWeU1IQJE1JPoAgEAAAAgK+xxhprxOWXX556RkkJANVJAAAAAPgG++yzT+yxxx6pZ5TM66+/Hp999lnqGRSYAAAAALACLr744mjQoEHq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XLCzNtxww1hrrbWyCynz58+P5557LvWM5OrVq+cTAFVMAKDsPf300/H000+nnlE0hx12mABQIuuss07qCSUxbdq0+NWvfhVXXHHFKp918803x7hx4wqwKl9bbbVV/OUvf0k9o2g++eST+M1vfhNXXnllwc4cOnRoPPXUUwU7rxx17969YDfYatiwYWy00UZZfMedr9a3b9+Cnrf11ltX/X04+HKbb755NGrUKPUMisQ9AIBs5PIJgIiIK6+8cpWfnT1p0qT42c9+VqBF+crhY5RXX311PProowU568MPP4yf/vSnBTmrnG2zzTYFPe973/teQc+jstSrVy922GGHgp7Zs2fPgp5H5dhuu+1ST6CIBAAgGw0bNswqAhx55JFx5513rtSvnTBhQvTp0yfmzZtX4FX52WyzzWKNNdZIPaOo6urqYr/99ovXXnttlc5ZuHBh7LnnnvHBBx8UaFn56t27d0HPEwDy9r3vfa8gX/v6Ii8C89WnT5/UEygiAQDISocOHVJPKJmlS5fG/vvvH6ecckp88sknK/RrFi1aFH/84x/ju9/9brz//vtFXpiH2tra2HbbbVPPKLrZs2fHdtttFw899NBK/frJkyfHdtttF//4xz8KvKw8CQAU0qBBgwp+5rbbbhsNGjQo+LmUt9ra2oL//kR5EQCArHTq1Cn1hJK76KKLYoMNNohf//rXMW7cuP/zmMDp06fHgw8+GMcff3ysv/768ctf/jKWLFmSaG11yuXdlI8++ij69esXBxxwwArf+PD999+PM844IzbZZJOqvlniF33nO9+Jtm3bFvTMTTbZJJo1a1bQM6kcP/zhDwt+ZuPGjX0NIENbbrlltGjRIvUMishNAIGs5BgAIiJmzpwZ5513Xpx33nkREbHmmmtGbW1tzJ8/34v9Eth9993j5JNPTj2jZO6444644447onPnztG3b9/o1q1brLPOOtGgQYOoq6uLmTNnxqRJk+LJJ5+M8ePHZ3f3+v79+xf8zHr16sUuu+wSQ4cOLfjZlLetttqqaJ9u22mnnWLs2LFFOZvyNGDAgNQTKDIBAMhK165dU08oCx999FHqCVnp1q1brL/++vH222+nnlJSkyZNikmTJqWeUXb22GOPopy75557CgAZ2nfffYt2dv/+/eO3v/1t0c6n/AgA1c9XAICsCACkUqwXfVSWZs2axfbbb1+Us3ffffeoqakpytmUp9ra2vjRj35UtPO32WabWHvttYt2PuVl7bXXjq222ir1DIpMAACy0q1bt9QTyNQ+++yTegJlYI899oiGDRsW5ew2bdr4znZmBgwYUNSb29bW1npHOCODBg2K2lovD6udf8NAVlq3bu3dDJLYYYcdol27dqlnkFgx362NiDjwwAOLej7l5dhjjy36NYrxhAHKUzFuJkn5EQCA7Gy55ZapJ5Ch2tpaL84yt8Yaa0S/fv2Keo2DDjqoaJ8woLx06tSpKDeU/E/9+vWLNdZYo+jXIa3WrVt7/F8mBAAgO1tssUXqCWTqoIMOSj2BhA444ICiP1d9rbXWir322quo16A8HHfccSX5uHbDhg1jv/32K/p1SGvfffeNevXqpZ5BCQgAQHa22Wab1BPI1JZbbhlbb7116hkkcswxx5TkOkceeWRJrkM6a621VvzkJz8p2fWK/dUV0jviiCNST6BEBAAgO9tuu23qCWSsFN/Zpfx873vfix49epTkWrvssosbnla5k08+OZo2bVqy622//fbRpUuXkl2P0urevXt897vfTT2DEhEAgOy0bt3aH2RI5oADDog111wz9QxKrJTv1tbW1sZpp51WsutRWi1atCh5SKypqYnjjjuupNekdHxqKC8CAJClHXfcMfUEMtW4ceP42c9+lnoGJdShQ4c44IADSnrNAw88MDp16lTSa1Iav/jFL6Jly5Ylv+7hhx8ejRs3Lvl1Ka4mTZrEYYcdlnoGJSQAAFkq9p244escf/zx0aRJk9QzKJFTTjkl6tevX9Jr1q9fP371q1+V9JoUX8eOHePkk09Ocu2WLVvGoYcemuTaFM/hhx+eJCiRjgAAZKlv374luXsyfJlWrVrFUUcdlXoGJdC2bdtkH6898sgjo3PnzkmuTXFceOGF0ahRo2TX/9WvfuVO8VWkpqYmjj/++NQzKDF/+gWytMYaa7gZIEn9+te/jmbNmqWeQZGdeeaZyV6wNWjQIC688MIk16bwdthhh+SP4+vUqZPHmVaRgQMHRteuXVPPoMQEACBbe++9d+oJZKxVq1bxy1/+MvUMiqhz587x4x//OOmGQYMGxe677550A6uufv368T//8z+pZ0RExOmnn+5TAFXi7LPPTj2BBAQAIFv77LNP6glk7qSTTor27dunnkGRXHjhhSX/7v+Xufzy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+OA466yzUs/gW9p8883j6aefjnPOOSeLSFUqe+21V0yYMCGOPvpo76b9y5577hmvvfZanH766T5evIJat24dN954Yzz88MM+WfUF//Vf/xWvvPJK7LvvvqmnVLzdd989nn/+eU/v4FsRAABWwA477BCPP/54VX5vs2/fvu4WXMEaNGgQv/71r2PixIlxwAEHpJ5T0TbeeON48MEHY/jw4d7t/hKNGzeO8847L1566aXYa6+9Us8pWzU1NXH00UfH66+/HocccojfW7/EeuutF3/729/ioYceio033jj1nIrTokWLuP766+O+++7zxB6+NQEAYAX16NEjnn322aq6AVufPn3i3nvv9Y5eFVhvvfXitttui3/84x/Rr1+/1HMqyoYbbhjXX399vPjii7HrrrumnlP2unbtGsOHD4/x48f7WfsPAwYMiOeeey6uueaaWHPNNVPPKXu77LJLvPzyy3HjjTe64eQKqKmpiaOOOiomTpwYhx9+eOo5VCgBAOBbWGutteKBBx6ICy+8sOIfa9S/f/8YMWJEVT7PPGe9evWKkSNHxj/+8Y/Yc889vfv4Nbp16xbXX399vP7663H44Ye7qeK3tPXWW//7Z23QoEFZ/6ztsMMOMXbs2BgxYkRsvvnmqedUlNra2jjkkEPi9ddfjyFDhsRmm22WelJZ6tevXzz33HNx7bXXxtprr516DhVMAAD4lurVqxennHJKPPPMM9GrV6/Uc1bKf//3f8c999zjxX8V69WrV9xzzz3xxhtvxPHHH++mW/9SU1MTu+22W4wcOTJeeeUVL/wLoFevXjFs2LB466234qSTTqrq+6V8Ub169WLfffeNsWPHxpgxY+L73/9+6kkVrX79+nHooYfGiy++GI888kjstdde/tuMf96T5KmnnoqRI0eKSxSEAACwkjbddNP4+9//Hrfddlt06tQp9ZwVss4668SIESPisssuiwYNGqSeQwlstNFG8ac//Sk++OCDuOmmm2KnnXbK8p3azp07x3nnnRdTpkyJ+++/P/r165fl/x+Kaf31149LLrkkpk2bFjfccEPV/qy1bt06fvGLX8Sbb74Zf/vb37zwL4K+ffvG8OHDY+rUqXHxxRdn96mANdZYI0444YR45ZVXYvjw4dGzZ8/Uk6giAgDAKqipqYkDDjggJk6cGEOGDInu3bunnvSlVl999TjxxBPjlVdeiQEDBqSeQwKNGzeOgw8+OEaNGhVTp06NK6+8Mnbeeeeqfodtk002iV//+tfx7LPPxhtvvBGnn366u7GXQJMmTeKwww6LUaNGxZQpU+KCCy6IXr16VXQMWH311eOAAw6IESNGxPvvvx8XXXRRxYTfSrb22mvHz3/+83jxxRfjjTfeiD/84Q8V/7P0VRo2bBh77LFH3HzzzTFt2rQYPHiwGyRSFDV1dXV1qUdQGC1btoy5c+emnsG3dNhhh8UNN9zwrX/dCy+8EFtssUXhB5WJYcOGxaBBg1LPWCmPPfZY3HrrrXHXXXfFnDlzkm5p2rRpHHLIIXHaaafFeuutt8rnDRo0KO6+++4CLCtPe+21VwwfPjz1jJL6+OOP49FHH41HHnkkHn744XjjjTdST1pprVq1ij59+sQuu+wSO+20U2ywwQapJ/EFM2bMiPvuuy/uvffeGDNmTPLfH79Ju3bton///rH77rtHv379fI2mjHz44Yfx6KOPxqhRo2L06NExadKk1JNWSps2bWLnnXeO/v37x8CBA6NFixapJ5EBAaCKzJ07N/zrrDwNGzZcqe9hL1u2LObPn1+EReWhSZMmFf8R9U8//TRGjx4dDz30UIwaNSpefvnlkly3YcOGsf3228dBBx0U++23XzRp0qRgZ3/yySexdOnSgp1Xbho0aFDQ/39VopkzZ8a4cePiqaeeivHjx8fLL78cM2bMSD3r/2jSpElsvPHGsfXWW0evXr1im222iS5dulTlO4PVaPny5TFhwoR4/PHH44knnohnnnkmJk+enHRTp06domfPntGzZ8/o27dvbLbZZn6eKsTs2bPj6aefjnHjxsUzzzwTEyZMiHfffTf1rP9jo402im222Sa22Wab6N27t58xkhAAAErkww8/jOeeey6effbZeOGFF2LSpEkxefLk+Pjjj1fp3DZt2kSPHj2iR48e0bt37+jdu3f2L2IprNmzZ8eECRPitddei7fffjveeeedmDx5crz33nsxe/bsWL58eVGu27Jly1h33XWjU6dOsf7668f6668fXbp0iU033TQ6duzoD85VZv78+fHSSy/Fiy++GK+//nq8/fbb//55++STTwp2nXXWWSe6dOkSnTt3jq5du8Z3vvOd2HrrraNNmzYFuwbpLViwIF577bV47bXX4p133vn3X++9915Mnz69oD9TX9SiRYt//77VpUuX6NatW3Tt2jW6d+/u0ZCUBQEAILGPP/44pk6dGh9++GHMmjUrPvroo1i4cGF89tlnsWDBgn//fZ9/KqJZs2axzjrrxLrrrhvrrLNOtGrVKuF6crd8+fKYPXt2zJo1K2bNmhXz5s2L+fPnx4IFC2LRokX/5+f4c6uvvnqsvvrq0aBBg2jatGm0aNEimjdvHi1atIi2bdtG69ato2HDhgn+iShHs2fPjg8//PB//fV5PF28eHEsXrz4339v8+bNo7a2Nho3bhxNmjSJVq1aRZs2bWLttdeO1q1bV/ynyyiMRYsWxaxZs2LGjBkxf/78mDdvXsybNy8++eSTWLJkyVd+0rJZs2ZRr169WH311aNFixbRsmXLaNmyZay55prRvn17AZ6yJwAAAABABjwFAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIwP8PWIabnjgcWq0AAAAASUVORK5CYII=',
scale: 3.508264580369843,
},
locked: false,
child: [],
parent: 'ROOT',
},
},
},
],
img: '/assets/images/qr-code/1.png',
},
{
elements: [
{
rootId: '5c11f494-5d02-4d65-a816-c9669c519065',
layers: {
'5c11f494-5d02-4d65-a816-c9669c519065': {
type: { resolvedName: 'GroupLayer' },
props: {
position: { x: 23.478260869565247, y: 100.89354861209551 },
boxSize: { width: 395.04347826086956, height: 462 },
scale: 1,
rotate: 0,
},
locked: false,
child: [
'd78fb0c2-7a1c-4381-8571-c9871ccd9cac',
'3f39efa2-4017-4c77-b3a9-c98456c629f0',
'930dca01-95e0-4527-be58-ede3cc41bc2e',
],
parent: 'ROOT',
},
'd78fb0c2-7a1c-4381-8571-c9871ccd9cac': {
type: { resolvedName: 'SvgLayer' },
props: {
image:
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OSIgaGVpZ2h0PSI2OSIgdmlld0JveD0iMCwtMC4wMDAwMDc2MjkzOTQ1MzEyNSwxNS40Nzk1NTMyMjI2NTYyNSwxOC4xNDQzNDA1MTUxMzY3MiIgdmVyc2lvbj0iMS4xIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDcuNDQxODM1LC0xMTUuODQ5NjcpIj4KICAgIDxyZWN0IHdpZHRoPSIxNS40Nzk1NTEiIGhlaWdodD0iMTguMTQ0MzM5IiB4PSI0Ny40NDE4MzMiIHk9Ii0xMzMuOTk0IiB0cmFuc2Zvcm09InNjYWxlKDEsLTEpIiByeT0iMC40NTEwMTUxNyIvPgogICAgPHJlY3QgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlLXdpZHRoPSIwLjUyNTg1OyIgaWQ9ImNyYXlvbi11bmlxdWUtaWQtMzQtNCIgd2lkdGg9IjE0LjU5MTQzNyIgaGVpZ2h0PSIxNC41NTI4MjQiIHg9IjQ3LjkwMzUiIHk9Ii0xMzAuODUzMDkiIHRyYW5zZm9ybT0ic2NhbGUoMSwtMSkiIHJ5PSIwLjMxNjk5OTkxIi8+CiAgPC9nPgo8L3N2Zz4K',
position: { x: 0, y: 0 },
boxSize: { width: 395.04347826086956, height: 462 },
colors: ['rgb(0, 0, 0)', 'rgb(255, 255, 255)'],
rotate: 0,
},
locked: false,
child: [],
parent: '5c11f494-5d02-4d65-a816-c9669c519065',
},
'3f39efa2-4017-4c77-b3a9-c98456c629f0': {
type: { resolvedName: 'QrCodeLayer' },
props: {
text: 'https://lidojs.com',
position: { x: 22.108510111942678, y: 21.070943504373645 },
boxSize: {
width: 350.8264580369844,
height: 350.8264580369844,
x: 1082.586770981508,
y: 155.9961470707375,
},
rotate: 0,
bgColor: 'rgb(255, 255, 255)',
textColor: 'rgb(30, 30, 45)',
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAYAAAB/HSuDAAAACXBIWXMAAC4jAAAuIwF4pT92AABbQ0lEQVR4nO3defzVc/7//8f73UJ7qBSpLNWEZBlqjKWyFJEYYxnrxzKYGR/MMGMZzAyGMZbMxzbMIDvjVyGERGRG2cmSCElpIS1apN6/P2bM12c+ltQ553nOeV6vl4t/Phc9X3cfb03nds55vWrq6urqAgAAAKhqtakHAAAAAMUnAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIQP3UA4CV8/7778cf//jH1DOK5sgjj4zu3bunngEAAFVDAIAKNWvWrLjssstSzyia3r17CwAAAFBAvgIAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyED91AMAAAAKZenSpTF58uR48803Y+rUqTF9+vSYPn16zJo1K+bOnfvvv5YuXRrLli2L+fPn//vXNm7cOBo2bBgREY0aNYpmzZr9+68111wzWrduHW3atIl27dpFmzZtolOnTtGxY8do0KBBqn9c+FYEAAAAoCJ98MEHMX78+HjhhRfi2WefjQkTJsS7774by5YtW6nz5s6d+61/TW1tbay33nqxwQYbRLdu3WKzzTaLzTbbLDbddNNo1qzZSu2AYhEAqshVV10VS5YsST2j4DbeeOPYddddU88AIuLee++Nt956K/WMotlwww1jzz33TD0DKIHBgwennlA0xx13XKy22mqpZxTFhx9+GCNHjoxHH300xowZE2+++WbqSbF8+fJ499134913341HH3303//3mpqa6NatW3z/+9//918bbbRRwqUQUVNXV1eXegSF0bJly5WqluXusMMOixtuuCH1jLLzwgsvxBZbbJF6RtEMGzYsBg0alHoG/2HQoEFx9913p55RNHvttVcMHz489QygBGpqalJPKJo5c+ZEy5YtU88omClTpsTtt98e9957b/z973+P5cuXp5600tZff/3Yfffdo3///rHTTjtFo0aNUk8iMz4BAAAAlJWFCxfGbbfdFjfddFM8/vjjUS3vWb799ttxxRVXxBVXXBFNmjSJPffcM370ox/FrrvuWrWf2qC8eAoAAABQFiZPnhw///nPY911142jjjoqxowZUzUv/v/TJ598ErfffnsMHDgw2rVrFyeddFK88cYbqWdR5QQAAAAgqYkTJ8bhhx8eXbp0iUsvvTQ+/vjj1JNKas6cOTF48ODo2rVr7LLLLjFy5MjUk6hSAgAAAJDE+++/H4cffnh069YthgwZstJ3768mo0aNit122y169uwZw4cPr9pPQJCGAAAAAJTU4sWL45xzzokuXbrEkCFDvMj9EuPHj4+99947tttuuxg/fnzqOVQJAQAAACiZJ598MjbffPM466yzYuHChannlL2///3v0bNnzzj44INj1qxZqedQ4QQAAACg6JYsWRK/+MUvYvvtt4+JEyemnlNxbrnllujWrVvccsstqadQwQQAAACgqN58883Ydttt45JLLvFx/1Xw4YcfxsEHHxw/+MEPYs6cOannUIEEAAAAoGjuu+++2HLLLeO5555LPaVqDB06NL773e/Gs88+m3oKFUYAAAAAiuLiiy+OgQMHxvz581NPqTqTJ0+O73//+3HrrbemnkIFEQAAAICCqqurixNOOCFOPvnkWL58eeo5VWvJkiVx0EEHxQUXXJB6ChVCAAAAAApm2bJlceSRR8af/vSn1FOycdppp8Xxxx/v/gp8IwEAAAAoiLq6ujj88MPj+uuvTz0lO5dffnmceuqpqWdQ5gQAAACgIH72s5/FzTffnHpGti688MI444wzUs+gjAkAAADAKvvd734XV155ZeoZ2fv9738f11xzTeoZlCkBAAAAWCV33HFHnH322aln8C8//elP45FHHkk9gzIkAAAAACvtmWeeif/6r/9KPYMv+Oyzz+KHP/xhvPfee6mnUGYEAAAAYKXMnTs39t9//1i0aFHqKfyHOXPmxIEHHhifffZZ6imUEQEAAABYKUcddVRMnjw59Qy+wpNPPhm/+93vUs+gjAgAAADAt3bDDTfEXXfdlXoG3+D3v/99PPfcc6lnUCYEAAAA4Fv54IMP4sQTT0w9gxWwbNmyOPLII30VgIgQAAAAgG/puOOOi7lz56aewQp64YUX4pJLLkk9gzIgAAAAACts5MiRMXz48NQz+JbOPffcmDFjRuoZJCYAAAAAK+Szzz6Lk046KfUMVsL8+fPj17/+deoZJFY/9QBg5ay55ppx2GGHpZ5RNB06dEg9AQD4D1deeWW8/vrrqWewkv7617/GSSedFBtvvHHqKSQiAECF6tChQ9xwww2pZwAAmVi0aFGcf/75qWewCurq6uJ3v/td3H777amnkIivAAAAAN/oz3/+c3zwwQepZ7CK7rzzznj11VdTzyARAQAAAPhaixcvjvPOOy/1DAqgrq7Ov8uMCQAAAMDXuvnmm2P27NmpZ1Agd955Z7z//vupZ5CAAAAAAHylurq6GDx4cOoZFNBnn30WV1xxReoZJCAAAAAAX2n06NHxyiuvpJ5Bgf35z3+OxYsXp55BiQkAAADAV/rLX/6SegJF8NFHH8Xw4cNTz6DEBAAAAOBLzZkzJ4YNG5Z6BkVy3XXXpZ5AiQkAAADAl7r11ltjyZIlqWdQJKNGjYopU6aknkEJCQAAAMCXuvPOO1NPoIjq6ur8O86MAAAAAPwfM2fOjLFjx6aeQZHdddddqSdQQvVTDwDIxfLly+Pdd9+Nt99+O955552YMWNGfPTRR/HRRx/FsmXL4uOPP46IiNVWWy0aNWoU9erVi2bNmkWrVq2idevW0aZNm1h33XWjS5cu0bJly6T/LPC5uXPnxrRp0+L999+PGTNmxIcffhhz5879919Lly6Nurq6mDt37r9/TZMmTaJBgwYREdGyZcto0aLFv/9q165dtGvXLtZZZ51o06ZN1NTUpPpHg+wNHTo0li9fnnoGRTZu3LiYMmVKdOjQIfUUSkAAACiSmTNnxuOPPx6PPfZYPPvss/Hyyy/HJ598UpCz11577fjOd74TW265ZWy33Xax3XbbRZs2bQpyNnyZyZMnx/PPPx8vvfRSvPnmmzFx4sSYNGlSzJs3r2jXbNCgQWywwQbRtWvX2GijjWLjjTeOLbbYIjbddNNo2LBh0a4L/NOIESNST6BEhg4dGieeeGLqGZSAAAAVatGiRTFx4sTUM4pm/fXXjxYtWqSe8a299957ceutt8bw4cNj3LhxUVdXV5TrzJgxI2bMmBFjxoyJSy+9NCIiNt5449hnn31in332iS222KIo1yUPixcvjqeeeirGjBkTY8eOjaeffvp/vYNfKkuXLo2JEyf+n9/r6tevH927d49tt902dtxxx9h+++2jbdu2Jd8H1WzJkiXx6KOPpp5BiTzwwAMCQCYEAKhQEydOrOoXecOGDYtBgwalnrFC6urq4oEHHoj/+Z//iQcffLBoL/q/yauvvhqvvvpqnHvuudG5c+f46U9/GkcccUQ0a9YsyR4qy9tvvx333ntvjBgxIh5//PGyvuv3Z599Fs8//3w8//zzccUVV0RExCabbBIDBgyIPfbYI7bddtuoV69e4pVQ2caOHRsLFy5MPYMSGTNmTCxatCgaNWqUegpF5iaAAKtg+PDhsfnmm8eAAQNi5MiRyV78/6dJkybFiSeeGOuuu2788pe//Pf9BeCL3nvvvbjwwgtj8803jw022CBOOOGEePjhh8v6xf9XeeWVV+LCCy+MHXbYIdq0aRPHHntsjB07tmz+m4RKM2rUqNQTKKElS5bEY489lnoGJSAAAKyECRMmxI477hh77713vPTSS6nnfKX58+fHH//4x9hwww3jsssui88++yz1JBL77LPP4q677oq+fftGx44d41e/+lW8+OKLqWcV1EcffRR//vOfY/vtt49OnTrFueeeGx988EHqWVBRnnzyydQTKLFHHnkk9QRKQAAA+BaWLVsW55xzTmy11Vbx+OOPp56zwj766KM48cQTo1evXvHqq6+mnkMCc+bMiXPOOSc6duwYP/zhD+PRRx/N4t3xKVOmxJlnnhkdOnSIAw44IJ555pnUk6DsffrppzF+/PjUMyixSvpzDStPAABYQR988EHsvPPOcdZZZ8Wnn36aes5KefbZZ2PrrbeOm2++OfUUSmTGjBlx6qmnxnrrrRdnnXVWTJs2LfWkJJYuXRp33HFHbL311tG/f/8YM2ZM6klQtp555pmK/CoQq+a5556LBQsWpJ5BkQkAACvg5Zdfjq233roqvh+3cOHCOOSQQ+LMM8/M4h3gXC1YsCDOPvvs2GCDDeIPf/hDwR5BWQ0efPDB6N27d/Tr16+sv8IDqTz33HOpJ5DAsmXL4qmnnko9gyITAAC+wdixY2O77baLqVOnpp5SUOeee24cdthhsWzZstRTKKC6urr461//Gp07d47f/e537uL9NR566KHYfPPN44gjjoiZM2emngNl4/nnn089gUTGjRuXegJF5jGAAF9j3LhxMWDAgJg3b17qKUVx0003xbJly+LGG2/02LQq8Nprr8WPf/zjGDt2bOopFaOuri6uv/76GD58eFx44YVx5JFHRk1NTepZkFQuAaBt27ax4447Rvfu3aNTp07RpEmTiPjnPRDee++9ePHFF2P06NHx/vvvJ15aOs8++2zqCRSZAADwFSZOnBj9+vWr2hf/n7v11lujtrY2brzxRi98KtSyZcvi/PPPj3POOadi70+R2pw5c+Loo4+Om266KYYMGRKdOnVKPQmSWLZsWbzyyiupZxTV7rvvHieffHLsuOOOUVv79R+IrqurizFjxsR5552XxaMR3Si1+vkKAMCXmDNnTgwcODDmzp2bekpJ3HzzzXHGGWeknsFKeOedd6J3795x5plnevFfAI8//nj06NEjbr311tRTIIl33nmnan8vadGiRQwdOjTuu+++6NOnzze++I+IqKmpid69e8fDDz8ct912WzRt2rQES9N57733YtasWalnUEQCAMCXOPzww+ONN95IPaOkzj///LjuuutSz+BbuOeee6JHjx4+8l9g8+bNi4MOOij+67/+KxYvXpx6DpTUxIkTU08oipYtW8YTTzwRe++990qfccABB8SYMWOiefPmBVxWfl5++eXUEygiAQDgP1x99dVxzz33pJ6RxHHHHef7fxWgrq4ufvOb38Ree+1V9V9RSemGG26I7bffPt57773UU6BkqjV+33rrrdG9e/dVPmfLLbeMu+66qwCLyle1fwUkdwIAwBe89957ccopp6Sekcynn34a++23XzZffahECxcujB/84Afx29/+NvWULDzzzDPx3e9+152xycZbb72VekLBHXHEEbHbbrsV7LxddtkljjzyyIKdV25ef/311BMoIgEA4AtOOOGEWLBgQeoZSU2ePDlOOOGE1DP4EnPmzIldd901hg0blnpKVmbOnBl9+vSJ+++/P/UUKLpqe+RtgwYN4uyzzy74uWeeeeYK3UOgEr322mupJ1BE1flTC7ASRo8e7YXVvwwZMiQefPDB1DP4gqlTp8Z2220XTz75ZOopWVq0aFEMHDgwbrnlltRToKimTJmSekJBDRo0KDp06FDwczt27Bh9+/Yt+LnloFrvA8E/CQAA8c/vVP/yl79MPaOsHH300fHJJ5+knkH888V/796949VXX009JWvLli2LQw89VASgqlXbJwD233//op3dr1+/op2d0rRp02LJkiWpZ1AkAgBARNx9991ufvcf3nvvvfjDH/6Qekb2pk2bFr17967K7+VWouXLl4sAVK1ly5bFzJkzU88oqB133LFoZ2+11VZFOzu1d999N/UEikQAALJXV1fnhmpf4aKLLqq6d4Mqydy5c2O33Xbz4r/MfB4BRowYkXoKFNSHH36YekJBrbPOOtGqVauind++ffuinZ3a22+/nXoCRSIAANm7//7744UXXkg9oywtWrQozjzzzNQzsvTpp5/GPvvsEy+99FLqKXyJ5cuXx3777Rf/+Mc/Uk+Bgqm2AFCM7/5/0ZprrlnU81MSAKqXAABkb/DgwaknlLWbbrop3nzzzdQzsnPEEUfE6NGjU8/ga3x+Y8DJkyenngIFMXv27NQTCmqNNdYo6vn16tUr6vkpTZ8+PfUEikQAALI2YcKEGDVqVOoZZW3ZsmVx0UUXpZ6RlYsvvth3zCvE7NmzY9CgQW6YSVX46KOPUk8oqIYNG6aeULE++OCD1BMoEgEAyNq1116bekJFuO6662LatGmpZ2ThkUce8USKCvPyyy/HEUccEXV1damnwCqptpA1b9681BMqlk8AVC8BAMjW4sWL46abbko9oyIsXbo0rrnmmtQzqt706dPjwAMPjOXLl6eewrd05513xhVXXJF6BqyShQsXpp5QUNX2lYZSmjFjRuoJFIkAAGRrxIgRMWfOnNQzKsY111wTS5cuTT2jatXV1cXhhx8es2bNSj2FlXTyySfHhAkTUs+AlbZgwYLUEwrqnXfe8cmclVRtj4Pk/xEAgGzdeuutqSdUlOnTp8djjz2WekbVGjx4cDz00EOpZ7AKlixZEgceeGAsWbIk9RRYKfPnz089oaDmz5/vMaorqdruB8H/IwAAWVqwYEHcd999qWdUnGr7eGi5ePPNN+OMM85IPYMCmDBhQpx77rmpZ8BKWbZsWeoJBff888+nnlCR5s2b5+toVUoAALL0wAMPxKeffpp6BkRdXV0cc8wxsWjRotRTKJALLrjAVwGgTPz9739PPaFi+ZpkdRIAgCzdfffdqSdAREQMGTIkRo8enXoGBfTZZ5/FUUcd5bvHUAb87/3K+/jjj1NPoAgEACA7y5cvjwcffDD1DIgFCxbEaaedlnoGRTBu3Li45ZZbUs+A7L399ts+kbOSqu2eEPyTAABk5/nnn/doIMrC+eefHx988EHqGRTJqaee6r4ZUAb+9re/pZ5Qkfz+VZ0EACA7Dz/8cOoJEFOmTIlLLrkk9QyK6P3334+LLroo9QxYYbW11fnS4Nprr43PPvss9YyK415J1ak6/ysH+Bpjx45NPQHi97//fSxevDj1DIrskksu8T1aKkbz5s1TTyiK6dOnx/Dhw1PPqDhz585NPYEiEACArCxfvtwdgUluypQpcd1116WeQQnMnTs3Bg8enHoGrJBq/QRARMSf/vSn1BMqjk8AVKfq/a8c4EtMmjTJY21I7g9/+EMsXbo09QxKZPDgwbFgwYLUM+AbtWrVKvWEonniiSfiscceSz2jonzyySepJ1AEAgCQlRdeeCH1BDI3Z86cGDJkSOoZlNDcuXPj+uuvTz0DvtFaa62VekJRnXbaaR7PSfYEACArL774YuoJZO4vf/mLd1UydNlll8Xy5ctTz4CvVe0B4KmnnhLjyJ4AAGTFJwBIafny5XH55ZennkECb731Vtx///2pZ8DXatu2beoJRffLX/7S41fJWv3UAwBKSQAgpYceeiimTJmSegaJ/OUvf4k99tgj9Qz4Sm3bto369etX9SPzPvzwwzj66KPj3nvvXeWz6tWrFz169CjAqvLUsmXL1BMoAgEAyMbs2bNj+vTpqWeQsRtuuCH1BBK67777YubMmdGmTZvUU+BL1a9fPzp06BCTJ09OPaWoRowYEZdddlmccMIJq3ROs2bNvLFAxfEVACAbb775ZuoJZGzOnDkxbNiw1DNI6LPPPotbbrkl9Qz4WhtssEHqCSVxyimnxLhx41LPgJLzCQAgG++8807qCck0adIkdtppp9hiiy2ic+fO0bx582jcuHHMmTMnpk2bFk8//XQ89NBDMXPmzNRTq9bw4cOze6Zy+/bto3///rHZZpvFeuutFy1atIgFCxbErFmz4pVXXolHHnkkuxtz3nHHHXHSSSelngFfaaONNopRo0alnlF0S5cujUGDBsXTTz8d7du3Tz0HSkYAALKRYwDo1KlTnH322bH//vtHo0aNvvbvXbp0aQwbNixOPfXUePvtt0u0MB9Dhw5NPaFkttpqqzjnnHOif//+UVNT87V/78svvxznnXde3HHHHSVal9a4ceNiypQp0aFDh9RT4EttuummqSeUzAcffBADBw6MsWPHRuPGjVPPgZLwFQAgG7kFgJNOOikmTpwYhx9++De++I+IaNCgQey3337xyiuvxOGHH178gRmZO3duPPTQQ6lnFF1NTU2ce+65MX78+Nhtt92+8cV/RET37t3j9ttvj/vuuy+bG04NHz489QT4SptvvnnqCSX1/PPPx7777htLly5NPQVKQgAAspFTADjvvPPikksuiYYNG37rX9uoUaO47rrr4tBDDy3Csjw9/PDDWXz8/4Ybbogzzjgjamu//R8vdt9993j88cdjzTXXLMKy8nL33XenngBfqUePHisU76rJAw88EEcffXTU1dWlngJFJwAA2cglAOy7775x+umnr9IZNTU18ec//zm6d+9eoFV5e/DBB1NPKLozzzxzlaNR9+7d429/+9tKBYRK8uSTT8bChQtTz4Av1bRp0+jcuXPqGSU3ZMiQ+MlPfiICUPWq+39hAb7go48+Sj2h6Bo3bhyDBw8uyFmrr756XHbZZQU5K3fV/vH/LbfcMs4+++yCnNW3b99VfjRXuVuyZEk8/vjjqWfAV9p+++1TT0ji6quvjlNPPTX1DCgqAQDIRg4B4Mgjj4x11123YOf16dMn+vTpU7DzcjRp0qSYMmVK6hlFdfHFF0e9evUKdt5ZZ50Va621VsHOK0c53GWdytW7d+/UE5K58MIL45RTTvFJAKqWAABkYd68ebFs2bLUM4ruiCOOKPiZbgi4ap588snUE4qqZ8+eBX+x0LJlyzjmmGMKema5GTt2bOoJ8JVy/QTA5y666CJfB6BqCQBAFmbNmpV6QtF16NChKHdv3nvvvaN+fU+NXVn/+Mc/Uk8oqmOPPbYo5/74xz8uyrnl4rnnnovFixenngFfqmPHjtGpU6fUM5K6+uqr45hjjsnizQPyIgAAWcjh4/99+/YtyrnNmjWLnj17FuXsHFRzAGjQoEHsvffeRTm7Y8eOVf1zt3Tp0njuuedSz4CvNHDgwNQTkrv22mvj0EMPFQGoKgIAkIUcAsBOO+1UtLN33nnnop1dzRYuXBivvPJK6hlFs80220SLFi2Kdn7//v2LdnY5ePrpp1NPgK8kAPzTrbfeGvvuu28Wj3IlDwIAkIVFixalnlB0xQwAxfp0QbV79dVXY/ny5alnFM2OO+5Y0een9tJLL6WeAF9phx12KGrgqyTDhw+Pfffd1+M7qQoCAEAVaNeuXbRr165o5/fq1ct9AFZCtb/A++53v1vU87faaquinp/ayy+/nHoCfKUGDRrEnnvumXpG2bj33ntjjz32EAGoeAIAkIV58+alnlBU3bt3L+r5DRs2jE022aSo16hG1R4Aiv1z17x58+jYsWNRr5HShAkTqvoTIlS+Qw45JPWEsvLoo4/GLrvsEnPnzk09BVaaAABkodr/kL3ZZpsV/Ro9evQo+jWqzZtvvpl6QtHU1NSU5MX5+uuvX/RrpLJo0aJ4//33U8+Ar7TTTjsV9dNllejvf/977LrrrlncW4jqJAAAWaj2AFDsd2IjoiiPGKx2kydPTj2haNq2bRsNGjQo+nU6dOhQ9GukVM0/I1S+evXqxcEHH5x6RtkZP3587Ljjjlk8YpjqIwAAWaj2rwCU4l3Sbt26Ff0a1aSuri7eeuut1DOKZu211y7JdVq3bl2S66QiAFDujjjiiNQTytKECRNihx12iKlTp6aeAt+KAABQBUrxEc1q/i52MUyfPr2qHxu1xhprVNV1UhEAKHff+c53ol+/fqlnlKXXX389evfuHVOmTEk9BVaYAABQBdq3b18V16gm1f7d7ubNm5fkOk2aNCnJdVKZMWNG6gnwjf77v/879YSy9dZbb8W2225b1fd8oboIAAAVbo011ojVV1+96Ndp1qxZyV70VQPfDS2Man/8ZLWHIqpD//79o3PnzqlnlK33338/dtxxR4/2pCIIAAAVrpQvytu2bVuya1W6adOmpZ5QFZo2bZp6QlEJRVSC2tra+NWvfpV6RlmbNm1a9O3bt+of/0rlEwAAKlyLFi1Kdq1GjRqV7FqVzgs7VoSfEyrFIYccEuutt17qGWVt9uzZsf3228e4ceNST4GvJAAAVLiampqSXava340tpGp/8gSFMWfOnNQTYIU0bNgwTj/99NQzyt68efNi1113jcceeyz1FPhSAgBAhWvZsmXJrlXt38cuJAGAFeHnhEpyxBFHeCLMCpg3b17svvvuMXr06NRT4P8QAABYYaWMDZVu/vz5qSdQAerq6mLBggWpZ8AKadiwYVxwwQWpZ1SERYsWRf/+/eOee+5JPQX+FwEAAIrAO7usqMWLF6eeACts//33j169eqWeURGWLl0a++67b9x5552pp8C/CQAAAAn5BACVpKamJi699NLUMyrG0qVL48ADD4xbbrkl9RSICAEAAIpiyZIlqScAFEWvXr3ikEMOST2jYixfvjwOPvjguOqqq1JPAQEAAIph0aJFqScAFM0ll1wSrVq1Sj2jovzkJz+JwYMHp55B5gQAAICEPvnkk9QT4Ftr1apVXHzxxalnVJyTTjrJjRRJSgAAAEho6dKlqSfASjn00ENj5513Tj2j4px22mlx2mmnpZ5BpgQAAABgpVx//fUeEbsSLrjggvjFL34RdXV1qaeQGQEAAABYKe3bt4+rr7469YyKdMkll8RPfvITEYCSEgAAAICVtv/++8fBBx+cekZFuvrqq+PQQw+NZcuWpZ5CJgQAAABglVx55ZXRuXPn1DMq0s033xwHH3xwfPrpp6mnkAEBAAAAWCXNmjWLoUOHRuPGjVNPqUi333577LvvviIARScAAAAAq2zTTTeNa6+9NvWMinXvvffGgAEDYuHChamnUMUEAAAAoCB+9KMfxfHHH596RsUaNWpU7LHHHjFv3rzUU6hSAgAAAFAwl156afTr1y/1jIr16KOPxi677BJz585NPYUqJAAAAAAFU69evbjzzjuje/fuqadUrPHjx8euu+4qAlBwAgAAAFBQzZs3jxEjRkTbtm1TT6lYIgDFIAAAAAAF16FDhxg5cmQ0b9489ZSKNX78+OjTp0/MmjUr9RSqhAAAAAAURY8ePeKBBx6IRo0apZ5SsZ5//vno27evCEBBCAAAAEDRbLvttjFs2LBo0KBB6ikVa8KECTFgwABfB2CVCQAAAEBR9evXL+666y4RYBU8/fTTMXDgwFi4cGHqKVQwAQAAACi6gQMHigCr6PHHH4999tknPv3009RTqFACAAAAUBIiwKp78MEH44ADDohly5alnkIFEgAAAICSGThwYAwdOtSNAVfBsGHD4qijjoq6urrUU6gwAgAAAFBSe+yxR4wYMSKaNWuWekrFuuGGG+Lss89OPYMKIwAAAAAl17dv33j44YejRYsWqadUrHPOOSf+8pe/pJ5BBREAAACAJHr27BlPPPFEtGrVKvWUinXMMcfEAw88kHoGFUIAAAAAkunevXv8/e9/j3XXXTf1lIq0fPny2HfffePZZ59NPYUKIAAAAABJde7cOcaOHRsbbrhh6ikVaeHChTFgwICYOnVq6imUOQEAAABIrlOnTvHYY4/FpptumnpKRZoxY0bstddesXDhwtRTKGMCAAAAUBbat28fo0ePjq222ir1lIr03HPPxZFHHunxgHwlAQAAACgbrVu3jkceeSS23Xbb1FMq0u233x7nn39+6hmUKQEAAAAoKy1atIiHH344dtppp9RTKtKvf/3ruOeee1LPoAwJAAAAQNlp3Lhx3H///bHnnnumnlJx6urq4qCDDopJkyalnkKZEQAAAICy1LBhwxg6dGj86Ec/Sj2l4ixYsCB++MMfxuLFi1NPoYwIAAAAQNmqX79+3HjjjfHjH/849ZSK8+KLL8bxxx+fegZlRAAAAADKWr169eLqq6+On//856mnVJy//OUv7gfAvwkAAABA2aupqYmLL744zjrrrNRTKs7RRx8ds2bNSj2DMiAAAAAAFeO3v/1t/PGPf0w9o6LMnDkzfvKTn6SeQRmon3oAAAAr5+OPP47BgwennlFwbdu2jWOPPTb1DMrYySefHE2aNImf/exnsXz58tRzKsJdd90V9957r6cqZE4AAACoUB9//HH89re/TT2j4Hr06CEA8I2OO+64aN68eRx66KEiwAr66U9/Gn369ImmTZumnkIivgIAAABUpIMOOiiGDRsWDRo0SD2lIrz33ntxzjnnpJ5BQgIAAABQsQYOHBj33XdfNGrUKPWUijB48OCYPHly6hkkIgAAAAAVbZdddokHH3wwmjdvnnpK2fv000/j5JNPTj2DRAQAAACg4m2//fYxatSoaNWqVeopZW/YsGHx1FNPpZ5BAgIAAABQFbbeeusYPXp0tGvXLvWUsnfaaaelnkACAgAAAFA1unfvHo8//nh06NAh9ZSy9thjj8UjjzySegYlJgAAAABVZaONNoonn3wyNtxww9RTyponAuRHAAAAAKpO+/bt47HHHotu3bqlnlK2xowZ414AmREAAACAqtS+ffsYM2ZMbLrppqmnlK3f//73qSdQQgIAAABQtVq3bh2jR4+O7373u6mnlKURI0bEpEmTUs+gRAQAAACgqrVu3TpGjRoV22yzTeopZaeuri4uv/zy1DMoEQEAAACoei1atIiHHnpIBPgS119/fSxYsCD1DEpAAAAAALLweQTwdYD/bf78+XHbbbelnkEJCAAAAEA2WrRoEffff78bA/6Hv/71r6knUAICAAAAkJXPbwwoAvw/48aNi1dffTX1DIpMAAAAALLzeQTYaKONUk8pGzfeeGPqCRSZAAAAAGSpdevW8fDDD8c666yTekpZ+Nvf/pZ6AkUmAAAAANnq1KlTjBw5Mlq0aJF6SnKTJ0+OZ599NvUMikgAAAAAsta9e/e47777olGjRqmnJHfXXXelnkARCQAAAED2vv/978edd94ZtbV5v0QaOXJk6gkUUd4/3QAAAP+yxx57xGWXXZZ6RlIvvPBCzJw5M/UMikQAAAAA+Jef/exncdxxx6WekdTDDz+cegJFIgAAAAB8wZ/+9KfYZZddUs9IZvTo0aknUCQCAAAAwBfUr18/7rzzzujatWvqKUn84x//SD2BIhEAAAAA/kPLli3j//v//r9o3Lhx6ikl9/rrr8fHH3+cegZFUD/1AAAAIL3BgwfH4MGDU88ouIsuuij23Xfflfq1m2yySfz5z3+OQw45pMCryltdXV2MHz8+dt1119RTKDABAAAAiI8//jjefffd1DMKbsGCBav06w8++OAYMWJE3HHHHQVaVBmee+45AaAK+QoAAADA17jqqquiXbt2qWeU1IQJE1JPoAgEAAAAgK+xxhprxOWXX556RkkJANVJAAAAAPgG++yzT+yxxx6pZ5TM66+/Hp999lnqGRSYAAAAALACLr744mjQoEHq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XLCzNtxww1hrrbWyCynz58+P5557LvWM5OrVq+cTAFVMAKDsPf300/H000+nnlE0hx12mABQIuuss07qCSUxbdq0+NWvfhVXXHHFKp918803x7hx4wqwKl9bbbVV/OUvf0k9o2g++eST+M1vfhNXXnllwc4cOnRoPPXUUwU7rxx17969YDfYatiwYWy00UZZfMedr9a3b9+Cnrf11ltX/X04+HKbb755NGrUKPUMisQ9AIBs5PIJgIiIK6+8cpWfnT1p0qT42c9+VqBF+crhY5RXX311PProowU568MPP4yf/vSnBTmrnG2zzTYFPe973/teQc+jstSrVy922GGHgp7Zs2fPgp5H5dhuu+1ST6CIBAAgGw0bNswqAhx55JFx5513rtSvnTBhQvTp0yfmzZtX4FX52WyzzWKNNdZIPaOo6urqYr/99ovXXnttlc5ZuHBh7LnnnvHBBx8UaFn56t27d0HPEwDy9r3vfa8gX/v6Ii8C89WnT5/UEygiAQDISocOHVJPKJmlS5fG/vvvH6ecckp88sknK/RrFi1aFH/84x/ju9/9brz//vtFXpiH2tra2HbbbVPPKLrZs2fHdtttFw899NBK/frJkyfHdtttF//4xz8KvKw8CQAU0qBBgwp+5rbbbhsNGjQo+LmUt9ra2oL//kR5EQCArHTq1Cn1hJK76KKLYoMNNohf//rXMW7cuP/zmMDp06fHgw8+GMcff3ysv/768ctf/jKWLFmSaG11yuXdlI8++ij69esXBxxwwArf+PD999+PM844IzbZZJOqvlniF33nO9+Jtm3bFvTMTTbZJJo1a1bQM6kcP/zhDwt+ZuPGjX0NIENbbrlltGjRIvUMishNAIGs5BgAIiJmzpwZ5513Xpx33nkREbHmmmtGbW1tzJ8/34v9Eth9993j5JNPTj2jZO6444644447onPnztG3b9/o1q1brLPOOtGgQYOoq6uLmTNnxqRJk+LJJ5+M8ePHZ3f3+v79+xf8zHr16sUuu+wSQ4cOLfjZlLetttqqaJ9u22mnnWLs2LFFOZvyNGDAgNQTKDIBAMhK165dU08oCx999FHqCVnp1q1brL/++vH222+nnlJSkyZNikmTJqWeUXb22GOPopy75557CgAZ2nfffYt2dv/+/eO3v/1t0c6n/AgA1c9XAICsCACkUqwXfVSWZs2axfbbb1+Us3ffffeoqakpytmUp9ra2vjRj35UtPO32WabWHvttYt2PuVl7bXXjq222ir1DIpMAACy0q1bt9QTyNQ+++yTegJlYI899oiGDRsW5ew2bdr4znZmBgwYUNSb29bW1npHOCODBg2K2lovD6udf8NAVlq3bu3dDJLYYYcdol27dqlnkFgx362NiDjwwAOLej7l5dhjjy36NYrxhAHKUzFuJkn5EQCA7Gy55ZapJ5Ch2tpaL84yt8Yaa0S/fv2Keo2DDjqoaJ8woLx06tSpKDeU/E/9+vWLNdZYo+jXIa3WrVt7/F8mBAAgO1tssUXqCWTqoIMOSj2BhA444ICiP1d9rbXWir322quo16A8HHfccSX5uHbDhg1jv/32K/p1SGvfffeNevXqpZ5BCQgAQHa22Wab1BPI1JZbbhlbb7116hkkcswxx5TkOkceeWRJrkM6a621VvzkJz8p2fWK/dUV0jviiCNST6BEBAAgO9tuu23qCWSsFN/Zpfx873vfix49epTkWrvssosbnla5k08+OZo2bVqy622//fbRpUuXkl2P0urevXt897vfTT2DEhEAgOy0bt3aH2RI5oADDog111wz9QxKrJTv1tbW1sZpp51WsutRWi1atCh5SKypqYnjjjuupNekdHxqKC8CAJClHXfcMfUEMtW4ceP42c9+lnoGJdShQ4c44IADSnrNAw88MDp16lTSa1Iav/jFL6Jly5Ylv+7hhx8ejRs3Lvl1Ka4mTZrEYYcdlnoGJSQAAFkq9p244escf/zx0aRJk9QzKJFTTjkl6tevX9Jr1q9fP371q1+V9JoUX8eOHePkk09Ocu2WLVvGoYcemuTaFM/hhx+eJCiRjgAAZKlv374luXsyfJlWrVrFUUcdlXoGJdC2bdtkH6898sgjo3PnzkmuTXFceOGF0ahRo2TX/9WvfuVO8VWkpqYmjj/++NQzKDF/+gWytMYaa7gZIEn9+te/jmbNmqWeQZGdeeaZyV6wNWjQIC688MIk16bwdthhh+SP4+vUqZPHmVaRgQMHRteuXVPPoMQEACBbe++9d+oJZKxVq1bxy1/+MvUMiqhz587x4x//OOmGQYMGxe677550A6uufv368T//8z+pZ0RExOmnn+5TAFXi7LPPTj2BBAQAIFv77LNP6glk7qSTTor27dunnkGRXHjhhSX/7v+Xufzy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+OA466yzUs/gW9p8883j6aefjnPOOSeLSFUqe+21V0yYMCGOPvpo76b9y5577hmvvfZanH766T5evIJat24dN954Yzz88MM+WfUF//Vf/xWvvPJK7LvvvqmnVLzdd989nn/+eU/v4FsRAABWwA477BCPP/54VX5vs2/fvu4WXMEaNGgQv/71r2PixIlxwAEHpJ5T0TbeeON48MEHY/jw4d7t/hKNGzeO8847L1566aXYa6+9Us8pWzU1NXH00UfH66+/HocccojfW7/EeuutF3/729/ioYceio033jj1nIrTokWLuP766+O+++7zxB6+NQEAYAX16NEjnn322aq6AVufPn3i3nvv9Y5eFVhvvfXitttui3/84x/Rr1+/1HMqyoYbbhjXX399vPjii7HrrrumnlP2unbtGsOHD4/x48f7WfsPAwYMiOeeey6uueaaWHPNNVPPKXu77LJLvPzyy3HjjTe64eQKqKmpiaOOOiomTpwYhx9+eOo5VCgBAOBbWGutteKBBx6ICy+8sOIfa9S/f/8YMWJEVT7PPGe9evWKkSNHxj/+8Y/Yc889vfv4Nbp16xbXX399vP7663H44Ye7qeK3tPXWW//7Z23QoEFZ/6ztsMMOMXbs2BgxYkRsvvnmqedUlNra2jjkkEPi9ddfjyFDhsRmm22WelJZ6tevXzz33HNx7bXXxtprr516DhVMAAD4lurVqxennHJKPPPMM9GrV6/Uc1bKf//3f8c999zjxX8V69WrV9xzzz3xxhtvxPHHH++mW/9SU1MTu+22W4wcOTJeeeUVL/wLoFevXjFs2LB466234qSTTqrq+6V8Ub169WLfffeNsWPHxpgxY+L73/9+6kkVrX79+nHooYfGiy++GI888kjstdde/tuMf96T5KmnnoqRI0eKSxSEAACwkjbddNP4+9//Hrfddlt06tQp9ZwVss4668SIESPisssuiwYNGqSeQwlstNFG8ac//Sk++OCDuOmmm2KnnXbK8p3azp07x3nnnRdTpkyJ+++/P/r165fl/x+Kaf31149LLrkkpk2bFjfccEPV/qy1bt06fvGLX8Sbb74Zf/vb37zwL4K+ffvG8OHDY+rUqXHxxRdn96mANdZYI0444YR45ZVXYvjw4dGzZ8/Uk6giAgDAKqipqYkDDjggJk6cGEOGDInu3bunnvSlVl999TjxxBPjlVdeiQEDBqSeQwKNGzeOgw8+OEaNGhVTp06NK6+8Mnbeeeeqfodtk002iV//+tfx7LPPxhtvvBGnn366u7GXQJMmTeKwww6LUaNGxZQpU+KCCy6IXr16VXQMWH311eOAAw6IESNGxPvvvx8XXXRRxYTfSrb22mvHz3/+83jxxRfjjTfeiD/84Q8V/7P0VRo2bBh77LFH3HzzzTFt2rQYPHiwGyRSFDV1dXV1qUdQGC1btoy5c+emnsG3dNhhh8UNN9zwrX/dCy+8EFtssUXhB5WJYcOGxaBBg1LPWCmPPfZY3HrrrXHXXXfFnDlzkm5p2rRpHHLIIXHaaafFeuutt8rnDRo0KO6+++4CLCtPe+21VwwfPjz1jJL6+OOP49FHH41HHnkkHn744XjjjTdST1pprVq1ij59+sQuu+wSO+20U2ywwQapJ/EFM2bMiPvuuy/uvffeGDNmTPLfH79Ju3bton///rH77rtHv379fI2mjHz44Yfx6KOPxqhRo2L06NExadKk1JNWSps2bWLnnXeO/v37x8CBA6NFixapJ5EBAaCKzJ07N/zrrDwNGzZcqe9hL1u2LObPn1+EReWhSZMmFf8R9U8//TRGjx4dDz30UIwaNSpefvnlkly3YcOGsf3228dBBx0U++23XzRp0qRgZ3/yySexdOnSgp1Xbho0aFDQ/39VopkzZ8a4cePiqaeeivHjx8fLL78cM2bMSD3r/2jSpElsvPHGsfXWW0evXr1im222iS5dulTlO4PVaPny5TFhwoR4/PHH44knnohnnnkmJk+enHRTp06domfPntGzZ8/o27dvbLbZZn6eKsTs2bPj6aefjnHjxsUzzzwTEyZMiHfffTf1rP9jo402im222Sa22Wab6N27t58xkhAAAErkww8/jOeeey6effbZeOGFF2LSpEkxefLk+Pjjj1fp3DZt2kSPHj2iR48e0bt37+jdu3f2L2IprNmzZ8eECRPitddei7fffjveeeedmDx5crz33nsxe/bsWL58eVGu27Jly1h33XWjU6dOsf7668f6668fXbp0iU033TQ6duzoD85VZv78+fHSSy/Fiy++GK+//nq8/fbb//55++STTwp2nXXWWSe6dOkSnTt3jq5du8Z3vvOd2HrrraNNmzYFuwbpLViwIF577bV47bXX4p133vn3X++9915Mnz69oD9TX9SiRYt//77VpUuX6NatW3Tt2jW6d+/u0ZCUBQEAILGPP/44pk6dGh9++GHMmjUrPvroo1i4cGF89tlnsWDBgn//fZ9/KqJZs2axzjrrxLrrrhvrrLNOtGrVKuF6crd8+fKYPXt2zJo1K2bNmhXz5s2L+fPnx4IFC2LRokX/5+f4c6uvvnqsvvrq0aBBg2jatGm0aNEimjdvHi1atIi2bdtG69ato2HDhgn+iShHs2fPjg8//PB//fV5PF28eHEsXrz4339v8+bNo7a2Nho3bhxNmjSJVq1aRZs2bWLttdeO1q1bV/ynyyiMRYsWxaxZs2LGjBkxf/78mDdvXsybNy8++eSTWLJkyVd+0rJZs2ZRr169WH311aNFixbRsmXLaNmyZay55prRvn17AZ6yJwAAAABABjwFAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIwP8PWIabnjgcWq0AAAAASUVORK5CYII=',
scale: 3.508264580369843,
},
locked: false,
child: [],
parent: '5c11f494-5d02-4d65-a816-c9669c519065',
},
'930dca01-95e0-4527-be58-ede3cc41bc2e': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(255, 255, 255)',
fontFamily: 'Roboto',
fontSize: '38px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: null,
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'bold' },
{
type: 'color',
attrs: { color: 'rgb(255, 255, 255)' },
},
],
text: 'SCAN ME',
},
],
},
],
},
position: { x: 30.717362039152988, y: 393.1064513879045 },
boxSize: {
width: 333.60875418256376,
height: 64,
x: 1300.8495002212821,
y: 524.5,
},
scale: 1.2075471698113207,
rotate: 0,
fonts: [
{
name: 'Roboto',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold_Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
style: 'Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)', 'rgb(255, 255, 255)'],
fontSizes: [38],
},
locked: false,
child: [],
parent: '5c11f494-5d02-4d65-a816-c9669c519065',
},
},
},
],
img: '/assets/images/qr-code/2.png',
},
{
elements: [
{
rootId: '54751aa8-e4cd-46d9-9baa-231efde747ac',
layers: {
'54751aa8-e4cd-46d9-9baa-231efde747ac': {
type: { resolvedName: 'GroupLayer' },
props: {
position: { x: 1207.2199999999998, y: 147.90937608922968 },
boxSize: { width: 329.5600000000002, height: 462 },
scale: 1,
rotate: 0,
},
locked: false,
child: [
'fc9cdd05-0d4a-4eaa-a2ad-1ab579a68be1',
'9fa1b8a2-7771-4d17-b319-d551e4001836',
'd9d46596-6424-4787-a583-f0f9a9f475d8',
],
parent: 'ROOT',
},
'fc9cdd05-0d4a-4eaa-a2ad-1ab579a68be1': {
type: { resolvedName: 'SvgLayer' },
props: {
image:
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJjcmF5b24tdW5pcXVlLWlkLTI1LTAiIHZpZXdCb3g9IjAsMCwzODMuMTYwMDAzNjYyMTA5NCw1MzUuNTEwMDA5NzY1NjI1IiB3aWR0aD0iMTA3IiBoZWlnaHQ9IjE1MCIgZGF0YS1lZGl0YWJsZT0idHJ1ZSIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyI+PGRlZnM+PC9kZWZzPjxnIGlkPSJjcmF5b24tdW5pcXVlLWlkLTI1LTEiPjxyZWN0IHdpZHRoPSIzODMuMTYiIGhlaWdodD0iNTM1LjUxIiByeD0iMjEuNjUiIHJ5PSIyMS42NSI+PC9yZWN0PjxwYXRoIGQ9Im0xMzQuNTgsNDIxLjA5bDU1LjktMjQuMjhjLjcyLS4zMSwxLjQ3LS4zMSwyLjIsMGw1NS45LDI0LjI4Yy42Ny4yOS41NSwyLjAxLS4xNCwyLjAxaC0xMTMuNzJjLS42OSwwLS44LTEuNzItLjE0LTIuMDFaIiBmaWxsPSIjZmZmZmZmIj48L3BhdGg+PHJlY3QgeD0iMTUuNDEiIHk9IjE1LjciIHdpZHRoPSIzNTIuNTciIGhlaWdodD0iMzUyLjU3IiByeD0iMTYuNDciIHJ5PSIxNi40NyIgZmlsbD0iI2ZmZmZmZiI+PC9yZWN0PjwvZz48L3N2Zz4=',
position: { x: 2.2737367544323206e-13, y: 0 },
boxSize: { width: 329.56, height: 462 },
colors: ['rgb(0, 0, 0)', 'rgb(255, 255, 255)'],
rotate: 0,
},
locked: false,
child: [],
parent: '54751aa8-e4cd-46d9-9baa-231efde747ac',
},
'9fa1b8a2-7771-4d17-b319-d551e4001836': {
type: { resolvedName: 'QrCodeLayer' },
props: {
text: 'https://lidojs.com',
position: { x: 24.866770981508125, y: 25.24833839665183 },
boxSize: {
width: 279.8264580369843,
height: 279.8264580369843,
x: 1009.6934326710815,
y: 215.1577144858814,
},
rotate: 0,
bgColor: 'rgb(255, 255, 255)',
textColor: 'rgb(30, 30, 45)',
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAYAAAB/HSuDAAAACXBIWXMAAC4jAAAuIwF4pT92AABbQ0lEQVR4nO3defzVc/7//8f73UJ7qBSpLNWEZBlqjKWyFJEYYxnrxzKYGR/MMGMZzAyGMZbMxzbMIDvjVyGERGRG2cmSCElpIS1apN6/P2bM12c+ltQ553nOeV6vl4t/Phc9X3cfb03nds55vWrq6urqAgAAAKhqtakHAAAAAMUnAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIQP3UA4CV8/7778cf//jH1DOK5sgjj4zu3bunngEAAFVDAIAKNWvWrLjssstSzyia3r17CwAAAFBAvgIAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyED91AMAAAAKZenSpTF58uR48803Y+rUqTF9+vSYPn16zJo1K+bOnfvvv5YuXRrLli2L+fPn//vXNm7cOBo2bBgREY0aNYpmzZr9+68111wzWrduHW3atIl27dpFmzZtolOnTtGxY8do0KBBqn9c+FYEAAAAoCJ98MEHMX78+HjhhRfi2WefjQkTJsS7774by5YtW6nz5s6d+61/TW1tbay33nqxwQYbRLdu3WKzzTaLzTbbLDbddNNo1qzZSu2AYhEAqshVV10VS5YsST2j4DbeeOPYddddU88AIuLee++Nt956K/WMotlwww1jzz33TD0DKIHBgwennlA0xx13XKy22mqpZxTFhx9+GCNHjoxHH300xowZE2+++WbqSbF8+fJ499134913341HH3303//3mpqa6NatW3z/+9//918bbbRRwqUQUVNXV1eXegSF0bJly5WqluXusMMOixtuuCH1jLLzwgsvxBZbbJF6RtEMGzYsBg0alHoG/2HQoEFx9913p55RNHvttVcMHz489QygBGpqalJPKJo5c+ZEy5YtU88omClTpsTtt98e9957b/z973+P5cuXp5600tZff/3Yfffdo3///rHTTjtFo0aNUk8iMz4BAAAAlJWFCxfGbbfdFjfddFM8/vjjUS3vWb799ttxxRVXxBVXXBFNmjSJPffcM370ox/FrrvuWrWf2qC8eAoAAABQFiZPnhw///nPY911142jjjoqxowZUzUv/v/TJ598ErfffnsMHDgw2rVrFyeddFK88cYbqWdR5QQAAAAgqYkTJ8bhhx8eXbp0iUsvvTQ+/vjj1JNKas6cOTF48ODo2rVr7LLLLjFy5MjUk6hSAgAAAJDE+++/H4cffnh069YthgwZstJ3768mo0aNit122y169uwZw4cPr9pPQJCGAAAAAJTU4sWL45xzzokuXbrEkCFDvMj9EuPHj4+99947tttuuxg/fnzqOVQJAQAAACiZJ598MjbffPM466yzYuHChannlL2///3v0bNnzzj44INj1qxZqedQ4QQAAACg6JYsWRK/+MUvYvvtt4+JEyemnlNxbrnllujWrVvccsstqadQwQQAAACgqN58883Ydttt45JLLvFx/1Xw4YcfxsEHHxw/+MEPYs6cOannUIEEAAAAoGjuu+++2HLLLeO5555LPaVqDB06NL773e/Gs88+m3oKFUYAAAAAiuLiiy+OgQMHxvz581NPqTqTJ0+O73//+3HrrbemnkIFEQAAAICCqqurixNOOCFOPvnkWL58eeo5VWvJkiVx0EEHxQUXXJB6ChVCAAAAAApm2bJlceSRR8af/vSn1FOycdppp8Xxxx/v/gp8IwEAAAAoiLq6ujj88MPj+uuvTz0lO5dffnmceuqpqWdQ5gQAAACgIH72s5/FzTffnHpGti688MI444wzUs+gjAkAAADAKvvd734XV155ZeoZ2fv9738f11xzTeoZlCkBAAAAWCV33HFHnH322aln8C8//elP45FHHkk9gzIkAAAAACvtmWeeif/6r/9KPYMv+Oyzz+KHP/xhvPfee6mnUGYEAAAAYKXMnTs39t9//1i0aFHqKfyHOXPmxIEHHhifffZZ6imUEQEAAABYKUcddVRMnjw59Qy+wpNPPhm/+93vUs+gjAgAAADAt3bDDTfEXXfdlXoG3+D3v/99PPfcc6lnUCYEAAAA4Fv54IMP4sQTT0w9gxWwbNmyOPLII30VgIgQAAAAgG/puOOOi7lz56aewQp64YUX4pJLLkk9gzIgAAAAACts5MiRMXz48NQz+JbOPffcmDFjRuoZJCYAAAAAK+Szzz6Lk046KfUMVsL8+fPj17/+deoZJFY/9QBg5ay55ppx2GGHpZ5RNB06dEg9AQD4D1deeWW8/vrrqWewkv7617/GSSedFBtvvHHqKSQiAECF6tChQ9xwww2pZwAAmVi0aFGcf/75qWewCurq6uJ3v/td3H777amnkIivAAAAAN/oz3/+c3zwwQepZ7CK7rzzznj11VdTzyARAQAAAPhaixcvjvPOOy/1DAqgrq7Ov8uMCQAAAMDXuvnmm2P27NmpZ1Agd955Z7z//vupZ5CAAAAAAHylurq6GDx4cOoZFNBnn30WV1xxReoZJCAAAAAAX2n06NHxyiuvpJ5Bgf35z3+OxYsXp55BiQkAAADAV/rLX/6SegJF8NFHH8Xw4cNTz6DEBAAAAOBLzZkzJ4YNG5Z6BkVy3XXXpZ5AiQkAAADAl7r11ltjyZIlqWdQJKNGjYopU6aknkEJCQAAAMCXuvPOO1NPoIjq6ur8O86MAAAAAPwfM2fOjLFjx6aeQZHdddddqSdQQvVTDwDIxfLly+Pdd9+Nt99+O955552YMWNGfPTRR/HRRx/FsmXL4uOPP46IiNVWWy0aNWoU9erVi2bNmkWrVq2idevW0aZNm1h33XWjS5cu0bJly6T/LPC5uXPnxrRp0+L999+PGTNmxIcffhhz5879919Lly6Nurq6mDt37r9/TZMmTaJBgwYREdGyZcto0aLFv/9q165dtGvXLtZZZ51o06ZN1NTUpPpHg+wNHTo0li9fnnoGRTZu3LiYMmVKdOjQIfUUSkAAACiSmTNnxuOPPx6PPfZYPPvss/Hyyy/HJ598UpCz11577fjOd74TW265ZWy33Xax3XbbRZs2bQpyNnyZyZMnx/PPPx8vvfRSvPnmmzFx4sSYNGlSzJs3r2jXbNCgQWywwQbRtWvX2GijjWLjjTeOLbbYIjbddNNo2LBh0a4L/NOIESNST6BEhg4dGieeeGLqGZSAAAAVatGiRTFx4sTUM4pm/fXXjxYtWqSe8a299957ceutt8bw4cNj3LhxUVdXV5TrzJgxI2bMmBFjxoyJSy+9NCIiNt5449hnn31in332iS222KIo1yUPixcvjqeeeirGjBkTY8eOjaeffvp/vYNfKkuXLo2JEyf+n9/r6tevH927d49tt902dtxxx9h+++2jbdu2Jd8H1WzJkiXx6KOPpp5BiTzwwAMCQCYEAKhQEydOrOoXecOGDYtBgwalnrFC6urq4oEHHoj/+Z//iQcffLBoL/q/yauvvhqvvvpqnHvuudG5c+f46U9/GkcccUQ0a9YsyR4qy9tvvx333ntvjBgxIh5//PGyvuv3Z599Fs8//3w8//zzccUVV0RExCabbBIDBgyIPfbYI7bddtuoV69e4pVQ2caOHRsLFy5MPYMSGTNmTCxatCgaNWqUegpF5iaAAKtg+PDhsfnmm8eAAQNi5MiRyV78/6dJkybFiSeeGOuuu2788pe//Pf9BeCL3nvvvbjwwgtj8803jw022CBOOOGEePjhh8v6xf9XeeWVV+LCCy+MHXbYIdq0aRPHHntsjB07tmz+m4RKM2rUqNQTKKElS5bEY489lnoGJSAAAKyECRMmxI477hh77713vPTSS6nnfKX58+fHH//4x9hwww3jsssui88++yz1JBL77LPP4q677oq+fftGx44d41e/+lW8+OKLqWcV1EcffRR//vOfY/vtt49OnTrFueeeGx988EHqWVBRnnzyydQTKLFHHnkk9QRKQAAA+BaWLVsW55xzTmy11Vbx+OOPp56zwj766KM48cQTo1evXvHqq6+mnkMCc+bMiXPOOSc6duwYP/zhD+PRRx/N4t3xKVOmxJlnnhkdOnSIAw44IJ555pnUk6DsffrppzF+/PjUMyixSvpzDStPAABYQR988EHsvPPOcdZZZ8Wnn36aes5KefbZZ2PrrbeOm2++OfUUSmTGjBlx6qmnxnrrrRdnnXVWTJs2LfWkJJYuXRp33HFHbL311tG/f/8YM2ZM6klQtp555pmK/CoQq+a5556LBQsWpJ5BkQkAACvg5Zdfjq233roqvh+3cOHCOOSQQ+LMM8/M4h3gXC1YsCDOPvvs2GCDDeIPf/hDwR5BWQ0efPDB6N27d/Tr16+sv8IDqTz33HOpJ5DAsmXL4qmnnko9gyITAAC+wdixY2O77baLqVOnpp5SUOeee24cdthhsWzZstRTKKC6urr461//Gp07d47f/e537uL9NR566KHYfPPN44gjjoiZM2emngNl4/nnn089gUTGjRuXegJF5jGAAF9j3LhxMWDAgJg3b17qKUVx0003xbJly+LGG2/02LQq8Nprr8WPf/zjGDt2bOopFaOuri6uv/76GD58eFx44YVx5JFHRk1NTepZkFQuAaBt27ax4447Rvfu3aNTp07RpEmTiPjnPRDee++9ePHFF2P06NHx/vvvJ15aOs8++2zqCRSZAADwFSZOnBj9+vWr2hf/n7v11lujtrY2brzxRi98KtSyZcvi/PPPj3POOadi70+R2pw5c+Loo4+Om266KYYMGRKdOnVKPQmSWLZsWbzyyiupZxTV7rvvHieffHLsuOOOUVv79R+IrqurizFjxsR5552XxaMR3Si1+vkKAMCXmDNnTgwcODDmzp2bekpJ3HzzzXHGGWeknsFKeOedd6J3795x5plnevFfAI8//nj06NEjbr311tRTIIl33nmnan8vadGiRQwdOjTuu+++6NOnzze++I+IqKmpid69e8fDDz8ct912WzRt2rQES9N57733YtasWalnUEQCAMCXOPzww+ONN95IPaOkzj///LjuuutSz+BbuOeee6JHjx4+8l9g8+bNi4MOOij+67/+KxYvXpx6DpTUxIkTU08oipYtW8YTTzwRe++990qfccABB8SYMWOiefPmBVxWfl5++eXUEygiAQDgP1x99dVxzz33pJ6RxHHHHef7fxWgrq4ufvOb38Ree+1V9V9RSemGG26I7bffPt57773UU6BkqjV+33rrrdG9e/dVPmfLLbeMu+66qwCLyle1fwUkdwIAwBe89957ccopp6Sekcynn34a++23XzZffahECxcujB/84Afx29/+NvWULDzzzDPx3e9+152xycZbb72VekLBHXHEEbHbbrsV7LxddtkljjzyyIKdV25ef/311BMoIgEA4AtOOOGEWLBgQeoZSU2ePDlOOOGE1DP4EnPmzIldd901hg0blnpKVmbOnBl9+vSJ+++/P/UUKLpqe+RtgwYN4uyzzy74uWeeeeYK3UOgEr322mupJ1BE1flTC7ASRo8e7YXVvwwZMiQefPDB1DP4gqlTp8Z2220XTz75ZOopWVq0aFEMHDgwbrnlltRToKimTJmSekJBDRo0KDp06FDwczt27Bh9+/Yt+LnloFrvA8E/CQAA8c/vVP/yl79MPaOsHH300fHJJ5+knkH888V/796949VXX009JWvLli2LQw89VASgqlXbJwD233//op3dr1+/op2d0rRp02LJkiWpZ1AkAgBARNx9991ufvcf3nvvvfjDH/6Qekb2pk2bFr17967K7+VWouXLl4sAVK1ly5bFzJkzU88oqB133LFoZ2+11VZFOzu1d999N/UEikQAALJXV1fnhmpf4aKLLqq6d4Mqydy5c2O33Xbz4r/MfB4BRowYkXoKFNSHH36YekJBrbPOOtGqVauind++ffuinZ3a22+/nXoCRSIAANm7//7744UXXkg9oywtWrQozjzzzNQzsvTpp5/GPvvsEy+99FLqKXyJ5cuXx3777Rf/+Mc/Uk+Bgqm2AFCM7/5/0ZprrlnU81MSAKqXAABkb/DgwaknlLWbbrop3nzzzdQzsnPEEUfE6NGjU8/ga3x+Y8DJkyenngIFMXv27NQTCmqNNdYo6vn16tUr6vkpTZ8+PfUEikQAALI2YcKEGDVqVOoZZW3ZsmVx0UUXpZ6RlYsvvth3zCvE7NmzY9CgQW6YSVX46KOPUk8oqIYNG6aeULE++OCD1BMoEgEAyNq1116bekJFuO6662LatGmpZ2ThkUce8USKCvPyyy/HEUccEXV1damnwCqptpA1b9681BMqlk8AVC8BAMjW4sWL46abbko9oyIsXbo0rrnmmtQzqt706dPjwAMPjOXLl6eewrd05513xhVXXJF6BqyShQsXpp5QUNX2lYZSmjFjRuoJFIkAAGRrxIgRMWfOnNQzKsY111wTS5cuTT2jatXV1cXhhx8es2bNSj2FlXTyySfHhAkTUs+AlbZgwYLUEwrqnXfe8cmclVRtj4Pk/xEAgGzdeuutqSdUlOnTp8djjz2WekbVGjx4cDz00EOpZ7AKlixZEgceeGAsWbIk9RRYKfPnz089oaDmz5/vMaorqdruB8H/IwAAWVqwYEHcd999qWdUnGr7eGi5ePPNN+OMM85IPYMCmDBhQpx77rmpZ8BKWbZsWeoJBff888+nnlCR5s2b5+toVUoAALL0wAMPxKeffpp6BkRdXV0cc8wxsWjRotRTKJALLrjAVwGgTPz9739PPaFi+ZpkdRIAgCzdfffdqSdAREQMGTIkRo8enXoGBfTZZ5/FUUcd5bvHUAb87/3K+/jjj1NPoAgEACA7y5cvjwcffDD1DIgFCxbEaaedlnoGRTBu3Li45ZZbUs+A7L399ts+kbOSqu2eEPyTAABk5/nnn/doIMrC+eefHx988EHqGRTJqaee6r4ZUAb+9re/pZ5Qkfz+VZ0EACA7Dz/8cOoJEFOmTIlLLrkk9QyK6P3334+LLroo9QxYYbW11fnS4Nprr43PPvss9YyK415J1ak6/ysH+Bpjx45NPQHi97//fSxevDj1DIrskksu8T1aKkbz5s1TTyiK6dOnx/Dhw1PPqDhz585NPYEiEACArCxfvtwdgUluypQpcd1116WeQQnMnTs3Bg8enHoGrJBq/QRARMSf/vSn1BMqjk8AVKfq/a8c4EtMmjTJY21I7g9/+EMsXbo09QxKZPDgwbFgwYLUM+AbtWrVKvWEonniiSfiscceSz2jonzyySepJ1AEAgCQlRdeeCH1BDI3Z86cGDJkSOoZlNDcuXPj+uuvTz0DvtFaa62VekJRnXbaaR7PSfYEACArL774YuoJZO4vf/mLd1UydNlll8Xy5ctTz4CvVe0B4KmnnhLjyJ4AAGTFJwBIafny5XH55ZennkECb731Vtx///2pZ8DXatu2beoJRffLX/7S41fJWv3UAwBKSQAgpYceeiimTJmSegaJ/OUvf4k99tgj9Qz4Sm3bto369etX9SPzPvzwwzj66KPj3nvvXeWz6tWrFz169CjAqvLUsmXL1BMoAgEAyMbs2bNj+vTpqWeQsRtuuCH1BBK67777YubMmdGmTZvUU+BL1a9fPzp06BCTJ09OPaWoRowYEZdddlmccMIJq3ROs2bNvLFAxfEVACAbb775ZuoJZGzOnDkxbNiw1DNI6LPPPotbbrkl9Qz4WhtssEHqCSVxyimnxLhx41LPgJLzCQAgG++8807qCck0adIkdtppp9hiiy2ic+fO0bx582jcuHHMmTMnpk2bFk8//XQ89NBDMXPmzNRTq9bw4cOze6Zy+/bto3///rHZZpvFeuutFy1atIgFCxbErFmz4pVXXolHHnkkuxtz3nHHHXHSSSelngFfaaONNopRo0alnlF0S5cujUGDBsXTTz8d7du3Tz0HSkYAALKRYwDo1KlTnH322bH//vtHo0aNvvbvXbp0aQwbNixOPfXUePvtt0u0MB9Dhw5NPaFkttpqqzjnnHOif//+UVNT87V/78svvxznnXde3HHHHSVal9a4ceNiypQp0aFDh9RT4EttuummqSeUzAcffBADBw6MsWPHRuPGjVPPgZLwFQAgG7kFgJNOOikmTpwYhx9++De++I+IaNCgQey3337xyiuvxOGHH178gRmZO3duPPTQQ6lnFF1NTU2ce+65MX78+Nhtt92+8cV/RET37t3j9ttvj/vuuy+bG04NHz489QT4SptvvnnqCSX1/PPPx7777htLly5NPQVKQgAAspFTADjvvPPikksuiYYNG37rX9uoUaO47rrr4tBDDy3Csjw9/PDDWXz8/4Ybbogzzjgjamu//R8vdt9993j88cdjzTXXLMKy8nL33XenngBfqUePHisU76rJAw88EEcffXTU1dWlngJFJwAA2cglAOy7775x+umnr9IZNTU18ec//zm6d+9eoFV5e/DBB1NPKLozzzxzlaNR9+7d429/+9tKBYRK8uSTT8bChQtTz4Av1bRp0+jcuXPqGSU3ZMiQ+MlPfiICUPWq+39hAb7go48+Sj2h6Bo3bhyDBw8uyFmrr756XHbZZQU5K3fV/vH/LbfcMs4+++yCnNW3b99VfjRXuVuyZEk8/vjjqWfAV9p+++1TT0ji6quvjlNPPTX1DCgqAQDIRg4B4Mgjj4x11123YOf16dMn+vTpU7DzcjRp0qSYMmVK6hlFdfHFF0e9evUKdt5ZZ50Va621VsHOK0c53GWdytW7d+/UE5K58MIL45RTTvFJAKqWAABkYd68ebFs2bLUM4ruiCOOKPiZbgi4ap588snUE4qqZ8+eBX+x0LJlyzjmmGMKema5GTt2bOoJ8JVy/QTA5y666CJfB6BqCQBAFmbNmpV6QtF16NChKHdv3nvvvaN+fU+NXVn/+Mc/Uk8oqmOPPbYo5/74xz8uyrnl4rnnnovFixenngFfqmPHjtGpU6fUM5K6+uqr45hjjsnizQPyIgAAWcjh4/99+/YtyrnNmjWLnj17FuXsHFRzAGjQoEHsvffeRTm7Y8eOVf1zt3Tp0njuuedSz4CvNHDgwNQTkrv22mvj0EMPFQGoKgIAkIUcAsBOO+1UtLN33nnnop1dzRYuXBivvPJK6hlFs80220SLFi2Kdn7//v2LdnY5ePrpp1NPgK8kAPzTrbfeGvvuu28Wj3IlDwIAkIVFixalnlB0xQwAxfp0QbV79dVXY/ny5alnFM2OO+5Y0een9tJLL6WeAF9phx12KGrgqyTDhw+Pfffd1+M7qQoCAEAVaNeuXbRr165o5/fq1ct9AFZCtb/A++53v1vU87faaquinp/ayy+/nHoCfKUGDRrEnnvumXpG2bj33ntjjz32EAGoeAIAkIV58+alnlBU3bt3L+r5DRs2jE022aSo16hG1R4Aiv1z17x58+jYsWNRr5HShAkTqvoTIlS+Qw45JPWEsvLoo4/GLrvsEnPnzk09BVaaAABkodr/kL3ZZpsV/Ro9evQo+jWqzZtvvpl6QtHU1NSU5MX5+uuvX/RrpLJo0aJ4//33U8+Ar7TTTjsV9dNllejvf/977LrrrlncW4jqJAAAWaj2AFDsd2IjoiiPGKx2kydPTj2haNq2bRsNGjQo+nU6dOhQ9GukVM0/I1S+evXqxcEHH5x6RtkZP3587Ljjjlk8YpjqIwAAWaj2rwCU4l3Sbt26Ff0a1aSuri7eeuut1DOKZu211y7JdVq3bl2S66QiAFDujjjiiNQTytKECRNihx12iKlTp6aeAt+KAABQBUrxEc1q/i52MUyfPr2qHxu1xhprVNV1UhEAKHff+c53ol+/fqlnlKXXX389evfuHVOmTEk9BVaYAABQBdq3b18V16gm1f7d7ubNm5fkOk2aNCnJdVKZMWNG6gnwjf77v/879YSy9dZbb8W2225b1fd8oboIAAAVbo011ojVV1+96Ndp1qxZyV70VQPfDS2Man/8ZLWHIqpD//79o3PnzqlnlK33338/dtxxR4/2pCIIAAAVrpQvytu2bVuya1W6adOmpZ5QFZo2bZp6QlEJRVSC2tra+NWvfpV6RlmbNm1a9O3bt+of/0rlEwAAKlyLFi1Kdq1GjRqV7FqVzgs7VoSfEyrFIYccEuutt17qGWVt9uzZsf3228e4ceNST4GvJAAAVLiampqSXava340tpGp/8gSFMWfOnNQTYIU0bNgwTj/99NQzyt68efNi1113jcceeyz1FPhSAgBAhWvZsmXJrlXt38cuJAGAFeHnhEpyxBFHeCLMCpg3b17svvvuMXr06NRT4P8QAABYYaWMDZVu/vz5qSdQAerq6mLBggWpZ8AKadiwYVxwwQWpZ1SERYsWRf/+/eOee+5JPQX+FwEAAIrAO7usqMWLF6eeACts//33j169eqWeURGWLl0a++67b9x5552pp8C/CQAAAAn5BACVpKamJi699NLUMyrG0qVL48ADD4xbbrkl9RSICAEAAIpiyZIlqScAFEWvXr3ikEMOST2jYixfvjwOPvjguOqqq1JPAQEAAIph0aJFqScAFM0ll1wSrVq1Sj2jovzkJz+JwYMHp55B5gQAAICEPvnkk9QT4Ftr1apVXHzxxalnVJyTTjrJjRRJSgAAAEho6dKlqSfASjn00ENj5513Tj2j4px22mlx2mmnpZ5BpgQAAABgpVx//fUeEbsSLrjggvjFL34RdXV1qaeQGQEAAABYKe3bt4+rr7469YyKdMkll8RPfvITEYCSEgAAAICVtv/++8fBBx+cekZFuvrqq+PQQw+NZcuWpZ5CJgQAAABglVx55ZXRuXPn1DMq0s033xwHH3xwfPrpp6mnkAEBAAAAWCXNmjWLoUOHRuPGjVNPqUi333577LvvviIARScAAAAAq2zTTTeNa6+9NvWMinXvvffGgAEDYuHChamnUMUEAAAAoCB+9KMfxfHHH596RsUaNWpU7LHHHjFv3rzUU6hSAgAAAFAwl156afTr1y/1jIr16KOPxi677BJz585NPYUqJAAAAAAFU69evbjzzjuje/fuqadUrPHjx8euu+4qAlBwAgAAAFBQzZs3jxEjRkTbtm1TT6lYIgDFIAAAAAAF16FDhxg5cmQ0b9489ZSKNX78+OjTp0/MmjUr9RSqhAAAAAAURY8ePeKBBx6IRo0apZ5SsZ5//vno27evCEBBCAAAAEDRbLvttjFs2LBo0KBB6ikVa8KECTFgwABfB2CVCQAAAEBR9evXL+666y4RYBU8/fTTMXDgwFi4cGHqKVQwAQAAACi6gQMHigCr6PHHH4999tknPv3009RTqFACAAAAUBIiwKp78MEH44ADDohly5alnkIFEgAAAICSGThwYAwdOtSNAVfBsGHD4qijjoq6urrUU6gwAgAAAFBSe+yxR4wYMSKaNWuWekrFuuGGG+Lss89OPYMKIwAAAAAl17dv33j44YejRYsWqadUrHPOOSf+8pe/pJ5BBREAAACAJHr27BlPPPFEtGrVKvWUinXMMcfEAw88kHoGFUIAAAAAkunevXv8/e9/j3XXXTf1lIq0fPny2HfffePZZ59NPYUKIAAAAABJde7cOcaOHRsbbrhh6ikVaeHChTFgwICYOnVq6imUOQEAAABIrlOnTvHYY4/FpptumnpKRZoxY0bstddesXDhwtRTKGMCAAAAUBbat28fo0ePjq222ir1lIr03HPPxZFHHunxgHwlAQAAACgbrVu3jkceeSS23Xbb1FMq0u233x7nn39+6hmUKQEAAAAoKy1atIiHH344dtppp9RTKtKvf/3ruOeee1LPoAwJAAAAQNlp3Lhx3H///bHnnnumnlJx6urq4qCDDopJkyalnkKZEQAAAICy1LBhwxg6dGj86Ec/Sj2l4ixYsCB++MMfxuLFi1NPoYwIAAAAQNmqX79+3HjjjfHjH/849ZSK8+KLL8bxxx+fegZlRAAAAADKWr169eLqq6+On//856mnVJy//OUv7gfAvwkAAABA2aupqYmLL744zjrrrNRTKs7RRx8ds2bNSj2DMiAAAAAAFeO3v/1t/PGPf0w9o6LMnDkzfvKTn6SeQRmon3oAAAAr5+OPP47BgwennlFwbdu2jWOPPTb1DMrYySefHE2aNImf/exnsXz58tRzKsJdd90V9957r6cqZE4AAACoUB9//HH89re/TT2j4Hr06CEA8I2OO+64aN68eRx66KEiwAr66U9/Gn369ImmTZumnkIivgIAAABUpIMOOiiGDRsWDRo0SD2lIrz33ntxzjnnpJ5BQgIAAABQsQYOHBj33XdfNGrUKPWUijB48OCYPHly6hkkIgAAAAAVbZdddokHH3wwmjdvnnpK2fv000/j5JNPTj2DRAQAAACg4m2//fYxatSoaNWqVeopZW/YsGHx1FNPpZ5BAgIAAABQFbbeeusYPXp0tGvXLvWUsnfaaaelnkACAgAAAFA1unfvHo8//nh06NAh9ZSy9thjj8UjjzySegYlJgAAAABVZaONNoonn3wyNtxww9RTyponAuRHAAAAAKpO+/bt47HHHotu3bqlnlK2xowZ414AmREAAACAqtS+ffsYM2ZMbLrppqmnlK3f//73qSdQQgIAAABQtVq3bh2jR4+O7373u6mnlKURI0bEpEmTUs+gRAQAAACgqrVu3TpGjRoV22yzTeopZaeuri4uv/zy1DMoEQEAAACoei1atIiHHnpIBPgS119/fSxYsCD1DEpAAAAAALLweQTwdYD/bf78+XHbbbelnkEJCAAAAEA2WrRoEffff78bA/6Hv/71r6knUAICAAAAkJXPbwwoAvw/48aNi1dffTX1DIpMAAAAALLzeQTYaKONUk8pGzfeeGPqCRSZAAAAAGSpdevW8fDDD8c666yTekpZ+Nvf/pZ6AkUmAAAAANnq1KlTjBw5Mlq0aJF6SnKTJ0+OZ599NvUMikgAAAAAsta9e/e47777olGjRqmnJHfXXXelnkARCQAAAED2vv/978edd94ZtbV5v0QaOXJk6gkUUd4/3QAAAP+yxx57xGWXXZZ6RlIvvPBCzJw5M/UMikQAAAAA+Jef/exncdxxx6WekdTDDz+cegJFIgAAAAB8wZ/+9KfYZZddUs9IZvTo0aknUCQCAAAAwBfUr18/7rzzzujatWvqKUn84x//SD2BIhEAAAAA/kPLli3j//v//r9o3Lhx6ikl9/rrr8fHH3+cegZFUD/1AAAAIL3BgwfH4MGDU88ouIsuuij23Xfflfq1m2yySfz5z3+OQw45pMCryltdXV2MHz8+dt1119RTKDABAAAAiI8//jjefffd1DMKbsGCBav06w8++OAYMWJE3HHHHQVaVBmee+45AaAK+QoAAADA17jqqquiXbt2qWeU1IQJE1JPoAgEAAAAgK+xxhprxOWXX556RkkJANVJAAAAAPgG++yzT+yxxx6pZ5TM66+/Hp999lnqGRSYAAAAALACLr744mjQoEHq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XLCzNtxww1hrrbWyCynz58+P5557LvWM5OrVq+cTAFVMAKDsPf300/H000+nnlE0hx12mABQIuuss07qCSUxbdq0+NWvfhVXXHHFKp918803x7hx4wqwKl9bbbVV/OUvf0k9o2g++eST+M1vfhNXXnllwc4cOnRoPPXUUwU7rxx17969YDfYatiwYWy00UZZfMedr9a3b9+Cnrf11ltX/X04+HKbb755NGrUKPUMisQ9AIBs5PIJgIiIK6+8cpWfnT1p0qT42c9+VqBF+crhY5RXX311PProowU568MPP4yf/vSnBTmrnG2zzTYFPe973/teQc+jstSrVy922GGHgp7Zs2fPgp5H5dhuu+1ST6CIBAAgGw0bNswqAhx55JFx5513rtSvnTBhQvTp0yfmzZtX4FX52WyzzWKNNdZIPaOo6urqYr/99ovXXnttlc5ZuHBh7LnnnvHBBx8UaFn56t27d0HPEwDy9r3vfa8gX/v6Ii8C89WnT5/UEygiAQDISocOHVJPKJmlS5fG/vvvH6ecckp88sknK/RrFi1aFH/84x/ju9/9brz//vtFXpiH2tra2HbbbVPPKLrZs2fHdtttFw899NBK/frJkyfHdtttF//4xz8KvKw8CQAU0qBBgwp+5rbbbhsNGjQo+LmUt9ra2oL//kR5EQCArHTq1Cn1hJK76KKLYoMNNohf//rXMW7cuP/zmMDp06fHgw8+GMcff3ysv/768ctf/jKWLFmSaG11yuXdlI8++ij69esXBxxwwArf+PD999+PM844IzbZZJOqvlniF33nO9+Jtm3bFvTMTTbZJJo1a1bQM6kcP/zhDwt+ZuPGjX0NIENbbrlltGjRIvUMishNAIGs5BgAIiJmzpwZ5513Xpx33nkREbHmmmtGbW1tzJ8/34v9Eth9993j5JNPTj2jZO6444644447onPnztG3b9/o1q1brLPOOtGgQYOoq6uLmTNnxqRJk+LJJ5+M8ePHZ3f3+v79+xf8zHr16sUuu+wSQ4cOLfjZlLetttqqaJ9u22mnnWLs2LFFOZvyNGDAgNQTKDIBAMhK165dU08oCx999FHqCVnp1q1brL/++vH222+nnlJSkyZNikmTJqWeUXb22GOPopy75557CgAZ2nfffYt2dv/+/eO3v/1t0c6n/AgA1c9XAICsCACkUqwXfVSWZs2axfbbb1+Us3ffffeoqakpytmUp9ra2vjRj35UtPO32WabWHvttYt2PuVl7bXXjq222ir1DIpMAACy0q1bt9QTyNQ+++yTegJlYI899oiGDRsW5ew2bdr4znZmBgwYUNSb29bW1npHOCODBg2K2lovD6udf8NAVlq3bu3dDJLYYYcdol27dqlnkFgx362NiDjwwAOLej7l5dhjjy36NYrxhAHKUzFuJkn5EQCA7Gy55ZapJ5Ch2tpaL84yt8Yaa0S/fv2Keo2DDjqoaJ8woLx06tSpKDeU/E/9+vWLNdZYo+jXIa3WrVt7/F8mBAAgO1tssUXqCWTqoIMOSj2BhA444ICiP1d9rbXWir322quo16A8HHfccSX5uHbDhg1jv/32K/p1SGvfffeNevXqpZ5BCQgAQHa22Wab1BPI1JZbbhlbb7116hkkcswxx5TkOkceeWRJrkM6a621VvzkJz8p2fWK/dUV0jviiCNST6BEBAAgO9tuu23qCWSsFN/Zpfx873vfix49epTkWrvssosbnla5k08+OZo2bVqy622//fbRpUuXkl2P0urevXt897vfTT2DEhEAgOy0bt3aH2RI5oADDog111wz9QxKrJTv1tbW1sZpp51WsutRWi1atCh5SKypqYnjjjuupNekdHxqKC8CAJClHXfcMfUEMtW4ceP42c9+lnoGJdShQ4c44IADSnrNAw88MDp16lTSa1Iav/jFL6Jly5Ylv+7hhx8ejRs3Lvl1Ka4mTZrEYYcdlnoGJSQAAFkq9p244escf/zx0aRJk9QzKJFTTjkl6tevX9Jr1q9fP371q1+V9JoUX8eOHePkk09Ocu2WLVvGoYcemuTaFM/hhx+eJCiRjgAAZKlv374luXsyfJlWrVrFUUcdlXoGJdC2bdtkH6898sgjo3PnzkmuTXFceOGF0ahRo2TX/9WvfuVO8VWkpqYmjj/++NQzKDF/+gWytMYaa7gZIEn9+te/jmbNmqWeQZGdeeaZyV6wNWjQIC688MIk16bwdthhh+SP4+vUqZPHmVaRgQMHRteuXVPPoMQEACBbe++9d+oJZKxVq1bxy1/+MvUMiqhz587x4x//OOmGQYMGxe677550A6uufv368T//8z+pZ0RExOmnn+5TAFXi7LPPTj2BBAQAIFv77LNP6glk7qSTTor27dunnkGRXHjhhSX/7v+Xufzy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+OA466yzUs/gW9p8883j6aefjnPOOSeLSFUqe+21V0yYMCGOPvpo76b9y5577hmvvfZanH766T5evIJat24dN954Yzz88MM+WfUF//Vf/xWvvPJK7LvvvqmnVLzdd989nn/+eU/v4FsRAABWwA477BCPP/54VX5vs2/fvu4WXMEaNGgQv/71r2PixIlxwAEHpJ5T0TbeeON48MEHY/jw4d7t/hKNGzeO8847L1566aXYa6+9Us8pWzU1NXH00UfH66+/HocccojfW7/EeuutF3/729/ioYceio033jj1nIrTokWLuP766+O+++7zxB6+NQEAYAX16NEjnn322aq6AVufPn3i3nvv9Y5eFVhvvfXitttui3/84x/Rr1+/1HMqyoYbbhjXX399vPjii7HrrrumnlP2unbtGsOHD4/x48f7WfsPAwYMiOeeey6uueaaWHPNNVPPKXu77LJLvPzyy3HjjTe64eQKqKmpiaOOOiomTpwYhx9+eOo5VCgBAOBbWGutteKBBx6ICy+8sOIfa9S/f/8YMWJEVT7PPGe9evWKkSNHxj/+8Y/Yc889vfv4Nbp16xbXX399vP7663H44Ye7qeK3tPXWW//7Z23QoEFZ/6ztsMMOMXbs2BgxYkRsvvnmqedUlNra2jjkkEPi9ddfjyFDhsRmm22WelJZ6tevXzz33HNx7bXXxtprr516DhVMAAD4lurVqxennHJKPPPMM9GrV6/Uc1bKf//3f8c999zjxX8V69WrV9xzzz3xxhtvxPHHH++mW/9SU1MTu+22W4wcOTJeeeUVL/wLoFevXjFs2LB466234qSTTqrq+6V8Ub169WLfffeNsWPHxpgxY+L73/9+6kkVrX79+nHooYfGiy++GI888kjstdde/tuMf96T5KmnnoqRI0eKSxSEAACwkjbddNP4+9//Hrfddlt06tQp9ZwVss4668SIESPisssuiwYNGqSeQwlstNFG8ac//Sk++OCDuOmmm2KnnXbK8p3azp07x3nnnRdTpkyJ+++/P/r165fl/x+Kaf31149LLrkkpk2bFjfccEPV/qy1bt06fvGLX8Sbb74Zf/vb37zwL4K+ffvG8OHDY+rUqXHxxRdn96mANdZYI0444YR45ZVXYvjw4dGzZ8/Uk6giAgDAKqipqYkDDjggJk6cGEOGDInu3bunnvSlVl999TjxxBPjlVdeiQEDBqSeQwKNGzeOgw8+OEaNGhVTp06NK6+8Mnbeeeeqfodtk002iV//+tfx7LPPxhtvvBGnn366u7GXQJMmTeKwww6LUaNGxZQpU+KCCy6IXr16VXQMWH311eOAAw6IESNGxPvvvx8XXXRRxYTfSrb22mvHz3/+83jxxRfjjTfeiD/84Q8V/7P0VRo2bBh77LFH3HzzzTFt2rQYPHiwGyRSFDV1dXV1qUdQGC1btoy5c+emnsG3dNhhh8UNN9zwrX/dCy+8EFtssUXhB5WJYcOGxaBBg1LPWCmPPfZY3HrrrXHXXXfFnDlzkm5p2rRpHHLIIXHaaafFeuutt8rnDRo0KO6+++4CLCtPe+21VwwfPjz1jJL6+OOP49FHH41HHnkkHn744XjjjTdST1pprVq1ij59+sQuu+wSO+20U2ywwQapJ/EFM2bMiPvuuy/uvffeGDNmTPLfH79Ju3bton///rH77rtHv379fI2mjHz44Yfx6KOPxqhRo2L06NExadKk1JNWSps2bWLnnXeO/v37x8CBA6NFixapJ5EBAaCKzJ07N/zrrDwNGzZcqe9hL1u2LObPn1+EReWhSZMmFf8R9U8//TRGjx4dDz30UIwaNSpefvnlkly3YcOGsf3228dBBx0U++23XzRp0qRgZ3/yySexdOnSgp1Xbho0aFDQ/39VopkzZ8a4cePiqaeeivHjx8fLL78cM2bMSD3r/2jSpElsvPHGsfXWW0evXr1im222iS5dulTlO4PVaPny5TFhwoR4/PHH44knnohnnnkmJk+enHRTp06domfPntGzZ8/o27dvbLbZZn6eKsTs2bPj6aefjnHjxsUzzzwTEyZMiHfffTf1rP9jo402im222Sa22Wab6N27t58xkhAAAErkww8/jOeeey6effbZeOGFF2LSpEkxefLk+Pjjj1fp3DZt2kSPHj2iR48e0bt37+jdu3f2L2IprNmzZ8eECRPitddei7fffjveeeedmDx5crz33nsxe/bsWL58eVGu27Jly1h33XWjU6dOsf7668f6668fXbp0iU033TQ6duzoD85VZv78+fHSSy/Fiy++GK+//nq8/fbb//55++STTwp2nXXWWSe6dOkSnTt3jq5du8Z3vvOd2HrrraNNmzYFuwbpLViwIF577bV47bXX4p133vn3X++9915Mnz69oD9TX9SiRYt//77VpUuX6NatW3Tt2jW6d+/u0ZCUBQEAILGPP/44pk6dGh9++GHMmjUrPvroo1i4cGF89tlnsWDBgn//fZ9/KqJZs2axzjrrxLrrrhvrrLNOtGrVKuF6crd8+fKYPXt2zJo1K2bNmhXz5s2L+fPnx4IFC2LRokX/5+f4c6uvvnqsvvrq0aBBg2jatGm0aNEimjdvHi1atIi2bdtG69ato2HDhgn+iShHs2fPjg8//PB//fV5PF28eHEsXrz4339v8+bNo7a2Nho3bhxNmjSJVq1aRZs2bWLttdeO1q1bV/ynyyiMRYsWxaxZs2LGjBkxf/78mDdvXsybNy8++eSTWLJkyVd+0rJZs2ZRr169WH311aNFixbRsmXLaNmyZay55prRvn17AZ6yJwAAAABABjwFAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIgAAAAAAAGRAAAAAAIAMCAAAAAGRAAAAAAIAMCAAAAACQAQEAAAAAMiAAAAAAQAYEAAAAAMiAAAAAAAAZEAAAAAAgAwIAAAAAZEAAAAAAgAwIAAAAAJABAQAAAAAyIAAAAABABgQAAAAAyIAAAAAAABkQAAAAACADAgAAAABkQAAAAACADAgAAAAAkAEBAAAAADIgAAAAAEAGBAAAAADIwP8PWIabnjgcWq0AAAAASUVORK5CYII=',
scale: 2.7982645803698425,
},
locked: false,
child: [],
parent: '54751aa8-e4cd-46d9-9baa-231efde747ac',
},
'd9d46596-6424-4787-a583-f0f9a9f475d8': {
type: { resolvedName: 'TextLayer' },
props: {
doc: {
type: 'doc',
content: [
{
type: 'paragraph',
attrs: {
textAlign: 'center',
color: 'rgb(255, 255, 255)',
fontFamily: 'Roboto',
fontSize: '38px',
lineHeight: '1.4',
letterSpacing: 0,
textTransform: null,
marginLeft: null,
indent: 0,
listType: '',
},
content: [
{
type: 'text',
marks: [
{ type: 'bold' },
{
type: 'color',
attrs: { color: 'rgb(255, 255, 255)' },
},
],
text: 'SCAN ME',
},
],
},
],
},
position: { x: 0, y: 382.98417252286583 },
boxSize: {
width: 325.60875418256376,
height: 64,
x: 1016.2199999999999,
y: 530.8935486120955,
},
scale: 1.2075471698113207,
rotate: 0,
fonts: [
{
name: 'Roboto',
fonts: [
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold_Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
style: 'Bold',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Bold.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
style: 'Italic',
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
{
urls: [
'https://lidojs-fonts.s3.us-east-2.amazonaws.com/Roboto/Roboto-Regular.woff2',
],
},
],
},
],
colors: ['rgb(0, 0, 0)', 'rgb(255, 255, 255)'],
fontSizes: [38],
},
locked: false,
child: [],
parent: '54751aa8-e4cd-46d9-9baa-231efde747ac',
},
},
},
],
img: '/assets/images/qr-code/3.png',
},
];
================================================
FILE: src/features/design/config/shape.tsx
================================================
import ArrowBottomIcon from '@duyank/icons/shape/ArrowBottom';
import ArrowLeftIcon from '@duyank/icons/shape/ArrowLeft';
import ArrowPentagonIcon from '@duyank/icons/shape/ArrowPentagon';
import ArrowRightIcon from '@duyank/icons/shape/ArrowRight';
import ArrowTopIcon from '@duyank/icons/shape/ArrowTop';
import ChevronIcon from '@duyank/icons/shape/Chevron';
import CircleIcon from '@duyank/icons/shape/Circle';
import CrossIcon from '@duyank/icons/shape/Cross';
import HexagonIcon from '@duyank/icons/shape/Hexagon';
import OctagonIcon from '@duyank/icons/shape/Octagon';
import ParallelogramIcon from '@duyank/icons/shape/Parallelogram';
import PentagonIcon from '@duyank/icons/shape/Pentagon';
import RectangleIcon from '@duyank/icons/shape/Rectangle';
import RhombusIcon from '@duyank/icons/shape/Rhombus';
import TrapezoidIcon from '@duyank/icons/shape/Trapezoid';
import TriangleIcon from '@duyank/icons/shape/Triangle';
import type { CSSObject } from '@emotion/react';
import type { ShapeType } from '@lidojs/design-core';
import type { FC, PropsWithChildren, ReactElement } from 'react';
export type Shape = {
type: ShapeType;
width: number;
height: number;
icon: ReactElement;
};
const IconBox: FC> = ({
children,
extraCss = {},
}) => {
return (
{children}
);
};
export const shapes: Shape[] = [
{
type: 'rectangle',
width: 64,
height: 64,
icon: (
),
},
{
type: 'circle',
width: 64,
height: 64,
icon: (
),
},
{
type: 'triangle',
width: 64,
height: 56,
icon: (
),
},
{
type: 'triangleUpsideDown',
width: 64,
height: 56,
icon: (
),
},
{
type: 'rhombus',
width: 64,
height: 64,
icon: (
),
},
{
type: 'arrowRight',
width: 64,
height: 64,
icon: (
),
},
{
type: 'arrowLeft',
width: 64,
height: 64,
icon: (
),
},
{
type: 'arrowTop',
width: 64,
height: 64,
icon: (
),
},
{
type: 'arrowBottom',
width: 64,
height: 64,
icon: (
),
},
{
type: 'arrowPentagon',
width: 64,
height: 32,
icon: (
),
},
{
type: 'chevron',
width: 64,
height: 32,
icon: (
),
},
{
type: 'cross',
width: 64,
height: 64,
icon: (
),
},
{
type: 'parallelogram',
width: 64,
height: 48,
icon: (
),
},
{
type: 'parallelogramUpsideDown',
width: 64,
height: 48,
icon: (
),
},
{
type: 'trapezoid',
width: 64,
height: 48,
icon: (
),
},
{
type: 'trapezoidUpsideDown',
width: 64,
height: 48,
icon: (
),
},
{
type: 'pentagon',
width: 64,
height: 64,
icon: (
),
},
{
type: 'hexagonVertical',
width: 55,
height: 64,
icon: (
),
},
{
type: 'hexagonHorizontal',
width: 64,
height: 55,
icon: (
),
},
{
type: 'octagon',
width: 64,
height: 64,
icon: (
),
},
];
================================================
FILE: src/features/design/pages/DesignPage.tsx
================================================
'use client';
import type { FontData } from '@lidojs/design-core';
import axios from 'axios';
import { useEffect, useState } from 'react';
import { LidoJSEditor } from '../components';
type FontVariant =
| 'regular'
| 'italic'
| '100'
| '200'
| '300'
| '400'
| '500'
| '600'
| '700'
| '800'
| '900';
export const DesignPage = () => {
const [googleFontList, setGoogleFontList] = useState([]);
useEffect(() => {
const getFont = async () => {
const data = await axios.get<{
items: {
family: string;
variants: FontVariant[];
files: Record;
}[];
}>(
`https://www.googleapis.com/webfonts/v1/webfonts?key=${process.env.FONT_API_KEY}`,
);
const items = data.data.items;
const res: FontData[] = items.map((i) => {
const fonts = Object.entries(i.files).reduce(
(acc, [fontWeight, file]) => {
if (fontWeight === 'regular' || fontWeight === '400') {
if (i.variants.includes('italic')) {
acc.push({
style: 'Italic',
urls: [file],
});
}
acc.push({
urls: [file],
});
} else if (fontWeight === '600') {
if (i.variants.includes('italic')) {
acc.push({
style: 'Bold_Italic',
urls: [file],
});
}
acc.push({
style: 'Bold',
urls: [file],
});
}
return acc;
},
[] as FontData['fonts'],
);
return {
name: i.family,
fonts: fonts,
};
});
setGoogleFontList(res);
};
getFont();
}, []);
return ;
};
================================================
FILE: src/features/design/pages/index.ts
================================================
export * from './DesignPage';
================================================
FILE: src/main.tsx
================================================
import * as ReactDOM from 'react-dom/client';
import './styles.css';
import axios from 'axios';
import Page from './pages/Main';
axios.defaults.baseURL = process.env.API_ENDPOINT;
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);
root.render( );
================================================
FILE: src/pages/Main.tsx
================================================
import { DesignPage } from '../features/design/pages';
export default function Page() {
return ;
}
================================================
FILE: src/shared/components/index.ts
================================================
export * from './masonry';
================================================
FILE: src/shared/components/masonry/Masonry.tsx
================================================
import React, { useCallback, useEffect, useRef, useState } from 'react';
interface MasonryProps {
children: React.ReactNode;
columnsCount?: number;
gutter?: string;
className?: string | null;
style?: React.CSSProperties;
containerTag?: string;
itemTag?: string;
itemStyle?: React.CSSProperties;
sequential?: boolean;
}
interface ColumnData {
columns: React.ReactNode[][];
childRefs: React.RefObject[];
}
const Masonry: React.FC = ({
children,
columnsCount = 3,
gutter = '0',
className = null,
style = {},
containerTag = 'div',
itemTag = 'div',
itemStyle = {},
sequential = false,
}) => {
const [state, setState] = useState<
ColumnData & {
hasDistributed: boolean;
children: React.ReactNode;
}
>({
columns: [],
childRefs: [],
hasDistributed: false,
children: null,
});
const prevChildrenRef = useRef(null);
const prevColumnsCountRef = useRef(columnsCount);
const getEqualCountColumns = useCallback(
(children: React.ReactNode, columnsCount: number): ColumnData => {
const columns: React.ReactNode[][] = Array.from(
{ length: columnsCount },
() => [],
);
let validIndex = 0;
const childRefs: React.RefObject[] = [];
React.Children.forEach(children, (child) => {
if (child && React.isValidElement(child)) {
const ref = React.createRef();
childRefs.push(ref);
columns[validIndex % columnsCount].push(
{child}
,
);
validIndex++;
}
});
return { columns, childRefs };
},
[],
);
const distributeChildren = useCallback(() => {
const columnHeights = Array(columnsCount).fill(0);
const isReady = state.childRefs.every(
(ref) => ref.current?.getBoundingClientRect().height,
);
if (!isReady) return;
const columns: React.ReactNode[][] = Array.from(
{ length: columnsCount },
() => [],
);
let validIndex = 0;
React.Children.forEach(children, (child) => {
if (child && React.isValidElement(child)) {
const childHeight =
state.childRefs[validIndex].current?.getBoundingClientRect().height ||
0;
const minHeightColumnIndex = columnHeights.indexOf(
Math.min(...columnHeights),
);
columnHeights[minHeightColumnIndex] += childHeight;
columns[minHeightColumnIndex].push(child);
validIndex++;
}
});
setState((prev) => ({ ...prev, columns, hasDistributed: true }));
}, [children, columnsCount, state.childRefs]);
useEffect(() => {
// Check if children or columnsCount have changed by comparing current vs previous
const childrenChanged = prevChildrenRef.current !== children;
const columnsCountChanged = prevColumnsCountRef.current !== columnsCount;
if (childrenChanged || columnsCountChanged) {
const newState = getEqualCountColumns(children, columnsCount);
setState((prev) => ({
...prev,
...newState,
children,
hasDistributed: false,
}));
// Update refs to current values
prevChildrenRef.current = children;
prevColumnsCountRef.current = columnsCount;
}
}, [children, columnsCount, getEqualCountColumns]);
useEffect(() => {
if (!state.hasDistributed && !sequential) {
distributeChildren();
}
}, [state.hasDistributed, sequential, distributeChildren]);
const renderColumns = () => {
return state.columns.map((column, i) =>
React.createElement(
itemTag,
{
key: i,
style: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignContent: 'stretch',
flex: 1,
width: 0,
gap: gutter,
...itemStyle,
},
},
column.map((item) => item),
),
);
};
return React.createElement(
containerTag,
{
style: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignContent: 'stretch',
boxSizing: 'border-box',
width: '100%',
gap: gutter,
...style,
},
className,
},
renderColumns(),
);
};
export default Masonry;
================================================
FILE: src/shared/components/masonry/index.ts
================================================
export * from './Masonry';
================================================
FILE: src/shared/icons/pencil/Highlighter.tsx
================================================
import type { ComponentProps, FC } from 'react';
export const Highlighter: FC> = (props) => {
return (
);
};
================================================
FILE: src/shared/icons/pencil/Marker.tsx
================================================
import type { ComponentProps, FC } from 'react';
export const Marker: FC> = (props) => {
return (
);
};
================================================
FILE: src/shared/icons/pencil/Pencil.tsx
================================================
import type { ComponentProps, FC } from 'react';
export const Pencil: FC> = (props) => {
return (
);
};
================================================
FILE: src/shared/theme/index.ts
================================================
export * from './palette';
export * from './theme';
================================================
FILE: src/shared/theme/palette.ts
================================================
// Helper function to convert hex to rgb values
const hexToRgb = (hex: string) => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? `${Number.parseInt(result[1], 16)}, ${Number.parseInt(result[2], 16)}, ${Number.parseInt(result[3], 16)}`
: null;
};
// Helper function to create rgba from hex
export const rgba = (hex: string, alpha: number) => {
const rgb = hexToRgb(hex);
return rgb ? `rgba(${rgb}, ${alpha})` : hex;
};
// Main colors
const primary = '#735DFF';
const secondary = '#FF5A29';
const error = '#FF383C';
const warning = '#FF9A13';
const info = '#0C9CFC';
const success = '#0CC763';
const dark = '#0A0A0A';
export const palette = {
mode: 'light',
header: {
main: '#61748f',
},
primary: {
main: primary,
light: rgba(primary, 0.3),
dark: rgba(primary, 0.8),
contrastText: '#fff',
},
secondary: {
main: secondary,
light: rgba(secondary, 0.3),
dark: rgba(secondary, 0.8),
contrastText: '#fff',
},
error: {
main: error,
light: rgba(error, 0.3),
dark: rgba(error, 0.8),
contrastText: '#fff',
},
warning: {
main: warning,
light: rgba(warning, 0.3),
dark: rgba(warning, 0.8),
contrastText: '#fff',
},
info: {
main: info,
light: rgba(info, 0.3),
dark: rgba(info, 0.8),
contrastText: '#fff',
},
success: {
main: success,
light: rgba(success, 0.3),
dark: rgba(success, 0.8),
contrastText: '#fff',
},
grey: {
50: '#f9fafb',
100: '#f2f4f5',
200: '#e6eaeb',
300: '#dbdfe1',
400: '#949eb7',
500: '#7987a1',
600: '#4d5875',
700: '#383853',
800: '#323251',
900: '#110f0f',
A100: '#8699A3',
A200: rgba('#8699A3', 0.2),
A400: rgba('#8699A3', 0.4),
A700: rgba('#8699A3', 0.7),
},
text: {
primary: '#222f36',
secondary: '#98a5c3',
disabled: rgba(dark, 0.38),
},
divider: '#e6eff1',
background: {
default: '#f5f6fa',
paper: '#ffffff',
},
action: {
active: rgba(dark, 0.54),
hover: rgba(dark, 0.04),
hoverOpacity: 0.04,
selected: rgba(dark, 0.08),
selectedOpacity: 0.08,
disabled: rgba(dark, 0.26),
disabledBackground: rgba(dark, 0.12),
disabledOpacity: 0.38,
focus: rgba(dark, 0.12),
focusOpacity: 0.12,
activatedOpacity: 0.12,
},
} as const;
// Additional custom colors that can be used with sx prop or styled components
export const extendedColors = {
blue: '#0082FF',
indigo: '#4d5ddb',
yellow: '#fff621',
teal: '#00D8D8',
orange: '#FE7C58',
purple: '#7B76FE',
pink: '#FE549B',
cyan: '#00D1D1',
};
// Gradient backgrounds
export const gradients = {
primary: `linear-gradient(to bottom right, ${primary} 0%, ${secondary} 100%)`,
secondary: `linear-gradient(to bottom right, ${secondary} 0%, #970312 100%)`,
warning: `linear-gradient(to bottom right, ${warning} 0%, #4b5002 100%)`,
info: `linear-gradient(to bottom right, ${info} 0%, #00428d 100%)`,
success: `linear-gradient(to bottom right, ${success} 0%, #035643 100%)`,
danger: `linear-gradient(to bottom right, ${error} 0%, #DE4980 100%)`,
orange: 'linear-gradient(to bottom right, #FE7C58 0%, #c3072d 100%)',
purple: 'linear-gradient(to bottom right, #7B76FE 0%, #0046d1 100%)',
teal: 'linear-gradient(to bottom right, #00D8D8 0%, #086a5a 100%)',
light: 'linear-gradient(to bottom right, #F7F8FA 0%, #D7FCFF 100%)',
dark: 'linear-gradient(to bottom right, #0A0A0A 0%, #16657A 100%)',
};
// Dark mode palette override
export const darkPalette = {
...palette,
background: {
default: '#191814',
paper: '#232226',
},
text: {
primary: rgba('#ffffff', 0.8),
secondary: rgba('#ffffff', 0.5),
disabled: rgba('#ffffff', 0.38),
},
action: {
active: rgba('#ffffff', 0.54),
hover: rgba('#ffffff', 0.04),
selected: rgba('#ffffff', 0.08),
disabled: rgba('#ffffff', 0.26),
disabledBackground: rgba('#ffffff', 0.12),
},
} as const;
================================================
FILE: src/shared/theme/theme.ts
================================================
'use client';
import { alpha, createTheme } from '@mui/material/styles';
import { palette, rgba } from './palette';
declare module '@mui/material/styles' {
interface Palette {
sidebar: {
background: string;
textColor: string;
activeBackground: string;
hoverBackground: string;
};
}
interface PaletteOptions {
sidebar: {
background: string;
textColor: string;
activeBackground: string;
hoverBackground: string;
};
}
}
const themeOptions = {
palette: {
primary: {
main: 'rgb(115, 93, 255)', // --primary-rgb
light: alpha('rgb(115, 93, 255)', 0.1),
},
secondary: {
main: 'rgb(255, 90, 41)', // --secondary-rgb
},
text: {
primary: '#222f36', // --default-text-color
secondary: '#657a99', // --menu-prime-color
},
background: {
default: 'rgb(245, 246, 250)', // --body-bg-rgb
paper: '#ffffff', // --menu-bg
},
divider: '#e6eff1', // --menu-border-color
sidebar: {
background: '#ffffff',
textColor: '#657a99',
activeBackground: alpha('rgb(115, 93, 255)', 0.1),
hoverBackground: alpha('rgb(115, 93, 255)', 0.05),
},
},
typography: {
fontFamily: 'inherit',
fontWeightRegular: 400,
fontWeightMedium: 500,
fontWeightBold: 700,
h1: {
fontSize: '2.5rem', // 40px
fontWeight: 700,
lineHeight: 1.2,
},
h2: {
fontSize: '2rem', // 32px
fontWeight: 700,
lineHeight: 1.2,
},
h3: {
fontSize: '1.75rem', // 28px
fontWeight: 600,
lineHeight: 1.2,
},
h4: {
fontSize: '1.5rem', // 24px
fontWeight: 600,
lineHeight: 1.2,
},
h5: {
fontSize: '1.25rem', // 20px
fontWeight: 600,
lineHeight: 1.2,
},
h6: {
fontSize: '1rem', // 16px
fontWeight: 600,
lineHeight: 1.2,
},
subtitle1: {
fontSize: '1.125rem', // 18px
fontWeight: 500,
lineHeight: 1.5,
},
subtitle2: {
fontSize: '0.85rem', // 14px
fontWeight: 500,
lineHeight: 1.57,
},
body1: {
fontSize: '0.85rem', // 14px
lineHeight: 1.5,
},
body2: {
fontSize: '0.75rem', // 12px
lineHeight: 1.57,
},
button: {
fontSize: '0.875rem',
textTransform: 'none',
fontWeight: 500,
},
caption: {
fontSize: '0.75rem',
lineHeight: 1.66,
},
overline: {
fontSize: '0.75rem',
fontWeight: 600,
letterSpacing: '0.5px',
lineHeight: 2.5,
textTransform: 'uppercase',
},
},
shadows: [
'none',
'0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)', // shadow-sm
'0 0.5rem 1rem rgba(0, 0, 0, 0.15)', // shadow
'0 1rem 3rem rgba(0, 0, 0, 0.175)', // shadow-lg
'0 0.25rem 0.5rem rgba(0, 0, 0, 0.1)',
'0 0.5rem 1.5rem rgba(0, 0, 0, 0.1)',
'0 0.75rem 2rem rgba(0, 0, 0, 0.1)',
'0 1rem 2.5rem rgba(0, 0, 0, 0.1)',
'0 1.25rem 3rem rgba(0, 0, 0, 0.1)',
'0 1.5rem 3.5rem rgba(0, 0, 0, 0.1)',
'0 1.75rem 4rem rgba(0, 0, 0, 0.1)',
'0 2rem 4.5rem rgba(0, 0, 0, 0.1)',
'0 2.25rem 5rem rgba(0, 0, 0, 0.1)',
'0 2.5rem 5.5rem rgba(0, 0, 0, 0.1)',
'0 2.75rem 6rem rgba(0, 0, 0, 0.1)',
'0 3rem 6.5rem rgba(0, 0, 0, 0.1)',
'0 3.25rem 7rem rgba(0, 0, 0, 0.1)',
'0 3.5rem 7.5rem rgba(0, 0, 0, 0.1)',
'0 3.75rem 8rem rgba(0, 0, 0, 0.1)',
'0 4rem 8.5rem rgba(0, 0, 0, 0.1)',
'0 4.25rem 9rem rgba(0, 0, 0, 0.1)',
'0 4.5rem 9.5rem rgba(0, 0, 0, 0.1)',
'0 4.75rem 10rem rgba(0, 0, 0, 0.1)',
'0 5rem 10.5rem rgba(0, 0, 0, 0.1)',
'0 5.25rem 11rem rgba(0, 0, 0, 0.1)',
],
shape: {
borderRadius: 4,
},
spacing: 8, // Base spacing unit in pixels
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 900,
lg: 1200,
xl: 1536,
},
},
components: {
MuiCssBaseline: {
styleOverrides: {
body: {
backgroundColor: palette.background?.default ?? '#f9fafb',
color: palette.text?.primary ?? '#222f36',
fontFamily: '"Quicksand", sans-serif',
fontWeight: 500,
},
},
},
MuiButton: {
styleOverrides: {
root: {
// Base styles
textTransform: 'none',
fontWeight: 500,
borderRadius: '6px',
padding: '6px 12px',
minWidth: 'auto',
fontSize: '0.85rem',
lineHeight: 1.5,
},
contained: {
boxShadow: 'none',
'&:hover': {
boxShadow: 'none',
},
},
outlined: {
borderWidth: '1px',
},
sizeLarge: {
padding: '10px 16px',
},
sizeSmall: {
padding: '4px 8px',
},
},
defaultProps: {
variant: 'contained',
disableElevation: true,
},
},
MuiCard: {
styleOverrides: {
root: {
borderRadius: '0.3rem',
border: '1px solid #f3f2f9',
boxShadow: '0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)',
},
},
},
MuiCardHeader: {
styleOverrides: {
root: {
padding: '1rem',
borderBottom: '1px solid #f3f2f9',
},
title: {
fontSize: 17,
fontWeight: 600,
},
action: {
marginRight: 0,
marginTop: 0,
marginBottom: 0,
},
},
},
MuiCardContent: {
styleOverrides: {
root: {
padding: '1rem',
'&:last-child': {
paddingBottom: '1rem',
},
},
},
},
MuiInputBase: {
styleOverrides: {
root: {
borderRadius: '4px',
fontSize: 13,
padding: 0,
},
input: {
padding: '9px 12px',
},
},
},
MuiOutlinedInput: {
defaultProps: {
margin: 'dense',
},
styleOverrides: {
root: {
padding: 0,
borderRadius: '4px',
'& .MuiOutlinedInput-notchedOutline': {
borderColor: '#e2e6f1',
borderWidth: '1px',
},
'&:hover .MuiOutlinedInput-notchedOutline': {
borderColor: '#e2e6f1',
borderWidth: '1px',
},
'&.Mui-focused .MuiOutlinedInput-notchedOutline': {
borderColor: rgba(palette.primary.main, 0.1),
boxShadow: `0 0 4px ${rgba(palette.primary.main, 0.1)}`,
},
},
input: {
padding: '9px 12px',
},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
padding: 4,
paddingLeft: 9,
'& .MuiSvgIcon-root': {
fill: '#e2e6f1',
},
'&.Mui-checked': {
'& .MuiSvgIcon-root': {
fill: palette.primary.main,
},
},
},
},
},
MuiFormLabel: {
styleOverrides: {
root: {
display: 'inline-block',
color: '#222f36',
fontSize: 13,
fontWeight: 500,
},
},
},
MuiFormHelperText: {
styleOverrides: {
root: {
marginLeft: 0,
marginRight: 0,
},
},
},
MuiPaginationItem: {
styleOverrides: {
root: {
borderRadius: '0.25rem',
height: 32,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'&:hover': {
background: palette.primary.main,
color: '#ffffff',
},
'&.Mui-selected': {
background: palette.primary.main,
color: '#ffffff',
},
},
icon: {
fontSize: 12,
},
},
},
MuiAlert: {
styleOverrides: {
root: {
borderRadius: '0.3rem',
},
},
},
MuiPaper: {
styleOverrides: {
root: {
borderRadius: '0.3rem',
},
},
},
MuiTable: {
styleOverrides: {
root: {
borderCollapse: 'separate',
borderSpacing: 0,
},
},
},
MuiTableRow: {
styleOverrides: {
root: {},
},
},
MuiTableCell: {
styleOverrides: {
root: {
borderBottom: '1px solid rgb(243, 242, 249)',
padding: '12px 16px',
fontWeight: 500,
fontSize: 13.6,
},
head: {
fontSize: 14,
fontWeight: 600,
},
},
},
MuiListItemText: {
styleOverrides: {
root: {
margin: 0,
},
},
},
MuiAppBar: {
styleOverrides: {
root: {
color: palette.header.main,
},
},
},
},
zIndex: {
appBar: 1200,
drawer: 1100,
},
} as const;
// @ts-ignore
export const theme = createTheme(themeOptions);
// Dark theme options
export const darkThemeOptions = {
...themeOptions,
components: {
...themeOptions.components,
MuiCssBaseline: {
styleOverrides: {
body: {
backgroundColor: '#191814',
color: 'rgba(255, 255, 255, 0.8)',
},
},
},
MuiCard: {
styleOverrides: {
root: {
backgroundColor: '#232226',
borderColor: 'rgba(255, 255, 255, 0.1)',
},
},
},
MuiTableCell: {
styleOverrides: {
root: {
borderColor: 'rgba(255, 255, 255, 0.1)',
},
head: {
fontSize: 14,
fontWeight: 600,
},
},
},
},
} as const;
// @ts-ignore
export const darkTheme = createTheme(darkThemeOptions);
================================================
FILE: src/styles.css
================================================
html, body {
margin: 0;
font-family: 'Nunito', sans-serif;
color: #5E6278;
font-size: 14px;
}
html,
body {
overflow-wrap: break-word;
-webkit-hyphens: none;
hyphens: none;
word-break: break-word;
margin: 0;
display: flex;
flex-direction: column;
height: unset;
overscroll-behavior: none;
}
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
button {
background-color: transparent;
background-image: none;
}
fieldset {
margin: 0;
padding: 0;
}
ol,
ul {
list-style: none;
margin: 0;
padding: 0;
}
body {
font-family: inherit;
line-height: inherit;
}
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0; /* 2 */
border-style: solid; /* 2 */
border-color: currentColor; /* 2 */
outline: none;
}
hr {
border-top-width: 1px;
}
img {
border-style: solid;
}
textarea {
resize: vertical;
}
input::placeholder,
textarea::placeholder {
opacity: 1;
color: #a1a1aa;
}
button,
[role='button'] {
cursor: pointer;
}
table {
border-collapse: collapse;
}
a {
color: inherit;
text-decoration: inherit;
}
button,
input,
optgroup,
select,
textarea {
padding: 0;
line-height: inherit;
color: inherit;
}
pre,
code,
kbd,
samp {
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
}
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
img,
video {
max-width: 100%;
height: auto;
}
================================================
FILE: src/utils/download.ts
================================================
export const downloadObjectAsJson = (exportName: string, data: unknown) => {
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(data))}`;
const downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute('href', dataStr);
downloadAnchorNode.setAttribute('download', `${exportName}.json`);
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
};
================================================
FILE: src/utils/thumbnail.ts
================================================
export const getThumbnail = (url: string) => {
const parts = url.split('/');
// get the filename
const fileName = parts.pop();
const segments = fileName?.split('.');
const fileExtension = segments?.pop();
const fileNameWithoutExtension = segments?.join('.');
return `${parts.join('/')}/${fileNameWithoutExtension}m.${fileExtension}`;
};
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"jsx": "preserve",
"allowJs": false,
"strict": true,
"jsxImportSource": "@emotion/react",
"types": ["vite/client"]
},
"files": [],
"include": [],
"exclude": ["dist", "node_modules"],
"references": [
{
"path": "../../libs/draw"
},
{
"path": "../../libs/design-editor"
},
{
"path": "../../libs/design-utils"
},
{
"path": "../../libs/text-editor"
},
{
"path": "../../libs/design-screen"
},
{
"path": "../../libs/design-layers"
},
{
"path": "../../libs/design-core"
},
{
"path": "../../libs/color-picker"
},
{
"path": "./tsconfig.app.json"
}
],
"extends": "../../tsconfig.base.json"
}
================================================
FILE: vite.config.ts
================================================
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import { analyzer } from 'vite-bundle-analyzer';
import EnvironmentPlugin from 'vite-plugin-environment';
const isProd = process.env.NODE_ENV === 'production';
const plugins = [react(), EnvironmentPlugin(['API_ENDPOINT', 'FONT_API_KEY'])];
if (isProd) {
plugins.push(
analyzer({
analyzerMode: 'static',
openAnalyzer: false,
}),
);
}
export default defineConfig({
plugins,
server: {
port: 4200,
},
build: {
sourcemap: true, // Generate source maps for debugging
rollupOptions: {
treeshake: true,
},
},
});