From 10e935d2e70db6c2ba9569ee189b159ad96fb9eb Mon Sep 17 00:00:00 2001 From: Mario Arita Date: Thu, 4 Jan 2024 22:43:54 -0600 Subject: [PATCH] feat(CodePlayground): :sparkles: Visualization of component code in real time --- .vscode/settings.json | 36 +- Dockerfile | 39 ++ config/default.json | 6 +- config/gt.json | 6 +- config/testing.json | 6 +- config/www.json | 6 +- jsconfig.json | 10 + package.json | 17 +- postcss.config.js | 4 +- public/images/backgrounds.webp | Bin 0 -> 30418 bytes src/components/CodeEditor/index.jsx | 32 ++ src/components/CodePlayground/index.jsx | 88 ++++ src/components/Icons/index.jsx | 25 + src/components/LivePreview/index.jsx | 41 ++ src/components/Login/FormLogin.jsx | 10 +- src/components/ResizableDiv/index.jsx | 118 +++++ src/components/vComponents/Sidebar/index.jsx | 468 +++++++++++++++++++ src/components/widgets/UserOptionsMenu.jsx | 24 +- src/data/menu.json | 72 +++ src/hooks/useKeyPress.js | 29 ++ src/hooks/useStore.ts | 8 + src/layout/ResponsiveContainer.jsx | 17 +- src/pages/{_app.tsx => _app.jsx} | 23 +- src/pages/{_document.tsx => _document.jsx} | 0 src/pages/dashboard/index.jsx | 40 ++ src/pages/index.jsx | 4 +- src/pages/via-ui/[...index].jsx | 9 + src/pages/via-ui/tab/[...index].jsx | 29 ++ src/pages/via-ui/test/[...index].jsx | 56 +++ src/styles/component-styles/navbar.css | 16 +- src/styles/component-styles/sidebar.css | 13 +- src/styles/globals.css | 52 +++ src/styles/page-styles/common.css | 2 +- src/styles/page-styles/login.css | 2 +- src/utils/globalPresets.js | 11 +- tailwind.config.ts | 24 +- tsconfig.json => tsconfigOld.json | 0 37 files changed, 1252 insertions(+), 91 deletions(-) create mode 100644 Dockerfile create mode 100644 jsconfig.json create mode 100644 public/images/backgrounds.webp create mode 100644 src/components/CodeEditor/index.jsx create mode 100644 src/components/CodePlayground/index.jsx create mode 100644 src/components/Icons/index.jsx create mode 100644 src/components/LivePreview/index.jsx create mode 100644 src/components/ResizableDiv/index.jsx create mode 100644 src/components/vComponents/Sidebar/index.jsx create mode 100644 src/data/menu.json create mode 100644 src/hooks/useKeyPress.js rename src/pages/{_app.tsx => _app.jsx} (64%) rename src/pages/{_document.tsx => _document.jsx} (100%) create mode 100644 src/pages/dashboard/index.jsx create mode 100644 src/pages/via-ui/[...index].jsx create mode 100644 src/pages/via-ui/tab/[...index].jsx create mode 100644 src/pages/via-ui/test/[...index].jsx rename tsconfig.json => tsconfigOld.json (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index e4a1751..7a629fa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,25 +11,25 @@ "source.fixAll.eslint": "explicit" }, "workbench.colorCustomizations": { - "activityBar.activeBackground": "#0894ba", - "activityBar.background": "#0894ba", - "activityBar.foreground": "#e7e7e7", - "activityBar.inactiveForeground": "#e7e7e799", - "activityBarBadge.background": "#99077a", - "activityBarBadge.foreground": "#e7e7e7", - "commandCenter.border": "#e7e7e799", - "sash.hoverBorder": "#0894ba", - "statusBar.background": "#066d89", - "statusBar.foreground": "#e7e7e7", - "statusBarItem.hoverBackground": "#0894ba", - "statusBarItem.remoteBackground": "#066d89", - "statusBarItem.remoteForeground": "#e7e7e7", - "titleBar.activeBackground": "#066d89", - "titleBar.activeForeground": "#e7e7e7", - "titleBar.inactiveBackground": "#066d8999", - "titleBar.inactiveForeground": "#e7e7e799" + "activityBar.activeBackground": "#fac8fb", + "activityBar.background": "#fac8fb", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#95920b", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#15202b99", + "sash.hoverBorder": "#fac8fb", + "statusBar.background": "#f598f8", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#f068f5", + "statusBarItem.remoteBackground": "#f598f8", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#f598f8", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#f598f899", + "titleBar.inactiveForeground": "#15202b99" }, - "peacock.color": "#066d89", + "peacock.color": "#f598f8", "cSpell.words": [ "orbis", "Orbis" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..088c6ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +## Build image and name it 'custom-next' +# docker build -t custom-next . + +## Run container and name it 'OrbisPlayground'. Webpage is localhost:3000 +# docker run -it --rm -dp 3000:3000 --name OrbisPlayground custom-next + +## Connect to container +# docker exec -it OrbisPlayground sh + +## Stop docker container +# docker stop OrbisPlayground + +## All together +# docker stop OrbisPlayground & docker image rm -f custom-next & docker build -t custom-next . && docker run -it --rm -dp 3000:3000 --name OrbisPlayground custom-next && docker exec -it OrbisPlayground sh + +# Start Dockerfile +ARG VERSION=18.16.0-alpine3.17 +ARG DIR=OrbisPlayground + +FROM node:${VERSION} as builder +# redeclare ARG because ARG not in build environment +ARG DIR +WORKDIR /${DIR} +COPY . . +RUN apk update +RUN apk add git +RUN yarn +RUN NODE_ENV=production yarn build + +FROM node:${VERSION} as runner +# redeclare ARG because ARG not in build environment +ARG DIR +WORKDIR /${DIR} +COPY --from=builder /${DIR}/public ./public +COPY --from=builder /${DIR}/.next/standalone . +COPY --from=builder /${DIR}/.next/static ./.next/static + +EXPOSE 3000 +ENTRYPOINT ["node", "server.js"] diff --git a/config/default.json b/config/default.json index df624a9..f80bc6b 100644 --- a/config/default.json +++ b/config/default.json @@ -1,12 +1,12 @@ { "constants": { "plataforma": "web", - "publicPath": "/orbistemplate", + "publicPath": "/orbisPlayground", "urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso", "urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso", "urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso", - "appTitle": "OrbisTemplate", - "idApp": "orbistemplate", + "appTitle": "orbisPlayground", + "idApp": "orbisPlayground", "publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----", "maxMbUpload": 4, "defaultLocale": "es" diff --git a/config/gt.json b/config/gt.json index 7d5b701..ddba126 100644 --- a/config/gt.json +++ b/config/gt.json @@ -1,12 +1,12 @@ { "constants": { "plataforma": "web", - "publicPath": "/orbistemplate", + "publicPath": "/orbisPlayground", "urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", "urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", "urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", - "appTitle": "OrbisTemplate", - "idApp": "orbistemplate", + "appTitle": "orbisPlayground", + "idApp": "orbisPlayground", "publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----", "maxMbUpload": 4, "defaultLocale": "es" diff --git a/config/testing.json b/config/testing.json index dee3b1e..7d3ab07 100644 --- a/config/testing.json +++ b/config/testing.json @@ -1,12 +1,12 @@ { "constants": { "plataforma": "web", - "publicPath": "/orbistemplate", + "publicPath": "/orbisPlayground", "urlServerImages" : "https://localhost:3000/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", "urlWebApi": "https://localhost:3000/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", "urlUploadApi": "https://localhost:3000/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw", - "appTitle": "OrbisTemplate", - "idApp": "orbistemplate", + "appTitle": "orbisPlayground", + "idApp": "orbisPlayground", "publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----", "maxMbUpload": 4, "defaultLocale": "es" diff --git a/config/www.json b/config/www.json index 2f5ef4c..a050beb 100644 --- a/config/www.json +++ b/config/www.json @@ -1,12 +1,12 @@ { "constants": { "plataforma": "web", - "publicPath": "/orbistemplate", + "publicPath": "/orbisPlayground", "urlServerImages" : "https://www.via-asesores.com/smartoperation/orbisapi/dtsrv/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5", "urlWebApi": "https://www.via-asesores.com/smartoperation/orbisapi/api/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5", "urlUploadApi": "https://www.via-asesores.com/smartoperation/orbisapi/upload/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5", - "appTitle": "OrbisTemplate", - "idApp": "orbistemplate", + "appTitle": "orbisPlayground", + "idApp": "orbisPlayground", "publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----", "maxMbUpload": 4, "defaultLocale": "es" diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..0405287 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + "vComponents/*": ["./node_modules/vComponents/dist/components/*"], + "via-ui/*": ["./node_modules/via-ui/dist/components/*"] + } + } +} diff --git a/package.json b/package.json index 02889fd..b628df8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "next-template", + "name": "orbis-playground", "version": "0.1.0", - "description": "My Next.js project", + "description": "Orbis Playground", "repository": { "type": "git", "url": "https://git.via-asesores.com/jmaritar/next-template" @@ -25,7 +25,13 @@ "lint": "next lint" }, "dependencies": { + "@babel/standalone": "^7.23.7", + "@codemirror/lang-javascript": "^6.2.1", + "@codemirror/theme-one-dark": "^6.1.2", + "@codesandbox/sandpack-react": "^2.10.0", "@headlessui/react": "^1.7.17", + "@uiw/codemirror-theme-monokai": "^4.21.21", + "@uiw/react-codemirror": "^4.21.21", "config": "^3.3.9", "js-cookie": "^3.0.5", "js-md5": "^0.8.3", @@ -36,10 +42,15 @@ "react-dom": "^18", "react-dropzone-component": "^3.2.0", "react-icons": "^4.12.0", + "react-live": "^4.1.5", + "react-live-runner": "^1.0.5", + "react-runner": "^1.0.3", "react-simple-hook-store": "^0.0.6", "react-toastify": "^9.1.3", "rosetta": "^1.1.0", - "vComponents": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-components.git" + "v-functions": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-functions.git", + "vComponents": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-components.git#dev_ja", + "via-ui": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/via-ui.git#dev_ja" }, "devDependencies": { "@types/node": "^20", diff --git a/postcss.config.js b/postcss.config.js index 33ad091..85f717c 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,6 @@ module.exports = { plugins: { tailwindcss: {}, - autoprefixer: {}, - }, + autoprefixer: {} + } } diff --git a/public/images/backgrounds.webp b/public/images/backgrounds.webp new file mode 100644 index 0000000000000000000000000000000000000000..70f22f284188ffee13403e2cbfd66ea88ac88e79 GIT binary patch literal 30418 zcmV)JK)b(ENk&G>b^riZMM6+kP&gpIb^rkII0BskDmVn60zQ#QpG&2rEvh55=;5#u z2~FRHk|=Wj>^bP_)MIg!bLo|IbZA{ipu#`$w`o6`UQ2z83#| z{;$-xr#<(S0P>9Qwfk56&tSjUzPx^uBF2h~W&`hywHNNCQEb2-I@V;~?YDVKO{k*p z`-b5h9X>YHQmD3I4;^i4G!-#;+vkb^NU2s{w2Z~C67C&UKHB_(TbVktkqHlPe;aBk zR9i3~d~Nf^037Y78%TOu6WK-vEWq6u8&!Gf64pcq=K)wy0nYKZqLoFrh+_z~e{97A;lpKcvm{%D)t)YV5w zDlM1;$60sMM0o32lrUh>RN)^L43;Hk*9FYaI}4|%1vHSsM~+-iP(0AFCcY0ogHq*cbwZPup_d>PdbyQ0_HF->r$l|{1v zc5#-6uM=fTPW>=PGrw@X#f9p3|7R$wO2PTK>PhW1MvsjL2O~Y8c?MA@2^F_0?Xa; zolxV`>ueKkg*(>nRh(GTgFU-tO(nGgc7zE6S=o^CoH}+q2;aU}D88?Gf5gj`_?&~@ zj8`&P5gJ;FcR^8Xz(;mgU|?NrExdJ%X5)ds7yB%nwTPsC@pXIb$V1x!jt%#Z{)7Lb zKpAY`w1R`;)27FmhV3^fn+EvLrzN3kd=WK%qO#EkxwPCKX3tLy67;3op9SezeGbUw zJwD#;f?FYo;WUmrgnaK^>zjnGh!{Nf1QR(ZOduXJefF%g3)z1hc333e>HVdsnoOZ) zc+#8z#9(yechqm*MBygn+(okhg$m+q#f_74qHYrXIeuGNyX-0m5>Lnb$mvu20C^B^ zA~Ioxr9g{I^s{7hw?Wc}Yx`-p1LDVXxM5*u`HkDMZpx){p{R$(L3jBbR3OC}LD^jY z#Kuk*GrD243zF0Dyf13f4yP5_ZhD6GM~-G>oa@GGHQW$GeX0$IGJqZRVi;l_? zol!W?chP?cke5J;noP;osLno`C3NMf)suuTmTe>*gt3>S_f1c^J24um`e+bryK*>l zCe2JJe|wvFHUiU^uMCI&S%o@@xZ=MDddF@q00M~3!W|@)*HKg{=RklXf4GV=4YnX- z)OsZ3$#+5V&s0WqvrI9xMrj!}VcUN*_*7u=JGm`!m!nXIyPr#&k_yoM&iYe7+L z(^5TgtER%*2q9zAB2!@6{d$p=i7iwdc?ke7xKt@C&-WeSNm8BR>ghR0ZNPa06unz% z(&KMHou_-kEBcz8FT?id20z3uys(xJc#0iSx4A$6_7et`rtw$ZJqHK_(UlvU;belM+12VaknNvW@~1jAXbV*M zH~5{8WpbIGu`z?WJ=P!Ab?F?~(0-Ux??y}SH}3R*XMv2_j7Uj4z#k+vnnA^&Mv%vx zF2AWhKXsW=8$IHx0OTMT>C>ic>De%ei7eIG`6WV`n~%f?0tjA^;jWMIrbh_7NTnAE zmvkgYqxoIi2{N0>YchC+YDa;{Q@}kNYCkqI_~oImt^hgSHzv%GQ~*cE0vfBIBZ);1Zxzm3)z4$I5~%YOrY(|2 zA@}o^FL(qcUPNivfRp*EoC~#*&!wjZzdXh{U}ww3xpKCH&W7s!9rp{ip2eRKEm7`* z=#y}UXaIdG3qg(EqKl}0#JEC?zWEP53@*n2Ddn!Nf2xpRO%wU_jn>Iz&9qj92Wkb&k&Vpj2A4anLk2Q6S z74UywOULqgs;sS=2ZOrE(cxwRs_fv3bOm|ittyORyZf!DK)jChdlg11DU1(2odnSU ze=cox(ZS!5foa}u?>jcBh5B(?32fKNrh-1agwA`KPfnl z?|q3K>}xUFnDB^8@!wVCf59r;U#X*SIX(jQhw~ZjWzRvC4z<2(Sf}0=`9)10R&y*Y zOZJ}*j1seqw4fFyB54{MLi>XVadvIi%qq|{c;qSb2^c4$5-O-~aTsVpcdcR3p?O5hI*fl#yKab2tEd z7I~>)f5Wq5Zn5y`RRvYp(|sKNdpGf=Gdcg%;K04=Cg5mJLI0XKdwgW=4@m;o1=TJ* z1OfVeYsT7&in$oszG-BnQ9B0D(R^55`e3k1AQV`9PWK=*P+-~TYva-xr$#}$6FG2Smdl_wVmb`IeUy^U0SR z{c#GK6d!YksOAhkf=OUxE*a+tTd9wG8AdmXB1&VpO>_V(PIhqv`*EAFbz0*VbNh@S zEEPMGsJa!{&5cW#53Tml6x>70a6`$K#)S){0!BgD36zb7GoM!yifHlHl}0ey34L{h zLBV<=|ANW^=6g##Ma?vE4j1#+f{+p_D%!Bii;6e4XRgYWKiOi@(tH)%^;R=~h4fa{ z)vI|WX^4oj8TcS_6^4sbabwaTBc6hN6+Im9@p;ATZIS<6$7Y1?zTMWUUSMRGc1@a`m!t> z5Dx((mtFtEtW*&6pHLt54Zw$CAtu@RXVvByFxg1)Luy_Q#7r^hy@5}Hb;bwrE(cBR zxcrweX6sXF^fwqO#T;!BvPCO@MI!HrA1s;td2 zLg`4K+ZTP3BR&kf)=`T~^cQbXtg6Dc*r~@AMZz$3N!53T=2i6ce%s-y2Rxk1gdWHa z$|iH2Yk*4mmP=F5Bd178=P=S)i!Ud-zkEmp>ZPe31&|Nr{RKmYqXMnq^Bqd^*r#%|SZnM8#*m5t269y-#k zFv>55hBwVy*Qq9fi|e?{qVED@&JIzRTFaOYC_=d$whPgEmDwh^R*%ReD9uZsT2Tn#^Ns}13lYlKfi*gBZzHZdm{^?x1k8ij1D{kGlb4QTL5XGnj&IdNucII zcBx`~*XZr8Io}>x3t_+u^h(G@F(E49#89q_9m_bn?^#qgNI(A_bIj3>+Xr%VF^+QL zD>kAdw)lgd>7fu~dhW_*@n6_huAP&?yVF6m%FEV`H}%SpO+7r-$aI&oIf*EsZ~mdJ zZT)g{e`V30%P=Zj)|ExGIy`mn-G(VuF1;V9+LTv;$1w-BmVOMxZ)1U57%~N)h?i~& z(H4qClBi}D-2YL-Z;*^Be}a&;u3oz>%Y(e z&uM5Tcctcy1=V|Yf%a-q$W}sJ>IZ(fA?lv;6x6by1Zxni$GvlXb*KQZvDuovbK!j4 zFHol2m&OMN0?a0fNiK92{@3s|ej!CSipz7L8z2^?^IDRaC~)zrN@T6rMi}^numVAN zFP2np5lW)jogO;hx}5Ug4}zpit$&yvMW^kKCl?42&GQsWwnY%qGC?NtCr|Tjp@Sl~ zsTQtk+FR}Ek$Dz^$fyq&_^YOJWisMQ_P_edcoEBJqB?VfB?IXFDN2;b=9>QJy-p)> z2II%Ty^;!#;(EY5;8bU=RL8{_riUq61>d(O>xFbd3fy&*bTpIQD9DutfTxK!R%%YD z@TT($J&Ud@Z-O&i$x;5i7G+EMfJZHFr~m5LFX?!mH|!Y>RH4h_ZAB`JY$R#vPn~xR zjgI1XtwJ-y`6R_d9wh02`2PCb>uNakXoSa37`NOn4)VdInmzi69(2uuYr4`O?Y^$f zZ7I#=i-KNA0Fkl}iXMkAn@rev>q?^XP!$%;75)tfbGG>Dy5#cD!_+i#le}Ml&c%rx zp}bgXAQ)MH3ExUlfBB-2fZq@b?mY~q+_uhYuYLFR*sIGt{5YL^Y-fjwO}{G@E-)06gy0!FTPnoYsOy2BE8NXS1oW4E~_;bG;!9I zMYF5cQRGyG=ynkBjrmQTt9JUFUENkDkpZ@Pd1UCJSBwbR@x)s&2ay(3gMJ)?sb-NPAN7G!ta^->%Xe%Iw`x|O_^nLR?d8Iw*@+8#tk`w~ z=9_je_PrjS@dF#THrA>2cMI!#G@lp=R8QM$Hp~Iztu!1*y*FsF@#apZAs#)7UlY)8 z&hx<^^ucUhB#}VYUWZGOkrPE?Q}buCS~rN__0LqyeVl=!gZR(c?M{YKY``8m(yZ^} zZ9g=>)yx3(y~-p{^?TXisyP?4ro$15OsJvBQH6Y$d$Xsfjx&~G$SeB(pdSMdhei~t zEtn6!OH*b@34@-v0QxwBXe<`8;ujXfnIOvqoMh^mZwUZMQ?z6e*Ad6+De<^)b8JEp`9SW-1q?N&u)b6MJkJCba?CEwHM%l$?Ci!iUHW^EE(1KNS|{X zEm=kqS4Ei0P90k>3f2MxY%5~-akW9})fh1cWnhC%Fh?M1Qa3J= zEm1pN*_|$a@1xUz2d5|s;hB~Hg1xKl7~*D#gNp|}M*O0`{Ty@{41y^^^A@9u+-+ZB3LF}D*PK^3%SqZhF5-RSJ_9=^ux#oA6$Koy z0T$2|R#NPW20hhi<|RlXNPoozzX-Q+A#EM?+^I&{YNyQs!qUtI!|=B9fnfAkPs3EX zh^KBPkvvX12E=l0Dz;yav25b-jkNJosfz!-kTQ4NksrB_{xLuTlRBaZrrHSdZUvo{ z-?YP$IxByh?+>Zg&kP$_-K^EMFcN41pN_w0Sys|mWGRN(%q;oqTWr>`48Udni8qP< z003^#Zg$%a&@#+9%>xon%#@!lB_0Sy_+t12?_$a+84H(BdYY3BI^}9I|jDjLW zut$ykiTA*5XO0~K-T&eZVLvGwPJw-JHklY1kwsXlvDIXn2^dCO8!TeGVofX<89U;0YQhBA@2bwFf5e|Tg+G`{T%@$LYN#n1vC zUto&8nG++DI=Uyyzm9K3HP^8uGeHP;PtD8c>0_(^ke+6m<&BLT*~+(SOXjiJfLvLa zd+}79LnOpbyxT-s^q;cN*$94-z_DT*I9><3m|mu%%5%N);lWQ9(et42%H0draF;P| zOs=?+#1&n9GBlsnD8tBY{d-tT+xlHU^jIz&o<)qO56&Slble9n_q1;jMQ(i1>_reP zdfgR!8LT9_)$%p-H@_EPT9g>40ri|7yk^ZIXva&wJJ>!L!qR%SPIAwwn4?+j74G@%XRbh%F0N3HA$$ zN`XqqQJ!*C1G&?(VIpY@pKr;P9ksIl>XoxR$mlG^UD^(|>{vi&iVQ2}*Ge=N{9Q53 z7I7Y`vadia zCH^u>*{(J8W8L_0QDd>`VlZF2pFXKK|H+DXH7nQUJiB~yIBM4HryR6+Q&}$5aHdDP z7F6J9q%}lG2N^$cW$mMFX`isXZqr1~X4&NGH%DGVY+^0|(UH*a=-vnfM;u7h5}{EYx!9wy?9;~K+W?4&}Q zzbsT7v*?fYMbJE6E`zi1bKPa9a;b@ZIn=&HFJ43?$$BPR)VCfJ%_lQt^Q@Wb@B7$WE8#(tgs0z-nSJlL?-hn6=no?Bw<-_ZkSIPEgWI zARxt`m0IsCj(|IwA0!v1ZkxB~W7S}SAG_b@QHd>~{96as!{MEq<-n81!CVT^Xn-`a zmr}qt6P1KBdt$7J1j8k#MlDmny%UoDY;WmuwwR|GZcBo@NYO%=RgFyHmaB%#Pu%%4xJ4| zahcC?bR0+(w&4RFz$c&LahRnEn$K}oJn|Mm)kG?3UD>YZ z)&5l%rjC8sPCfTpc`aIMW5hi;%PjHrZt-J-be^?J^JN~S==1VN^+s3bN5U;wU|2UO z$s+^5B-2H0yqO^Ak*xlB7PLO_U*J)Q4_5^agG6TmBov4d9lWE>x87#I4ddV=u^PY= z%6!?Vx%(HN`ggZ;s6E#Mu2)e@#Fs=n;LpNDE(yL0w(b%M{-vQn5zkZM0TD90Z1cMv zn-{+Uqq3@jOUeYW;R+o>y(Q-W&_qdTd8bM7*<>I^CsslNso3@Weo|$_T#7C9_%Yb$ zc?yUF+uRb5eNO2pjWrr0`kp=0yaCr@t}DG%2X0dXA}>No$(F3dW_Bu9 z`&C*l({c>Igu4pDj!U`Xs_21MJ^v5WfPaJbelZv7b{8OYQh(UH?#=Nv(>W}tEX&Vy z5=sdoT??koJJe)*XTX>sRjs|;Q$qHzQ_RupEBeR|gbUcQbS{MAJS!k5V`rpobJ@-C6Qp>~ZO#POF0Vvz(? zOw<~sAK$~L0SWb2I=PK&?d0EwZq)Js7?u}c00ZzMbuAVcj{+KdaRS#0XXhzt4I5A^ z{7N=B%?VL1M$WHgpR{wZ6v$@lm?ut`^v3|j3`@XktV~8N#&@mAAl!JfU16*A$}@Yc9NPBtD?Yn|FxCkU5S|An z@aiy1ZKj>^CR;N%p{T>y~Oxpydhj}vzmWt$%OO8+{ zh4!wo;5)~;G_&J{t#r)fg$|FUlF59*`&I~sHclCCsRmf}pk11WW`7{BL37cmCC-hr zM&bRm1HVwB3P5i5?1>GKF*2TJs?4+fsDw*iqp5!V2?+1FZ2dAPO#vHtzCU%8;zV57 zlsSdwRJwNkwHeP&=(H);ernfN_yx{W2m0QhMMPJ(4LtainYcRn%S@qDeTp2aFb@n7 zA5`LAo&%i?BzmVn(mvmSExyc^?P;qE$Nd`rElB5!W2MU zrfN4sTX9v>C*J(6C06Rvw-G85S92S#3dkMwdMda0b?v(=4k4HD*}&JH?4gOq$$O$p zv9j~`^BR*F;B+d zp?Yb$#{Rv5=GZwn;NRFqz9+y;pe;GYtdm;xWci(lGV-^>lDBTT1jU(dYiVTy+}ikf z1uwWOtK^i&@1PAuJTJ!TZx8Dqw@ z56)Kfqlfx3)1G-<=A2-H{fo*bSQ%>sJ@5*mjFWnkz1p(upS9LU?5C#qh9q9rNopubuSZ8ub%n|%n%%XAu?=7$3+AEI`?u2Y*pSG@iLk{E>eKg}(g&ASu> zwwK3aJSK8tITprxJlu8X?mTc3zJ__d{rM0C9T{fFckkMc=sr|ut8Ot-RD^s`lSll< zVmR^b5VUO7zR|r(cmysgz`8R`MI8*_$Gnmnkh4>^>p1%%frfPEj$7pvQ-pSPsZ^f3 z>1>RlW98*KKLSSN|99W;Jlp*jj)|3XdUhxZ(Z`Oz4WEAKYFYT43igBg#ul2EM*j=m zjs^H!m_cyM7v<6&T-g0xAX>8nCdAUwDrjMJpfSpwG#fS{Y_lyZ6KEm zpQF$@B;9o=!rU{S%BXqZ+g}bMB196S?`bHT#&ewgmE+W+_t>5rp>R77enYm>&OIkQ z@h5qHUawD=U6f$P`W(>!F@W{QQkkWz0r8NE4$@MviAYd(Q@Gh+yYi_f$PvwuHZ*Rd zgzk(D*!FKZT?pi^-lXwx}#aan;yt+*x*<^dxn^_}yWYNc6rA@iaIc;v8 z*qt3KKPuIToC-s#pRxy=#|u&bjo%a)5?~UQ8f7I(^*pmGo%FhWZrzat z&v(_iq@DiVKzWbUSX`%^JU5Uc0;zsx&3kYGa02&WD|r%zQjX?o1PJDjn(({)5!hz< z*;oEeLJY)RJkir=Nmds(5?P}d45^aZj|(03GJBx2h_ zab;l#AK0XTBAT5%RB|w=aC2>|?aUClJxF^(-FuMVG<1E^77@1f|9KCFuId+am!js$ zS6Hs^A_l8#kb!fshjcl-%VbIM?S0qlZ<|l0w)Yh_2wtpySCOeQ=@R%;itzFjs2PW# ze}R6DUrIB1jY&EK0<^k5nOwUbxwwWLW(Ohw_oU);aWI$hBE`#0EuV>7F2n5A>QAIq zuTfY=D?G-%mV<*SrZlB;q+&S9k&U9PxOc!ddhiwY_H{1`b!kVqc`m}}5{f##)8$ zLy^nFyOMn&X}d;4I^I%rWD#U(aK|HPF)sAA9kWr-P;Pdmdp|z)SU?HuZWuPVZsAdE z+-0p&GQD_=_OtARs+=w_I83?6d0zr&@N)B))W&CzO*RT#s;EJk1g;)lU*Z&^FF!0k zefbPpDEHwq7?PXqpzSo4%>C@o;HOEup|nmHf%o$X1H7#a_oQd$I!5D?tz&`v7VppA z6>76Ldivf!q}j2_#@t{WeZr`^nI1lm=$i|}@O#P4fW@9?KhZ8>rb|ok5~MZ$CWL{u zD^#U|eo<+t@wyc*wS2{2UEk?9cRqwOEg!ufhgLhTpu&Y+A{h-+*6nf zpc;eJcV)F63|s;fFh3?oXMrB4S)|AWe5X>s;jZzVA~1n z->K6H)d2JQ?h;@gMD_U~U3m{76>A-q-v03%*Kg8>Oe_Da+{cG=iT~M16sCedHwBH zF{mq>`n-BYhN-{6_QV?pJPdX(NM^Sxqng28@E|i+m|EtF%sm!2-@HQB>JdAtfF4pl zWW1Qvd_j;pS>Nd=z%0^I0i~w;@Qp6*J4$kp@W-hP3saPA(x!G$o)p#78CjLqjWJNR z+Lm$dR)&RBYCcp$AK~K#Jp4Z8&D%TxriP7Qj1JW2h78ydbjexbi}EE)4U)`b3B7|U`nez z$v?*u%xWmv!S;HfjTei*+|1e^wc{^mVODojke*@ByN^EZGb{rWk_>5W0q8lp1PRcV zJm=G`hmVNZr|xMF;6XGVa^S|IN*3N-JZXV$d!or>@+U|4pwUEt&{54=wPCM%W8}`cg4pN)4zI5&K>Q21QY9zeNDAbJ zGA9pNb%EyF_;4IB0^|fC1dyt3yh05j)KBG&0|o%BU52qul!)hxg@i+a~z=tgd0M&rX~vo zzs2yy(_nLktS!`i*%#f+)^3>@I3PQ~MOVEA0v`@nM8E!K(b)2-r?yFh_5}cT?n!4@ z?^SLc7udJGqQkTqm&)sqRkTCP$4?TK^E8LPAts7gv-883RSIsuPp9EI-pL~6ewZ8% zVOlrEuVp>L_e`A7%xx%_=}oV@?c>AB1;nfS@9YJR>x-o-V5?027DnD<BhJ>9^G>m#9`($l67$om4qc6;b9#iiYOjDOA)BaPCiyRTwgXG8`tM zbtsyn5VwL*sWG>Jl?J$AZ{2PBB2IdOnDH3_&xSFlN_24`{H)K*gFaX~5d1ge;l{Q` zBpS1qODQ4ie8k#Z^&?z7*_KUAdiIh(7;N?z_S2lfC(^=iC5ptSgh8U>F!hRHOv~Dc zb3ghG$XFB63;+oSohECweEXp*W7H@U9dwiS+B&AwC(28M<+u?xI-PNJ+F8xu#fLU-TGXSMbR{q8nd~G*6bdPT z;_Ot7*f!_ULj_z$8FKQee>$=8-PjL~a8<85;jOns4q&S_?5S@r-cn9DF#nQF?Xqki zSI~L9$b`|H*$r^u+44$r05q=AkOfRw5=Rx=;o|?7AnPZJ$!cdt zA(PW#ce5)c@&hbo3ZGS;WWVR$cxN;cVLV0hr@DpZNNjtFjkM(nSQgiM#1is$;vTgI z+5%0;B*$fexS{ZDdLn9=PZn&%Bh3#qQ>RwLdPccYDr$?H>wcal9+QACQO!A7eE@=? zN!$sO;)d2%>jTnrzSNP$u`ih(>>uKrAkZpiUD^bda>3u^Jb|M7hyC_Gru zE2hRS+LxI^$g{6-Lvo2ki>#QtM=<@!p%eBJ62bnP{N()EsV5Lej?(fJ z1Et_d7g9LxcDvku#_W-KA4y~-;yM1<2zNhTKOf)X(?>mrx4PeslP`4}G5lQm>u%$WF?VzVM%cZNc?Dd93Zc!M?^ zc^ai_S~C^#yc=q2R26a&Q-ZcSmC2Da64}%4L+=*OUT*P3fap3*inm&0% zaluN_IjA}!swFpv2elqab!_aOY|ww}RkVtmw>h_^9@$jOy$<>9?7$QmKbDw%rQ?>v z>d$JFxl;tmVQmcjuw zRa=>U|5I5Syw|$h_@kEEw_Lddx{1KXFSNkf7sCqLOj>t%aLv>Q_im@@w~6w6^EU z_fama3{jR8cy@H$yC)e}vq{Bkz2Q1Bnw4`bJnECJv+O?fj^d3QTg;Bt9^BtWl)iCp z=0DtPM)cs}NL8dN> z)q)yY-w@5&=f8gM9d__fyU!00UE$Uu9#%z?@=ORg^UVfC@q{`cx5`d^_H7~vgczux zVNZqon~gEEdB@2Vn0bkh`Mp5CNFN7L1AhC^;BciGgD(MQ0R$lg0P4LvX1vw5E3cN) zFFYkjn`f(7{w~qDB&bS-3NSQP*^mtb;KW#vd3FL#A*04QcFTKdH6n!+!zFQ0JTI3Q z3_B#K8c29vEf%L0N;(gd=(m#8_6!1H#2%3Q?lh9Co$_hU#vV@m_l>fQom1JF7@Oru z?%j@VWfqI=j~Bi0oSWiT-X1a3ywM=IYgG0I1u+ggb1U!x#8P8To?LZ2-$;aPtxH`3Jj9y2-U%S21|_7^c(h$ z!8Mi5R_NflAa~P@j)^;M$#X}ZHtDstxamkH$RM-?9cnZQLIx~xt5)t@;D&jCcZY43fPT8b6Q5iW5^at(_r6RnJ3|wVJvC>%BpA9a%kuN-J|YB}i8JtoG>797qG6V+e*X5uT;4e!b7l4` z5?{KX%M!zROl#d#3wgtEe#KRo9}|`Xc7NN%(7pw6MF+A}clhy75^xXuL`-Wb)R;LUI@X_&gHQD6+!GrzLtns*1aFd(fnGpugva-82MC@iM_WZZWl-0Bb>8*z?8f z^}n7r54ivz&8tgR%ny_eDv14S@e|m#%t?{ww*VaG9yEDORlG9RD%FR8a2ukMY&Eoc zcURIa3ci_#F=yg?uxdch^nvimm+2n1dJ)jcr!64;20mxs90f#03*^&y#rXlLC}OUE zS!9&C-{#n~9b5V|{*w|)BLplTRXaN>tNo~FXhDY;{Gq$R$^ZZW00013f&h@BHoDv6 zWkH#UWR?uHcr%3yGfiKy(3djldpXLdaSXB~@i|~2KdNi`+E{xZijq$eiF zoB7S*P#gcZZqYM;)4qObvz0y#y$pz(BFKYY%A2ou;BP2Do5lbfX+!?`qT(Eb`dPrhz`39n zmHd`3Wj+m2s~fn!b9*zNqJybQV=Iljm2!F@RXx)4k1@2C9x!d?0?shlO6L_C zD{MusE$&oMCH)XyvS&bd;pbEO>c;l{2Iw)^^Eon zmRgz(WOk&Px+4|c$7^JADr|G{rzae?sX`qlu1TFgu9w-v1P6$tF|?;nEVyNxJL!4hp3BWN zRtIgTWM9cZDIeh0>}X(^;WU8CF2tTz*h@s$H6;oA?$2ZsM#6-zb~sQ#GHsybMjpyD ztRP?oYik%~Jnl#*!S5y~sVcbW#2ZBmOHK>6=C-d-Rwlak;6NwLA4QV$MLj&u_}nNZ zgKm#d5?0!gnQpzPRH(cI*vxaHU;?y6-J@Z~xv2ON8p4zV|pL7l-7ho&rO007+*vUwESQVm|^fw z&8D05RgTKZp1^XIJ6YU=QXx7g7wp!c&F7h9B9`4A(o@*39?sh_Xt@$ce0A7@0{&-% zBKwX)zv&p|BA0)gbA+nudmGA3@pqy-0D4xFdt1kSD6Ho(4J!@wEKAtO! zE;glqM_SgTJ+EXC=7UC2T2XY?|@`AGT*y z;vrK@h+cT$KxPR9v8dxf00-3%Qce#&Gh?*|^0r!Sp~zyc!#6#B)YmN}fDI{!d5zUf2uL8cO!2xF}xR zh0+4O-L;ADz7r64pzD)E%Z9fjn<~e;|^g zrc7}yKfL?6dXm6GwTKK^9TKzx++@(+I`f*Hz8c~3l3OO93& zQ^bb3QTe=6B@HxY!tRNZ#QD{Lw8=PcAIH%NOi??w9UxLYlVu~2t@_4N$F)nci$W=< zlUu{+Dw_mnE|BQvOzf^!<6gfG`ivc6TMx1&BQqoVzdm;svr19ck9t4ZE72iV*esI@ zG1xkxR^?k^eznj2O(w{w=hO{O13y$up^kGC4{ z)wd+{Y^sv%_G~7A?bdS}=_W_S%=|+Sg+~X|8TO&4{wTA_J-wS6doD>%RKRbW;ood5 z8L=ae^R`IWrZ+H3FS_f(OLmfwJ_ghyLOz{1V1W83Mzjl{kCmAXD$d*;_bgv=CnYi2ZOJfz?)EoPWo;L1(O(oee-s{CJ}#)KhYlB} zPjG&9fL{FHp2Y{_&G4-x;>FKCshmlqLuuu@i&tm%=NcA)0b~j6LJ|snWjgb0Fb{fR ziA9a=r^xbLvV`uUGL3ctjy7@0BJl$GeZUTje^_#F?(~t^X|3dQ zNh`p%QrrCmzu4p4!#9V%1-DEvRZB^<*NVv)cVO30xid?Jwe~303ETNg*HS$KjgBBH zRMib+pTA_GZG1`?HfrxO-rvp*Vi{XeiXkech{T4idIfR4Mz9xE7q)n>5EbtpE&S7Sg8rbc~NNB;F% zZZtlm&ymQ>6M0UGUP#NHIx)4!8>fhBtm>#YS-1@XUaEw7wEzR$imJGDfl7fO;Q&aV zH9+=YZ-zR|U^NPmS{~R)G*q&ZOs|4w5e^>~SU4JrU=*ynSZ-pFo-qg0HnqXpDp6Ph zUH>#0+@ASYh3N$vU=Q23AAa+(V$?ji13wc0rLmw|;yB>wj2(b$wbxygn4F4==}5Xx z+zV3Ci!R2c+G>;(-0@AcfbxoucR0nzFUdr8q*ze5jrqE|XS(^TtByk5YLG+$)k}*^qNwm%X0gs z2hQIhGpLLCJi-<x?@NB$D97!Ib~ZHfbLenL2>a-?7}@$hYo z$xZF`xiFY&_G_oP)VzIp3H2!#h`quB+jz^WI06*Zd;>M@| zvg_B{We7_joaUT3c@4T1*{L8C2)O; zGrohVzcHbm@&nWs;YLMJ%%~q>x_x_eP|$f=O@U|sj+8Ng6^?1YV#B-b<*%~^G{>r8 zTiavSK22OK+;D?@JYSer|Md=}^AfCo;8>JcQO0m`P(q1bYXeBuhA1?p1PJ_y` zXvkg<6}|j*B;px zVF7Sh0!5*bKCD8l%rx7yAume%V0$Jr-aJJoH?XPa@s212&z)(|jN6>k4q>~NSE-|r zJ1v|jcXrhT0*;7`wwm-W7dj*JQVArcILR@hsP*WhPurHWV~%QD^5P_O0;ri=^$E2L zs~)aBho0GO9&T!q^@y(-hD{J7N?Ao-juw@Bm|Y-6ywlVbw?yT; z6on-fSxe|+FZ~r2M={nkdUo*@vDw|!G*M1&4D}6Bx>&OsKF8YL5>?UWOEyQl7S^>T z=9;c7AYx%>X&UjNwClxI9o*=^8R}CMCK<@k*ZzL*NLx5%$FP^Po)mgHbW1(vwVe+- zI%j_j^5w3|6#kBs{1UzIbNCc*A%r2@X|=mO$}>s&r|=emIeNCeKMr?MSPV_5h~NpB zH32b0G6<8^dUJo%>6c$L)iUEC5!34*yh@9z9HHSJZE1WSN_0%1 zrM<1gk|kgGOOQ5gqP&7!dH_6N6}eh!uzkScEX0A_JPH%~97xRr^1b^OPl%6}%t!6F zbAP~Y>=6hgI6iaZu0Sl|$Ocr3#{u`pGUcyQ#-Nq@RYoBXnxYV1zIEFV)!t!?ep~P8 zXQ*g1s{-NZnno7Tz%e^B%rv9^?Ff%=PzR-ylvUC`SdFWBV33~uC7Ar8Vx{G@vhVal z73PhPrrt!;Xw5V_7Az7x78gU4nqlZG!ubJ_m#qKEx+^$U{PdeSKFk^hcjylmwzmR1 z=v)gnnZvNeFTkY&G|SJu_ygj}bm5f`OTxM&#rmGGG6HQ`a4eJ8LQO5FUOAPs(IQUl z=x&1yzBa(f*R#1`XOB>$ee(ALeb7~l_F#i^;(6Rj(Ru;OL^@7%a{SaD*9Hn)w&vnX z-SELB)Ty>MCf2i?=ae#$*w5I(BRn$Y%^agUY(P^g5*&<$9EEbU^zS7?1_8uh^c?-p z`gPHom480LK#F$~XWi*sTNVX%C3IcMnxYNXC=i5iRFY{T#sl>=^j8I*aWR+!* z_t`B%xkpRBh51%lz<3u2*S}amU+x~64?$4qmx9k6ux{tNfpa_b1+$ug#)A*=S(Y;y zAgkCfvN6yq7H{v~`NU)YO%fJX!J;rQs{%@C4oEi{M8+oT;tr8siDmJ}q6p%R50RkH zuk7)qHOK)BAKHX5C_l?N2yZgc>U0C36;ZjdBtD;C$n*1l1OPMefo#n0bv-@V7WF zu;nGHo{3;`WlI=wfa7Y!(dMVT!u^CHY&)op`Y#B>4Ai^G7ygt5k3-*V)(ZrwEXbJn z?Itn5A5Gu_rta=l7jt3(5{tmEkc8=mp%R=ChB^Qj&YsZkZy|q*+2pRMOmK^{HgV>j zUz9PFFtz_A(*U>=dsKzbKQzubt7iG-p_B(3aK3WDG}pa`(x8e+`v4&peK;eDkO6=~;o*jOY;S{LQaC7+9=Fg-M z_*4ZjiZ`}Q?oTPm2`nV?+SeU@pA=4}tRMgqGa}1iH34kTA{^sHl_+GqyLs&XXS+Aa z2iPP!UMp|Ro81lh+RdprK}goab_XwCQph@mw^Ur*Ga6qS26F~US4I&x^&U?#MRREz zG<1l!HJtffqQ|gsTiygADjO^4cIHDBDK**_TL#0J`CHP9;w^Y@2em)`OqcQYA!kS> z6nf6#XVTpc3TsJbF$`6llAPow0^qr(IO&5y14OipJPrkislMPBN~NexwF=C#FvT*K z6)U~=i-ZcL5Hv9cgx~+*u^@Ia6IpYowY>EWbxSBnh&|xqJ)q0Jx$E6jV@tc_xo{TP>kJmqzqt5f6KeY8rE@`2H?<~P9ovw`{LM^U2XSH zE(*Jx(hE{et`882z%g_PAC9sUmIl7pB2zMqBxBxYkSg7`7ItyX*?^P$`LC?Hul>Oy z=T!%=-symC7h28%t6aC`h~I79HU^JcUAgPyp1jZjG|~MZL&JLOcp{NM7iwWX_dE#0sgPf= zsK!~2O2O$-EMDI#4AKdud1nfkKBb{r!ZTy#;_v)N{2>;Di%Z0?tNh&!-F#mi7%&R! zWsWCR+QvcEqH01rG@yoTb&xObR!EE!m_ZhU#1YS_1(z@sDOHH^75dtN``agtGXEXd8E6@g(N30Y_3 zOFRiPodUCGFgQgO2ptEVPmw;Gu6wY_crDQ;5b(|*xjd|3q zQkq{zVH5|$;2=a)b%v5=DgcFGW`6M}?fL2FTx9m6iLlBL3hWjj;E{ z$i&W}A4uRz84=Z)%}s3YK(&j(YE;HWSd50uzG;NkIdCF=;&dwMJF%D2jncV_Ks9w9 zg$g;y%JV}@JH`Hb>rp0^rqsx(WK7Qm`IurK05w4j_j_f3nJA=5$2#o2!V2dDefohb6siw zx=8IwamMp%$|5Dm7dVMsiH#iWi77XBx{fzyhvlwj+3#vDjH9tk^|$?h86B&l+@h9a zOXj^(x>Z#=Q8e}DUj{c{WCU=?{-7e&A$g}_(HW^ogX(maf-1#2Y}AYgj4FgE^Q%fs zw`wyau}ApX(nR3<9IqPGq0GFvsqhe1-IYs1u)Ed&L@d%czEKM!K=uIKWRNPfuk^)> zn%~>KL6v&?Xj6dfS#BHxV3MvYyavNpc{PmQjNOsB=uGOPSKi6MMk5&&uu#Gd8iQ%g5t@bhX==wRucd3ot zGaU;a9wCaKQbfY+7i`3~w+9Zf;C<=`gTuM1v_5s=CVZVEPP>sIYa3_ud>!QguIZR8 z`7{I)TfADaZBl6jQ6ulCyqSUtKVg3Xe#>&FTA{Z)|}Z<&m!tJmOa+6AsET_bF=;VuC- z>>_^u)PuucyJQ{g>ch12$}2k~Utzd8umZ9tczgBVvzv5A=46$1yhp(Abf_tRlEu>D z=o0$bQB2&VUWNA(U*=-`!U-m?@i#VUSsMSX^{MHCRBgH#deh#8+S(x7I2{H~jtT>? zDZ%=i_{8{6_`hsr*Pd3O^htO-EQ97KivLa$y>c{I?lUHB4VL`jE#} zN%bA-3nn_gSPx!?%S^I;Xt{7aG(|evX@-TaO$SLqeuXh%6=OzP7Cr0#5L9|Bc^_RA zJOd3ZtnrZP0E=Fik^ptThYG|ue$R=Phv|J z?dvdpgvP^9Tc>=bp~9{DJIvuWc(6-XTujY&8t}#+nALZlvq~ra@YbKF_@4(yudisR@!J2tJ_Z&?)IEcjI_S7I=7&=H}F6GFEE>o2iM~@ZUwy1g1THDtf$tWajf!+W+m)@ZyQHlKzSe?*MG2g)vYgn{} z$99Hk#h(`xRW?yg3fM)N$xP3XFzUT;!;s>EKdj!^vR_WLr6V+$9m8|p>uh+oZt~P} z$cR-t(ePRc(8>Md8?n*$8r=`_`+SKD=Nku@XS<})ao7KhttiqJT!%ClA$Cvu?bu+n zIqcupQ9@p3Mb5P$k$Fj3vwpK>5w@0pz;|6EfB*_AxdEeR_$63sI*9DC6fcz3v@T@X zJ#XYCu1|%Hm39}lo4?za=*|DL?fZb|xny=3TotNGO`+ool}Lc-LmEib{#O5p3h1~E z(N|9mS}H_-j2}ppLC{$In|5CRWV-Tn!Qk++?X-zkaZGXtqh0i8Wv>sAdT;9I1e(Kq zZ?`oW*Vo5lHJaWoE5{N;OwP8Cr%P1;oxor!)3BU+vP5Yc`Ll83IDXc9_^hABtJ8Qr zU#k9Og~oSgIki$m()<1LAMrxgLHFT=5m{iSlUC;X1_GL-x8;lNm>zS93R7}0Er!(7 z53`i%eY=A-^&zt)>Dpt~l&y4@u|5P5pZ$Pl?epK8c6F)nQlP$V_>7R9lCg3pSLUx- zh~TFZX~uYwR)p)2tGMkP=Bj_%?Z@lZK+4n+CMg5eYUc_nBixjY@0cU3BO_k!SUPFp z?2uv3p(OL1g}qZl`g{{R7=TRiTYk)u@c~gKm@9+1;V;+lKc1NM3e7F!^Uz?CXFA10 zQsnVY>T7x*_H8G1D8O7nUC!Q&kPpE+TjalaiIUQ#$U4?+gdMh+wvL2dQgus*yeXCY z;>}u53XGo~5Q%DH81DluVSF~imTP&ZdQ&oBA)bTU2_t)Im3?&QlLQ*#h6Jy;2p!7gRX$I73jkgOGR#1B)b{eachf3%U*@aF&?#FYzxl_&;rE7*LH0+iiR$Ptl>jwgA$o{()P$_h+6Vf zjF=qqc2pzViT^%)$q{7FT`r}Ca$!_f3V@A|w1X*%1mlkMG41>}{Z(8fb_keO_dUD# z1JwGVu!K&+>Dad71}S+NtO|}FZ128+D$>t|-3D$t6v*OgiNDcJynI*Y?$=Tmacxs` z^RMRL=q`7g@+3d~000gfDS}kq;BDWI*P0FO_=IZH^I{J`PCRCdCrte?E>}!GD-}Te zjfK}LkBVW;Iq9W1GsTnaG&X5M2`1>=hQvL!J|`_upnO`k=+g7pHJ2P9jiEFMgp!Z5 zX`fRm0ANQ)7^#f^i-f(fB9|>waURhy_nW)p_p&f4Y}a4uh~%t+am_14NpPa@Mew&w zvs|W!C>%$0&cnS?M9G8fla({UdoaUnbs1uu&u}4=4N^C8n`cgJjUHE zEJu_^Z?rT_baQyLc9yjy4s=KvcL%U#_)g!ge-`yqBx21==^C`O!sLS{VoT4@U+h^C zcLd5`#~N7Awc843*(SYclCpwzS83fJzEbaLC9p2>eS+bk7o1s9M1$A0Kxxs~${zV< zos(G-DzCCwe;K-lgZfH+pX8zra!4jDxIL~(KlD;^Yv~LqL!_UV<-8DGzEcl$^;<^k zJ=V@kLr`ticP=>&uQsXGjtIFOAj4+m^`SQGj{amQLG{Qz65Z0jcvUpCAKkm;9Dahf zZ$D7o)U;jIhZ~D-HH)M_hi-rbgGHDIAn5T%H?%Ob2Tiq}Y7D7s^#J%NI8&!h$+C9v zor9iG2)()NQIP*)u21+GFQtzbVBpv*-KGrV;Nc$xsH|@XM-=X^X&-6@{1pP(4dO`+CFjZ2BZ0MY4Czm$ zS<&@t9No!_3OEBPJGUtTzoPypvL*<}K5MI;3zQO^VVA^Bpf+V>5Fg&0wOJU!#BymU znIHK&+xs}<7pAV>X9p-2E*JpM`DHJQqnYk!{ zi_TDpexAl`743MrTY2A=LC?Y-4oF80xo-^%V2><_D2x%PO@H)3DI%wucsQ6=SaGtc zU_^of*Lp1RxxYy1CLwBpi&L-MvUzs$65TSpt2n6j03a};?>SJ1k65f7kLX9G^-tnT zdGL>U_5$&Zg^m}8S%B@xe`#(uh8IWKKEP8LN|Rbu7yyTP+^1tgwr{Hpg$405uUt49 z{7-N81^G{~Ka1#I&NMtoFJ9;opk2i}!>rlxmp)j$2`)?j{I#;ML>=3cdX*p$j3g?U zEFgr!QT|Oly%3RsT?XaWO;5w*B9~~54;!?9cY}g(JZm$W z8wx?D$0LQxfpG0Q@MLd&lptnHL@br9Zt>27#qfW}_shjpvLBH%R$L*7qz6YG<`S#^FOr{3SE(tFycNp4ifj^G389A`tbkfF$#In4`JOtn%Mxe|F_k!*nbtfDQyS0m=`x zZCsFyu5w-nk?IfbogE&xDpqCT=_XGvLN@FXv@2YDyqAHC-ide54xLU(@7Ay;%Mcu5 z$EvLgFX^{KeFl$^pDIe$_uMO*uiYY)pPf{b^*b_dgtN&*c2ydU_FxY*X;jb$pj@fQ z%zp8P#TI1!yG1!6BO~fp+Ubhgqk;pP01xcSL0Y#PU=76_6&<}Cjxk~WUV|hZ70QP{ z%e$C?k~8BC)Mw_bQ|d7wziKSX{?NGHkFst@@RTI{1z4B-IG*1qsRl^;mD`U#y6?be zJr^6CYL}h}K&l&WQIqy}1e*Pwv%t~Hb-;Ww^pWN6pLoGVbvwx)W3t$X1KTieI!rdObS9Hll6nX zp|6eoFbcah3iZQjk%*q*Jj-w{H-vV!d2&X&U+QXR8_H>Juz(GD$E*U>Nwd{Pomp=I zbi`{x#VGUkNq_oTE|kjSrPg5^@g&74j~JX973#OKFP&lNcpNvw4QEzep>BUL82bOc zi}BW2$!)2&uj(*EKzMHL3vh};nuCrNMCg8ipE=op|&VE^dT^GoQ8?& z7hPIEpNi4<8Sv8t02NAF7Uo zilp5YOJ2{zwyFSD&(dRVK;~FBh{_0$7T8tiSG0fp3S2e(+lh#Q99b?559S0f0eDQy zzz_zBJ{B?{+U<|i50YQgV3rD-GjA}Dv}74|DYH4aMS`O&Y}i;w?Fkezj&%0=1YST4 zLK_Lrt5&8VP$ro#y2cb8E7o(i^Pas=^g!&+4Wx_|F?tv#ZZb`amL zPIDUE+0TMIqcx(yuFR>#B3X_-|F6TCX}TAbO067fbXyR|{^%*iQnvtFQ4cplJUI1Q z(^eX_iMH^dw+IJP!2@s086 zvak^_{dk#EP=F3a{S~X~h=HA)jv9#p6GLd<9p*236-|kUHOl}J^^po%4wgj>hZ9JT zKW^XvAG|6DVC%RmzF>5KCB5q6Uq&~MsiE1(I$I3WO zL>qBWr+^VJVZ*(e&a22CGnb$@TBu^mI9F2?vR}1=(V&(t`dl)Iz-ZGC_JLE_- z>TOVS^1b;d**1wUusucS8@I%F^8&m%{@M|t9_$*av+fCZIT)%Jo zf&)QFW(Pu!1Po~Scg9!Pda(366*`cesplPg^zUr-$v76?^nkQ3R-{~u&d>({`c680 znwAu;+pbZ_9t_Ray%d#pULe&3Yk~Ls8xsRV0{KMtdxVeN2R0D@p6m=l52xethIL)g z$D~4w-d7-n(1}Vc-+?T3Ynl=ba!}N-{0eBH6x5|7+R7-WKv`6jQ=k6vRn>|uY*aEs zL8IU5H32UP1jw}$#+$Qo+hNJ^{)l=V!8r&Z@whxHs{>XDEE*a;v1f9&063&-hQ&Lg z&;IczAAx_aLm7ez3d2mwC`AK#+|MX*wIkoWfW}L2Lkh<{V6>~PxFIQwKK{)(S-saO zw-oOB_DOq@ym=zB*m>kN4A7}($LpjE3#$S=QFKWzDjHMloVq1`FwtwB7}N}p+_l`l z-dC(j2+*MFRT7iv0r*?9=sJ~#m^0K|UjDX0#G61taM1eZyo@~o4#nA<0&=h91`(jO zIrD?OsA5<81}uN(45MCwti>F31?foqa=DbuGLZ#}X6UG6Z&&b?x^pjFQxJ>!A>W)kRp& zSiR!mQBbnw`~#J9{yK8;VURKpU0AYr48%zNRhr4|%Tnu69m7<9P;@)!9qGP*#LP4!=f+J67_2v-c|Ut4=0Cpd`l>ACRIAEz9KzjtOC0st(55w;rL1? zLml0|)3n^oT7W&cBXhf(fQ2pi^o?0?U!L#da&}Kpq=L%jRq5>?Ngycjd-O-y{hx6z zdO(PGCio5C0mX%2Be>l%uYL#x5nwJSi=DFI|afQ;i6FtW-!zLrWAF+ZZqj{|k~LTLRh-2O)k7-pHTJV3=-G*X1Kw|k zpYPV0kK-0e+Qld(7XmLp=+rDLou$zvba zWqwOZ+H5EwO#at+C}1z&WP;lBz#0QP0l&^UfD*|@xYa(EyUZc22-=7>I^ei2et>}N zKjn=PE-XQWj%1T1phrR6hn1q@tb{^qzhSya;ye-F82|&yMvZ^v=O=T)jF3S>$NR$u z_}-Q>y;omXZP|*EQHGt}6f(9;^q|Lj$p)wkB%K_W-79fi5q?;X{+;WP=^Vkk40f&I zj-2@7bp)6?v1`u4csmP0k8Kz#0pbrr(n&D@pwm!+W)H#m2783h2n==jMF*w)#Fj)t zo{$i^Dv<5%tB4W}&h>fj`9JB9vl|et<7g2k(GX38`r!CIdkd@H(ATiQ006Aw0C&&O zHlQ-WAOEIyqFrF)Sne>B2Zd@{QywB&OX*D}B&Lg{XaXk6x7~W=d`Ls*=76%j6)(v zuo2Fq1$ju>{f}Ri8g?2Qd3l8oe<|lFRKcPi zJHSA#)A}53J3TRe`G{hAY5`&??zzK-@f96lt2hk9!(yBCnCbIDo7ueW(>Y|63y>O6 z(r!9vsKVCr9Na?cA6}ed-k_xO`#03}xJa)-ukh8jI=?t=qW8HF6yxVei#WSn+Km)m z|2Wjnkzg4z2fsn?d;+ean+1Q`xN%X3fa7vn3lbBehj<&1>BkG`-YP~ZS`i6`+?p1X^t2$^iAVz=CYRPO* zhZ?DmbXIozEcC3eM$HnW?(DK9&(lvy%e%hvzMu4ys^^YgG6YwHyC%^Vi-)bsRA|ea zKY@>4)&D@^fI`kcWFSYR(O5M{1bb6|`jkqZo#ciYx|u9}gobd#9`K+mSZ%kZc^Rlp z<@kcsH00zbJIE!NtBZB%Su=q8G$Nd4Gifa6Kdz3~B+%3g%3B`vBgGlKS_=^{Q=`eO zN;B*;M*$v)u}+)yN*@$L2~OCYfX*+{s@?tnOBezG0f;~(mljqBsTmi=C(#!)m}j9g`l zk6g9}jF?sZk87^`l1v2)`WGN~o?#JX>0W&&JlhsZeQ)3pfGO71t91{=lUe4pTlpN; zs;>$sZxVY2>ZcYGPy@K2P(L-m?m2cxnc6Z1)?-E>*faDO{EM_}&vDmtj7EWObng?? zH{M^@zDF)Aw14-+B{_L$}8Rq1?LhglgJ) zpb@V)O;pM5_%ZS{?K-k_X_i9`*R=sI&5az0FK&)e!2<9mWaoc1H=F8Ad z+&ze8PKa}AJvXO5wjGByIkz3I(6FT)&jK4MhWJ_rZP~=(n8?waqPF>~E_@R{NmF_K z0+#>)000v6v!1$teeM9GXQE9f?kuIG=F$TqG8BTn9|0moAAWefVxi+iQFwicinA@lPUpXNG3Rlxz@ycRpSk0U-_CWtosBnUQK9F4WH4&su_V2~zm|i1M!%{gAF6{Yl)JSyXXv=`UbmmPpFA z@#YWED?g+>$*Fm+FR!b}1OOCe?_VrF4fwy9$vF+;wwu7&D<~rSQlb{St3(ewkYg5g z*AEU9j3SfRBv=GFdWR&BX%+QNq6T3YM?NNQs#781(@I15o5MbA8b0W|Rg$?Fh81g~ z;$9(?e@RUgS(-uHH||hSjlm|qi-NUbWSl<@89mR@=OW?n%NRe?PBXxZ$N>2*td5S4 zD)bR~Kc#_fz_Co^Ngf#`so}AKdvTkn@9H)a%P2QudNYTW%-O8Num}f`9|(Q&yH_J+ zxEH%}X+Z^35lvHG3)|HXF`kK5< zaQXD2ukiy4Pk9;q{!z10#UPN4`Q-6N;HuKzFwe2ji>zL!EJjOffInG;*GkxY*t< zEE2H7?v6#sP?pD;1+cSm+;P5@1(%t|Apy}5-tuNZ?Yj3mL@7*(Yo(Wz7}5*wM4?G} zU2b)#`M}^}Q@F9q5H^OeGt;9Zr}-7L=E9%1`B!!LjIYuVssI203&g|Yhj}%aL|4O+ z02zIpk-Y|;LJD25%K{4gSfFzZg#cCi&hN_D24Nbh(TScfl<@95N_?eW{<-_bgt@E! zP*;D&|0I5kED_{K)Dobrf=fs;TPjUi<-i72Oy@4TkNably>p`9f;k4uWe7x|0}RPS zY`!8LLhSOI8F*K`)I`8?ybE@K85o;bJC-}no=F2w zgaH1dU+h3&~ALHtFwyPCJ+~ie%k4VCkH^UHS5FOBvdE=$dK4b7}fw|LUF7Ci*I@~e)R9?-| zUI?vZd*a$cm7OW5-~5KD+n?2f;l&K-N=Q1EblPa8Z7}Y>f9WjJ!ibBB|4(7#T*@gm z4a5!sJ z!*RNr720t9X0tQOV}W~3MCLvxr4InAJp-X*o{yu3T&La(RGZ<84y;zb>f&X?e3AXT z)7q9vALVSFseEdYO5=1>9o_);@$(weJ(1OyAHK3NJ#TH?+f6)?WOxz+O(HXn&;r)5 zb7DXQ5}I}%0amg`%SP2hP9mVa_$K1P1sg8*l1HKtu@&1!v^mmI5G2#c-UWTigSUKF z*Zyg=nt@FLcU~^)+-7edGFqc=Ld0_<9g3e2Q+Kih*Xjj|HyNuR(*fP<#9&Gffax3| zV7beCKyT<8Y^^ji!KB|7kS>p$svul?+e$A8$1@LY3>)h)$JksREsFivZ-A#ocSe}y zH$%6d>_E!eY!FF6eOw8o&6iAJ^BZE$BZD9|SR&4oe^R|};RNSS@3838w&?tmtOx3= z^cIAFs<{`(SVz8o%h*{D`gJ5@VO=ia8^hyD_Gj6mk&VlN3mS8L+J|@}2=w&T*Z?S_ zNMF>;fcTnm)VCQxAQ2#lpn~81500G{;H2Ge9=*j)hNbSAxd0UDqRzUw1#kg%m;q>M z9xkx2-IrC33bUUCJpED6?a5^4=fY&?Ob@6L+5~g>33Q%E0s#$_y%x5ku$N+`ye%M&lyq>(kO6Ig3K7A8W+t3|>kPd% z&2du~83y&@4NQZA`hg(qpUC60Pdq`{%&T`2&jR|0S(SNy4`QnjX}AlL zops$b2TEDif`jI2TqS>)+^-`mzfOUJ8W`OxPa4URQEyS?gGQ9Hk!n2l9JD7V&!Xe@^lLq2_@5bN{k@Eo& zp`+XWNNZKUdVAXhG zKK+5E+tyEjxpaa3B^|y10^FWp#Kx1C4wa$fHuiqfx?3kT<{bud^H0v!AvA0}JLl1x z6ij>1D7D}Icv62mkH-iA00IU|#x?*(`UdvEmI36~Ja;oPFn?rAf*vRKUrrZztz}^~ z=&LC?blZuMGcR&kIP0tAW!jrQiu;Lj*F6h7Gv0N0<83ekdq6oKt^fc4ixdd)0XJ1c ztT@iauPu+7f4m2XW1&&;lbYZiCDrlmt>rc{{mujW{*0p-wNfk8V5Swbz#I3(1<@*U zAY_+5)GT-aDM*k2d?P3<2#4h$F6O57I007(Y?g{_^ literal 0 HcmV?d00001 diff --git a/src/components/CodeEditor/index.jsx b/src/components/CodeEditor/index.jsx new file mode 100644 index 0000000..041a19c --- /dev/null +++ b/src/components/CodeEditor/index.jsx @@ -0,0 +1,32 @@ +import React, { useState } from 'react' +import CodeMirror from '@uiw/react-codemirror' +import { javascript } from '@codemirror/lang-javascript' +import { monokai } from '@uiw/codemirror-theme-monokai' +import { useStore } from '@/hooks/useStore' +// import { oneDark } from '@codemirror/theme-one-dark' + +const CodeEditor = ({ code, onChange }) => { + const [currentCode, setCurrentCode] = useState(code) + + const [theme] = useStore(s => s.theme, a => a.setTheme) + + const onCodeChange = (value, viewUpdate) => { + onChange(value) + setCurrentCode(value) + } + + return ( + <> + + + ) +} + +export default CodeEditor diff --git a/src/components/CodePlayground/index.jsx b/src/components/CodePlayground/index.jsx new file mode 100644 index 0000000..c52edb7 --- /dev/null +++ b/src/components/CodePlayground/index.jsx @@ -0,0 +1,88 @@ +import React, { useEffect, useState } from 'react' +import { Icons } from '../Icons' +import { LiveProvider, LiveError, LivePreview } from 'react-live' +import CodeEditor from '../CodeEditor' +import useKeyPress from '@/hooks/useKeyPress' +import { toast } from 'react-toastify' +import presets from '@/utils/globalPresets' + +const CodePlayground = ({ code, onChange, scope }) => { + const [view, setView] = useState('preview') + const [currentCode, setCurrentCode] = useState(code) + + const toggleView = () => { + setView(view === 'preview' ? 'code' : 'preview') + } + + useKeyPress('Tab', toggleView, true) + + const copyToClipboard = () => { + navigator.clipboard.writeText(code).then(() => { + toast.success('Código copiado al portapapeles', presets.toaster) + }).catch(err => { + console.error('Algo salió mal al copiar el código: ', err) + }) + } + + const handleCodeChange = (editor, data, value) => { + setCurrentCode(editor) + onChange(editor) + } + + useEffect(() => { + setCurrentCode(code) + }, [code]) + + return ( +
+
+
+ + +
+ +
+ + +
+ +
+ + { view === 'preview' && +
+ + +
+ } + +
+ +
+
+
+
+ ) +} + +export default CodePlayground diff --git a/src/components/Icons/index.jsx b/src/components/Icons/index.jsx new file mode 100644 index 0000000..6a72b7a --- /dev/null +++ b/src/components/Icons/index.jsx @@ -0,0 +1,25 @@ +import { BsSearch } from 'react-icons/bs' +import { IoEllipsisVertical, IoFilter } from 'react-icons/io5' +import { DocumentPlusIcon, EyeIcon, PencilSquareIcon } from '@heroicons/react/24/solid' +import { FaChevronLeft, FaChevronRight, FaPaperclip, FaUser } from 'react-icons/fa' +import { RiEyeLine } from 'react-icons/ri' +import { LuEye, LuCode2, LuClipboardList } from 'react-icons/lu' + +export const Icons = { + // Common Icons + Search: BsSearch, + New: DocumentPlusIcon, + Edit: PencilSquareIcon, + View: IoFilter, + Pre: FaChevronLeft, + Next: FaChevronRight, + User: FaUser, + Details: EyeIcon, + Attachments: FaPaperclip, + Options: IoEllipsisVertical, + + Eye: LuEye, + Code: LuCode2, + Copy: LuClipboardList + +} diff --git a/src/components/LivePreview/index.jsx b/src/components/LivePreview/index.jsx new file mode 100644 index 0000000..8aae735 --- /dev/null +++ b/src/components/LivePreview/index.jsx @@ -0,0 +1,41 @@ +import React, { useEffect, useRef } from 'react' +import { transform } from '@babel/standalone' + +const LivePreview = ({ code }) => { + const iframeRef = useRef(null) + + useEffect(() => { + if (!iframeRef.current) return + + // Aquí, asegúrate de que 'code' contenga solo el JSX, no una declaración de componente. + // Por ejemplo, debería verse así: "
Hello from JSX!
;" + const transformedCode = transform(`<>${code}`, { + presets: ['react'] + }).code + + const iframe = iframeRef.current + const iframeDoc = iframe.contentDocument || iframe.contentWindow.document + iframeDoc.open() + iframeDoc.write(` + + + Preview + +
+ + + + + + `) + iframeDoc.close() + }, [code]) + + return