From 6e33faa5fd9dd6e7f397c744800cd942572bfccf Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Fri, 25 Sep 2026 23:41:39 +0100 Subject: [PATCH] Initialize project structure with client and server setup, including environment configuration, package management, and essential assets. Added .env.example, .gitignore, package.json, pnpm workspace configuration, and client-side files including HTML, CSS, and SVG assets. --- .env.example | 45 + .gitignore | 5 + package.json | 14 + .../client/assets/lottie/no-flower-plant.json | 10329 ++++++++++++++++ .../assets/lottie/water-animation.lottie | Bin 0 -> 1594 bytes packages/client/assets/png/pcb-board.png | Bin 0 -> 44533 bytes packages/client/assets/png/solar-panel.png | Bin 0 -> 48734 bytes packages/client/assets/svg/Loading.svg | 7 + packages/client/assets/svg/PatchDry.svg | 1186 ++ packages/client/assets/svg/PatchNormal.svg | 1186 ++ packages/client/assets/svg/PatchWet.svg | 1186 ++ packages/client/assets/svg/produce/apple.svg | 3 + packages/client/assets/svg/produce/beet.svg | 3 + .../client/assets/svg/produce/cabbage.svg | 3 + packages/client/assets/svg/produce/carrot.svg | 27 + packages/client/assets/svg/produce/cherry.svg | 3 + packages/client/assets/svg/produce/corn.svg | 3 + .../client/assets/svg/produce/cucumber.svg | 3 + packages/client/assets/svg/produce/kiwi.svg | 3 + packages/client/assets/svg/produce/leek.svg | 3 + .../client/assets/svg/produce/lettuce.svg | 3 + packages/client/assets/svg/produce/peas.svg | 3 + packages/client/assets/svg/produce/plum.svg | 3 + packages/client/assets/svg/produce/potato.svg | 3 + packages/client/assets/svg/produce/radish.svg | 3 + .../client/assets/svg/produce/raspberry.svg | 3 + .../client/assets/svg/produce/strawberry.svg | 3 + packages/client/assets/svg/produce/tomato.svg | 3 + packages/client/index.html | 26 + packages/client/package-lock.json | 3192 +++++ packages/client/package.json | 32 + packages/client/src/App.css | 219 + packages/client/src/App.jsx | 153 + .../client/src/components/AnimatedOutlet.css | 82 + .../client/src/components/AnimatedOutlet.jsx | 184 + .../client/src/components/AnimatedText.css | 46 + .../client/src/components/AnimatedText.jsx | 198 + packages/client/src/components/Button.css | 125 + packages/client/src/components/Button.jsx | 47 + .../client/src/components/DateTimeInput.css | 184 + .../client/src/components/DateTimeInput.jsx | 406 + packages/client/src/components/Drawer.css | 458 + packages/client/src/components/Drawer.jsx | 508 + packages/client/src/components/Flex.css | 6 + packages/client/src/components/Flex.jsx | 70 + .../src/components/HistoryLineChart.css | 125 + .../src/components/HistoryLineChart.jsx | 481 + packages/client/src/components/IconButton.css | 106 + packages/client/src/components/IconButton.jsx | 44 + packages/client/src/components/Image.css | 73 + packages/client/src/components/Image.jsx | 155 + packages/client/src/components/ImageList.css | 106 + packages/client/src/components/ImageList.jsx | 138 + .../client/src/components/ImageListItem.jsx | 38 + .../client/src/components/ImageSlideshow.css | 75 + .../client/src/components/ImageSlideshow.jsx | 183 + packages/client/src/components/Input.css | 283 + packages/client/src/components/Input.jsx | 252 + packages/client/src/components/Label.css | 3 + packages/client/src/components/Label.jsx | 19 + .../client/src/components/LifecyclePhase.css | 70 + .../client/src/components/LifecyclePhase.jsx | 371 + .../client/src/components/LifecyclePhases.css | 11 + .../client/src/components/LifecyclePhases.jsx | 206 + .../client/src/components/LoadingIcon.css | 19 + .../client/src/components/LoadingIcon.jsx | 21 + packages/client/src/components/Metric.jsx | 10 + packages/client/src/components/Metrics.css | 5 + packages/client/src/components/Metrics.jsx | 36 + packages/client/src/components/PageScroll.css | 175 + packages/client/src/components/PageScroll.jsx | 88 + packages/client/src/components/PlantGrid.css | 118 + packages/client/src/components/PlantGrid.jsx | 154 + packages/client/src/components/Popover.css | 200 + packages/client/src/components/Popover.jsx | 207 + .../client/src/components/ProduceIcon.jsx | 66 + .../src/components/ProduceIconSelect.css | 86 + .../src/components/ProduceIconSelect.jsx | 80 + packages/client/src/components/Select.css | 219 + packages/client/src/components/Select.jsx | 221 + packages/client/src/components/Sidebar.css | 265 + packages/client/src/components/Sidebar.jsx | 226 + packages/client/src/components/Slider.css | 93 + packages/client/src/components/Slider.jsx | 230 + packages/client/src/components/Switch.css | 167 + packages/client/src/components/Switch.jsx | 133 + packages/client/src/components/Table.css | 34 + packages/client/src/components/Table.jsx | 21 + .../components/TemperatureHumidityDisplay.css | 13 + .../components/TemperatureHumidityDisplay.jsx | 31 + packages/client/src/components/TextArea.css | 246 + packages/client/src/components/TextArea.jsx | 269 + packages/client/src/components/Untitled | 1 + .../client/src/components/UploadImage.jsx | 58 + .../client/src/components/WaterScheduler.css | 304 + .../client/src/components/WaterScheduler.jsx | 122 + .../src/components/WaterSchedulerItem.jsx | 74 + .../src/components/WaterSchedulerRow.jsx | 81 + .../src/components/allotment/Battery.css | 83 + .../src/components/allotment/Battery.jsx | 51 + .../client/src/components/allotment/Patch.css | 161 + .../client/src/components/allotment/Patch.jsx | 239 + .../client/src/components/allotment/Plant.css | 52 + .../client/src/components/allotment/Plant.jsx | 700 ++ .../components/allotment/PowerFlowLine.css | 74 + .../components/allotment/PowerFlowLine.jsx | 49 + .../src/components/allotment/WaterTank.css | 110 + .../src/components/allotment/WaterTank.jsx | 68 + .../client/src/components/produceIconIds.js | 25 + packages/client/src/contexts/ApiContext.jsx | 295 + packages/client/src/contexts/AuthContext.jsx | 26 + .../client/src/contexts/LottieFileContext.jsx | 139 + packages/client/src/contexts/ThemeContext.jsx | 199 + .../src/drawers/AddWaterScheduleDrawer.jsx | 158 + .../client/src/drawers/EditPatchDrawer.jsx | 631 + .../drawers/EditWateringScheduleDrawer.jsx | 186 + .../client/src/drawers/PatchInfoDrawer.jsx | 161 + .../client/src/forms/WateringScheduleForm.jsx | 215 + packages/client/src/main.jsx | 11 + packages/client/src/pages/PatchesPage.jsx | 88 + packages/client/src/pages/PowerPage.css | 44 + packages/client/src/pages/PowerPage.jsx | 100 + .../client/src/pages/WaterSchedulesPage.jsx | 97 + packages/client/src/pages/WaterTankPage.jsx | 86 + .../client/src/pages/WateringSessionPage.jsx | 86 + packages/client/src/responsive.css | 56 + .../client/src/utils/waterScheduleTimeline.js | 18 + packages/client/src/vite-env.d.ts | 2 + packages/client/vite.config.js | 21 + packages/server/auth/oidc.js | 104 + packages/server/config.js | 157 + packages/server/config.json | 139 + packages/server/config/mqtt.json | 12 + packages/server/constants/produceIcons.js | 25 + packages/server/db/connect.js | 11 + packages/server/db/models/Device.schema.js | 15 + packages/server/db/models/History.schema.js | 50 + packages/server/db/models/Image.schema.js | 13 + packages/server/db/models/Patch.schema.js | 84 + .../server/db/models/PowerState.schema.js | 22 + .../server/db/models/WaterSchedule.schema.js | 38 + packages/server/db/models/WaterTank.schema.js | 10 + .../db/models/WateringSession.schema.js | 18 + packages/server/db/models/index.js | 8 + packages/server/index.js | 163 + packages/server/logger.js | 29 + packages/server/mqtt/MqttTtnIngest.js | 148 + packages/server/mqtt/loadConfig.js | 29 + packages/server/package-lock.json | 2857 +++++ packages/server/package.json | 28 + packages/server/routes/images.js | 83 + packages/server/services/allotmentState.js | 82 + packages/server/services/devices.js | 117 + packages/server/services/history.js | 298 + packages/server/services/images.js | 239 + packages/server/services/patchGrowingState.js | 720 ++ packages/server/services/patches.js | 604 + packages/server/services/powerState.js | 111 + packages/server/services/waterSchedules.js | 274 + packages/server/services/waterTank.js | 16 + packages/server/services/wateringSessions.js | 41 + packages/server/socket/SocketClient.js | 30 + packages/server/socket/SocketManager.js | 87 + .../server/socket/SubscriptionRegistry.js | 61 + packages/server/socket/allotmentSocketApi.js | 343 + pnpm-lock.yaml | 6082 +++++++++ pnpm-workspace.yaml | 5 + 167 files changed, 44165 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 package.json create mode 100644 packages/client/assets/lottie/no-flower-plant.json create mode 100644 packages/client/assets/lottie/water-animation.lottie create mode 100644 packages/client/assets/png/pcb-board.png create mode 100644 packages/client/assets/png/solar-panel.png create mode 100644 packages/client/assets/svg/Loading.svg create mode 100644 packages/client/assets/svg/PatchDry.svg create mode 100644 packages/client/assets/svg/PatchNormal.svg create mode 100644 packages/client/assets/svg/PatchWet.svg create mode 100644 packages/client/assets/svg/produce/apple.svg create mode 100644 packages/client/assets/svg/produce/beet.svg create mode 100644 packages/client/assets/svg/produce/cabbage.svg create mode 100644 packages/client/assets/svg/produce/carrot.svg create mode 100644 packages/client/assets/svg/produce/cherry.svg create mode 100644 packages/client/assets/svg/produce/corn.svg create mode 100644 packages/client/assets/svg/produce/cucumber.svg create mode 100644 packages/client/assets/svg/produce/kiwi.svg create mode 100644 packages/client/assets/svg/produce/leek.svg create mode 100644 packages/client/assets/svg/produce/lettuce.svg create mode 100644 packages/client/assets/svg/produce/peas.svg create mode 100644 packages/client/assets/svg/produce/plum.svg create mode 100644 packages/client/assets/svg/produce/potato.svg create mode 100644 packages/client/assets/svg/produce/radish.svg create mode 100644 packages/client/assets/svg/produce/raspberry.svg create mode 100644 packages/client/assets/svg/produce/strawberry.svg create mode 100644 packages/client/assets/svg/produce/tomato.svg create mode 100644 packages/client/index.html create mode 100644 packages/client/package-lock.json create mode 100644 packages/client/package.json create mode 100644 packages/client/src/App.css create mode 100644 packages/client/src/App.jsx create mode 100644 packages/client/src/components/AnimatedOutlet.css create mode 100644 packages/client/src/components/AnimatedOutlet.jsx create mode 100644 packages/client/src/components/AnimatedText.css create mode 100644 packages/client/src/components/AnimatedText.jsx create mode 100644 packages/client/src/components/Button.css create mode 100644 packages/client/src/components/Button.jsx create mode 100644 packages/client/src/components/DateTimeInput.css create mode 100644 packages/client/src/components/DateTimeInput.jsx create mode 100644 packages/client/src/components/Drawer.css create mode 100644 packages/client/src/components/Drawer.jsx create mode 100644 packages/client/src/components/Flex.css create mode 100644 packages/client/src/components/Flex.jsx create mode 100644 packages/client/src/components/HistoryLineChart.css create mode 100644 packages/client/src/components/HistoryLineChart.jsx create mode 100644 packages/client/src/components/IconButton.css create mode 100644 packages/client/src/components/IconButton.jsx create mode 100644 packages/client/src/components/Image.css create mode 100644 packages/client/src/components/Image.jsx create mode 100644 packages/client/src/components/ImageList.css create mode 100644 packages/client/src/components/ImageList.jsx create mode 100644 packages/client/src/components/ImageListItem.jsx create mode 100644 packages/client/src/components/ImageSlideshow.css create mode 100644 packages/client/src/components/ImageSlideshow.jsx create mode 100644 packages/client/src/components/Input.css create mode 100644 packages/client/src/components/Input.jsx create mode 100644 packages/client/src/components/Label.css create mode 100644 packages/client/src/components/Label.jsx create mode 100644 packages/client/src/components/LifecyclePhase.css create mode 100644 packages/client/src/components/LifecyclePhase.jsx create mode 100644 packages/client/src/components/LifecyclePhases.css create mode 100644 packages/client/src/components/LifecyclePhases.jsx create mode 100644 packages/client/src/components/LoadingIcon.css create mode 100644 packages/client/src/components/LoadingIcon.jsx create mode 100644 packages/client/src/components/Metric.jsx create mode 100644 packages/client/src/components/Metrics.css create mode 100644 packages/client/src/components/Metrics.jsx create mode 100644 packages/client/src/components/PageScroll.css create mode 100644 packages/client/src/components/PageScroll.jsx create mode 100644 packages/client/src/components/PlantGrid.css create mode 100644 packages/client/src/components/PlantGrid.jsx create mode 100644 packages/client/src/components/Popover.css create mode 100644 packages/client/src/components/Popover.jsx create mode 100644 packages/client/src/components/ProduceIcon.jsx create mode 100644 packages/client/src/components/ProduceIconSelect.css create mode 100644 packages/client/src/components/ProduceIconSelect.jsx create mode 100644 packages/client/src/components/Select.css create mode 100644 packages/client/src/components/Select.jsx create mode 100644 packages/client/src/components/Sidebar.css create mode 100644 packages/client/src/components/Sidebar.jsx create mode 100644 packages/client/src/components/Slider.css create mode 100644 packages/client/src/components/Slider.jsx create mode 100644 packages/client/src/components/Switch.css create mode 100644 packages/client/src/components/Switch.jsx create mode 100644 packages/client/src/components/Table.css create mode 100644 packages/client/src/components/Table.jsx create mode 100644 packages/client/src/components/TemperatureHumidityDisplay.css create mode 100644 packages/client/src/components/TemperatureHumidityDisplay.jsx create mode 100644 packages/client/src/components/TextArea.css create mode 100644 packages/client/src/components/TextArea.jsx create mode 100644 packages/client/src/components/Untitled create mode 100644 packages/client/src/components/UploadImage.jsx create mode 100644 packages/client/src/components/WaterScheduler.css create mode 100644 packages/client/src/components/WaterScheduler.jsx create mode 100644 packages/client/src/components/WaterSchedulerItem.jsx create mode 100644 packages/client/src/components/WaterSchedulerRow.jsx create mode 100644 packages/client/src/components/allotment/Battery.css create mode 100644 packages/client/src/components/allotment/Battery.jsx create mode 100644 packages/client/src/components/allotment/Patch.css create mode 100644 packages/client/src/components/allotment/Patch.jsx create mode 100644 packages/client/src/components/allotment/Plant.css create mode 100644 packages/client/src/components/allotment/Plant.jsx create mode 100644 packages/client/src/components/allotment/PowerFlowLine.css create mode 100644 packages/client/src/components/allotment/PowerFlowLine.jsx create mode 100644 packages/client/src/components/allotment/WaterTank.css create mode 100644 packages/client/src/components/allotment/WaterTank.jsx create mode 100644 packages/client/src/components/produceIconIds.js create mode 100644 packages/client/src/contexts/ApiContext.jsx create mode 100644 packages/client/src/contexts/AuthContext.jsx create mode 100644 packages/client/src/contexts/LottieFileContext.jsx create mode 100644 packages/client/src/contexts/ThemeContext.jsx create mode 100644 packages/client/src/drawers/AddWaterScheduleDrawer.jsx create mode 100644 packages/client/src/drawers/EditPatchDrawer.jsx create mode 100644 packages/client/src/drawers/EditWateringScheduleDrawer.jsx create mode 100644 packages/client/src/drawers/PatchInfoDrawer.jsx create mode 100644 packages/client/src/forms/WateringScheduleForm.jsx create mode 100644 packages/client/src/main.jsx create mode 100644 packages/client/src/pages/PatchesPage.jsx create mode 100644 packages/client/src/pages/PowerPage.css create mode 100644 packages/client/src/pages/PowerPage.jsx create mode 100644 packages/client/src/pages/WaterSchedulesPage.jsx create mode 100644 packages/client/src/pages/WaterTankPage.jsx create mode 100644 packages/client/src/pages/WateringSessionPage.jsx create mode 100644 packages/client/src/responsive.css create mode 100644 packages/client/src/utils/waterScheduleTimeline.js create mode 100644 packages/client/src/vite-env.d.ts create mode 100644 packages/client/vite.config.js create mode 100644 packages/server/auth/oidc.js create mode 100644 packages/server/config.js create mode 100644 packages/server/config.json create mode 100644 packages/server/config/mqtt.json create mode 100644 packages/server/constants/produceIcons.js create mode 100644 packages/server/db/connect.js create mode 100644 packages/server/db/models/Device.schema.js create mode 100644 packages/server/db/models/History.schema.js create mode 100644 packages/server/db/models/Image.schema.js create mode 100644 packages/server/db/models/Patch.schema.js create mode 100644 packages/server/db/models/PowerState.schema.js create mode 100644 packages/server/db/models/WaterSchedule.schema.js create mode 100644 packages/server/db/models/WaterTank.schema.js create mode 100644 packages/server/db/models/WateringSession.schema.js create mode 100644 packages/server/db/models/index.js create mode 100644 packages/server/index.js create mode 100644 packages/server/logger.js create mode 100644 packages/server/mqtt/MqttTtnIngest.js create mode 100644 packages/server/mqtt/loadConfig.js create mode 100644 packages/server/package-lock.json create mode 100644 packages/server/package.json create mode 100644 packages/server/routes/images.js create mode 100644 packages/server/services/allotmentState.js create mode 100644 packages/server/services/devices.js create mode 100644 packages/server/services/history.js create mode 100644 packages/server/services/images.js create mode 100644 packages/server/services/patchGrowingState.js create mode 100644 packages/server/services/patches.js create mode 100644 packages/server/services/powerState.js create mode 100644 packages/server/services/waterSchedules.js create mode 100644 packages/server/services/waterTank.js create mode 100644 packages/server/services/wateringSessions.js create mode 100644 packages/server/socket/SocketClient.js create mode 100644 packages/server/socket/SocketManager.js create mode 100644 packages/server/socket/SubscriptionRegistry.js create mode 100644 packages/server/socket/allotmentSocketApi.js create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..40049b3 --- /dev/null +++ b/.env.example @@ -0,0 +1,45 @@ +# Server +PORT=3001 +NODE_ENV=development +MONGODB_URI=mongodb://127.0.0.1:27017/toms-allotment +SESSION_SECRET=replace-with-long-random-string + +# Browser origin (CORS + session). In dev with Vite, use the Vite dev server URL so cookies work through the proxy. +CLIENT_URL=http://localhost:5173 + +# OIDC (optional — omit to disable sign-in; watering stays disabled) +OIDC_ISSUER=https://your-idp.example.com/realms/your-realm +OIDC_CLIENT_ID=toms-allotment +OIDC_CLIENT_SECRET= +# In dev, use Vite proxy so the callback is same-site with the UI: +OIDC_REDIRECT_URI=http://localhost:5173/auth/callback + +# MQTT (optional — copy config/mqtt.example.json to config/mqtt.json) +MQTT_CONFIG_PATH= +MQTT_PASSWORD= + +# Single TTN device (optional — overrides packages/server/config.json device.*) +# DEMO_* still supported; DEVICE_TTN_* wins if both are set. +DEMO_TTN_APP_ID=demo-app +DEMO_TTN_DEV_ID=demo-device +# DEVICE_TTN_APPLICATION_ID= +# DEVICE_TTN_DEVICE_ID= +# DEVICE_NAME= + +# S3-compatible storage (patch images). Prefer env for secrets — do not commit keys. +# Cloudflare R2: endpoint https://.r2.cloudflarestorage.com (no bucket in path). +# Region is forced to "auto" for R2 when the endpoint host is r2.cloudflarestorage.com. +# MinIO: set S3_ENDPOINT (e.g. http://localhost:9000) and S3_FORCE_PATH_STYLE=true +S3_BUCKET= +S3_PREFIX=allotment-images +S3_ENDPOINT= +# R2 API token or MinIO access key (AWS_* also work if unset here) +S3_ACCESS_KEY_ID= +S3_SECRET_ACCESS_KEY= +# Optional (temporary creds / assume-role) +S3_SESSION_TOKEN= +S3_FORCE_PATH_STYLE= +AWS_REGION= +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_SESSION_TOKEN= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af3f68a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules +dist +.env +*.log +.DS_Store diff --git a/package.json b/package.json new file mode 100644 index 0000000..ff4415e --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "toms-allotment", + "version": "0.0.1", + "private": true, + "type": "module", + "scripts": { + "dev": "concurrently \"pnpm --filter @toms-allotment/server dev\" \"pnpm --filter @toms-allotment/client dev\"", + "build": "pnpm --filter @toms-allotment/client build", + "start": "pnpm --filter @toms-allotment/client build && pnpm --filter @toms-allotment/server start" + }, + "devDependencies": { + "concurrently": "^8.2.2" + } +} diff --git a/packages/client/assets/lottie/no-flower-plant.json b/packages/client/assets/lottie/no-flower-plant.json new file mode 100644 index 0000000..f648614 --- /dev/null +++ b/packages/client/assets/lottie/no-flower-plant.json @@ -0,0 +1,10329 @@ +{ + "nm": "Main Scene", + "cl": "main scene", + "ddd": 0, + "h": 1080, + "w": 1080, + "meta": { + "g": "@lottiefiles/creator 1.84.0" + }, + "layers": [ + { + "ty": 4, + "nm": "Dust-Foreground", + "cl": "dirt-foreground", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [50.385, 53.564, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [500, 500, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [539.425, 797.822], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-2.58, -1.497], + [0, 0], + [3.141, 0.719], + [0, 0] + ], + "o": [ + [0, 0], + [2.613, 1.497], + [0, 0], + [-3.109, -0.715], + [0, 0] + ], + "v": [ + [-5.638, -0.391], + [2.629, -0.781], + [5.638, 2.278], + [-0.876, 0.29], + [-5.638, -0.393] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [66.558, 97.134], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-3.607, -0.913], + [0, 0], + [2.382, 0.13], + [0, 0] + ], + "o": [ + [0, 0], + [3.57, 0.911], + [0, 0], + [-2.38, -0.094], + [0, 0] + ], + "v": [ + [-6.697, 1.219], + [0.712, -2], + [6.697, 2.913], + [-2.893, 1.09], + [-6.695, 1.22] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [80.182, 91.195], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 3, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-2.418, -0.781], + [0, 0], + [1.59, 0.617] + ], + "o": [ + [0, 0], + [2.413, 0.813], + [0, 0], + [-1.554, -0.618] + ], + "v": [ + [-4.877, -0.846], + [0.909, -2.083], + [4.877, 2.864], + [-1.042, 0.228] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [52.67, 84.021], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 4", + "cl": "group 4", + "ix": 4, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-2.578, 1.172], + [-0.727, -1.073], + [2.217, -0.879] + ], + "o": [ + [0, 0], + [2.579, -1.203], + [0.694, 1.075], + [-2.217, 0.879] + ], + "v": [ + [-6.596, 3.091], + [-1.902, -1.888], + [5.902, 0.682], + [-2.1, 1.366] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [46.882, 92.383], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 5", + "cl": "group 5", + "ix": 5, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-5.325, -3.482], + [0, 0], + [2.777, -0.356], + [0, 0] + ], + "o": [ + [3.34, 2.178], + [0, 0], + [-2.744, 0.327], + [1.653, -3.904] + ], + "v": [ + [2.547, -0.879], + [6.382, 4.361], + [-1.488, 1.105], + [-6.382, 2.733] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [31.788, 91.96], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 6", + "cl": "group 6", + "ix": 6, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-1.851, -1.464], + [0, 0], + [4.43, 0.425], + [0, 0] + ], + "o": [ + [0, 0], + [1.819, 1.464], + [0, 0], + [-4.431, -0.424], + [0, 0] + ], + "v": [ + [-1.852, -2.961], + [4.629, -1.497], + [6.877, 2.961], + [-1.819, -0.229], + [-6.877, -0.424] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [17.172, 89.647], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 7", + "cl": "group 7", + "ix": 7, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-1.622, -0.065], + [-0.927, -0.412], + [-2.347, 0.975], + [0, 0], + [-0.995, 1.171], + [0, 0], + [-0.923, 1.142], + [-0.331, -0.165], + [-0.894, 0], + [0, 0], + [0, 0], + [1.019, -0.321], + [0, 0], + [1.458, 0], + [0, 0], + [-0.858, -0.781], + [0, 0], + [0.86, -0.063], + [0, 0], + [-1.059, -0.879], + [-0.529, -0.814], + [1.322, -0.619], + [0.761, -0.879], + [0.349, -0.087], + [0, 0], + [1.721, 0.944], + [0, 0] + ], + "o": [ + [0, 0], + [1.016, 0.04], + [0, 0], + [2.315, -0.947], + [0, 0], + [1.025, -1.136], + [0, 0], + [0.962, -1.172], + [0.362, 0.163], + [0.894, 0], + [0, 0], + [-1.051, 0.2], + [-1.787, 0.521], + [0, 0], + [-1.421, 0], + [0, 0], + [0.827, 0.748], + [0, 0], + [-0.859, 0.062], + [0, 0], + [0.694, 0.585], + [-1.554, -0.685], + [-0.993, 0.455], + [-0.357, 0.043], + [-1.62, 0.421], + [0, 0], + [-1.72, -0.975], + [0, 0] + ], + "v": [ + [-17.033, 6.279], + [-13.592, 3.482], + [-10.65, 4.165], + [-8.336, -0.096], + [-4.896, -0.617], + [-3.805, -4.391], + [-1.292, -5.368], + [1.915, -8.007], + [5.422, -9.829], + [8.596, -12.107], + [10.617, -10.87], + [17.033, -5.958], + [13.924, -5.176], + [11.51, -3.387], + [7.372, -5.078], + [5.16, -3.516], + [9.889, -1.922], + [11.773, 0.876], + [4.003, 2.012], + [1.452, 4.396], + [5.62, 6.122], + [7.702, 8.758], + [2.975, 8.27], + [0.262, 10.482], + [-0.797, 10.678], + [-3.876, 12.107], + [-7.381, 8.495], + [-14.258, 8.887] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5059, 0.2078, 0.1137], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [40.487, 78.976], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Dust-Body-Bit5", + "cl": "dirt-body-bit5", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [-5.551, 316.252, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [535.385], + "t": 0 + }, + { + "s": [551.635], + "t": 5 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.124, + "y": -1.177 + }, + "i": { + "x": 0.833, + "y": 1 + }, + "s": [869.252], + "t": 0 + }, + { + "s": [874.002], + "t": 5 + } + ], + "ix": 4 + } + }, + "r": { + "a": 0, + "k": 200, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "cl": "ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.046, 0], + [0, -11.046], + [11.046, 0], + [3.238, 10.56] + ], + "o": [ + [11.046, 0], + [0, 11.046], + [-11.046, 0], + [-4.035, -13.159] + ], + "v": [ + [-1.812, -14.004], + [20, 0], + [0, 10.5], + [-20, 0] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [-5, 321], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 2 + }, + { + "ty": 4, + "nm": "Dust-Body-Bit4", + "cl": "dirt-body-bit4", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [-5.551, 316.252, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [539.135], + "t": 0 + }, + { + "s": [525.385], + "t": 5 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.124, + "y": 0.276 + }, + "i": { + "x": 0.833, + "y": 1 + }, + "s": [893.002], + "t": 0 + }, + { + "s": [872.752], + "t": 5 + } + ], + "ix": 4 + } + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "cl": "ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.046, 0], + [0, -11.046], + [11.046, 0], + [-5.172, 9.76] + ], + "o": [ + [11.046, 0], + [0, 11.046], + [-11.046, 0], + [5.565, -10.5] + ], + "v": [ + [0, -20], + [20, 0], + [0, 10.5], + [-20, 0] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [-5, 321], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 3 + }, + { + "ty": 4, + "nm": "Flower2-Body", + "cl": "flower2-body", + "sr": 1, + "st": -10, + "op": 100, + "ip": 50, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [149.483, 139.344, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [0, 0, 100], + "t": 50 + }, + { + "s": [200, 200, 100], + "t": 90 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [491.422, 328.829], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-0.738, -0.005], + [-1.108, -1.064], + [-0.087, -1.535], + [0.252, -0.688], + [0.505, -0.53], + [0.674, -0.284], + [0.732, 0.009], + [1.106, 1.047], + [0.105, 1.521], + [-0.25, 0.697], + [-0.506, 0.538], + [-0.678, 0.291] + ], + "o": [ + [1.535, 0.023], + [1.107, 1.064], + [0.042, 0.731], + [-0.253, 0.688], + [-0.506, 0.53], + [-0.675, 0.284], + [-1.521, -0.018], + [-1.107, -1.046], + [-0.05, -0.738], + [0.249, -0.696], + [0.506, -0.538], + [0.679, -0.29] + ], + "v": [ + [-0.287, -5.692], + [3.824, -4.001], + [5.682, 0.043], + [5.363, 2.195], + [4.213, 4.041], + [2.424, 5.275], + [0.292, 5.692], + [-3.795, 4.036], + [-5.679, 0.043], + [-5.376, -2.132], + [-4.231, -4.003], + [-2.435, -5.26] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 0.9098, 0.0941], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [142.198, 128.222], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.495, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [0, 0], + [0.713, 2.729], + [-2.322, 1.111], + [0, 0], + [-3.056, -1.439], + [0, 0], + [3.309, -1.519], + [0, 0], + [0.528, -1.481], + [3.252, 0.425], + [0, 0], + [2.109, 2.09], + [0.313, 2.167], + [0, 0] + ], + "o": [ + [0, 0], + [-0.44, -2.169], + [2.288, -0.906], + [0, 0], + [3.572, 2.307], + [4.279, 0.019], + [-3.03, 1.795], + [0, 0], + [-1.201, 1.545], + [-3.217, -0.421], + [0, 0], + [-1.252, -1.241], + [-0.696, -2.299], + [0, 0] + ], + "v": [ + [-14.046, -2.526], + [-16.965, -6.567], + [-13.498, -12.008], + [-8.656, -11.838], + [-1.526, -11.331], + [4.107, -7.603], + [7.381, 5.318], + [3.113, 7.1], + [2.239, 10.466], + [-4.232, 12.882], + [-9.661, 10.757], + [-13.75, 6.896], + [-16.709, 1.487], + [-14.057, -2.536] + ] + } + ], + "t": 50 + }, + { + "s": [ + { + "c": true, + "i": [ + [0, 0], + [2.157, 7.554], + [-8.293, -2.659], + [0, 0], + [-12.107, -3.575], + [0, 0], + [17.246, -7.392], + [0, 0], + [-1.486, -5.649], + [6.806, -1.078], + [0, 0], + [5.723, -1.328], + [1.988, 4.902], + [0, 0] + ], + "o": [ + [0, 0], + [-2.239, -7.48], + [8.292, 2.577], + [0, 0], + [12.105, 3.656], + [12.44, -13.296], + [-6.551, 2.901], + [0, 0], + [0.915, 3.656], + [-17.329, 2.744], + [0, 0], + [-3.979, 0.913], + [-4.893, -11.8], + [0, 0] + ], + "v": [ + [-14.046, -2.526], + [-30.796, -10.745], + [-20.846, -22.958], + [-8.656, -11.838], + [1.212, -26.459], + [4.107, -7.603], + [18.62, 7.767], + [3.113, 7.1], + [11.316, 17.238], + [4.268, 27.29], + [-9.661, 10.757], + [-19.945, 18.566], + [-30.973, 12.005], + [-14.057, -2.536] + ] + } + ], + "t": 90 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 1, 1], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [1, 10], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [148.251, 137.797], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 4 + }, + { + "ty": 4, + "nm": "Flower3-Body", + "cl": "flower3-body", + "sr": 1, + "st": 0, + "op": 100, + "ip": 50, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [202.237, 109.947, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [0, 0, 100], + "t": 50 + }, + { + "s": [200, 200, 100], + "t": 80 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [597.474, 270.893], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-0.735, 0.001], + [-0.082, -3.157], + [0.25, -0.691], + [0.507, -0.532], + [0.677, -0.282], + [0.733, 0.015], + [0.164, 3.157], + [-0.251, 0.693], + [-0.505, 0.536], + [-0.675, 0.292] + ], + "o": [ + [3.151, 0], + [0.048, 0.733], + [-0.25, 0.69], + [-0.506, 0.531], + [-0.678, 0.281], + [-3.067, 0], + [-0.043, -0.735], + [0.252, -0.693], + [0.504, -0.537], + [0.675, -0.293] + ], + "v": [ + [-0.293, -5.69], + [5.677, 0.039], + [5.371, 2.199], + [4.223, 4.052], + [2.428, 5.285], + [0.289, 5.689], + [-5.68, 0.039], + [-5.365, -2.126], + [-4.219, -3.989], + [-2.431, -5.245] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 0.9098, 0.0941], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [202.238, 110.026], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.675, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [0, 0], + [0.431, 2.339], + [-2.7, 0.476], + [0, 0], + [-5.96, -1.996], + [0, 0], + [3.247, -1.593], + [0, 0], + [0.827, -2.339], + [2.28, -0.072], + [0, 0], + [3.162, 0.45], + [-0.696, 3.068], + [0, 0] + ], + "o": [ + [0, 0], + [-0.298, -1.854], + [2.793, -0.493], + [0, 0], + [4.43, 1.285], + [5.362, 0.737], + [-2.221, 1.324], + [0, 0], + [-0.758, 2.144], + [-4.175, 0.131], + [0, 0], + [-2.489, -0.644], + [0.702, -3.095], + [0, 0] + ], + "v": [ + [-14.089, -2.524], + [-18.081, -7.199], + [-13.517, -12.57], + [-8.619, -11.84], + [-1.119, -13.072], + [4.147, -7.602], + [9.178, 5.482], + [3.068, 7.188], + [3.158, 12.135], + [-3.343, 15.444], + [-9.62, 10.761], + [-14.979, 10.366], + [-19.446, 2.973], + [-14.096, -2.536] + ] + } + ], + "t": 50 + }, + { + "s": [ + { + "c": true, + "i": [ + [0, 0], + [2.239, 7.474], + [-8.291, -2.574], + [0, 0], + [-12.107, -3.655], + [0, 0], + [17.164, -7.477], + [0, 0], + [-1.494, -5.649], + [6.717, -1.08], + [0, 0], + [5.638, -1.33], + [1.991, 4.82], + [0, 0] + ], + "o": [ + [0, 0], + [-2.154, -7.56], + [8.292, 2.659], + [0, 0], + [12.105, 3.573], + [12.437, -13.209], + [-6.551, 2.824], + [0, 0], + [0.912, 3.655], + [-17.333, 2.741], + [0, 0], + [-3.981, 0.998], + [-4.891, -11.797], + [0, 0] + ], + "v": [ + [-14.089, -2.524], + [-30.841, -10.662], + [-20.808, -22.96], + [-8.619, -11.84], + [1.251, -26.378], + [4.147, -7.602], + [18.657, 7.851], + [3.068, 7.188], + [11.361, 17.239], + [4.313, 27.292], + [-9.62, 10.761], + [-19.901, 18.568], + [-30.93, 12.088], + [-14.096, -2.536] + ] + } + ], + "t": 80 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 1, 1], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [207.329, 109.599], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 5 + }, + { + "ty": 4, + "nm": "Flower1-Body", + "cl": "flower1-body", + "sr": 1, + "st": -5, + "op": 101, + "ip": 55, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.836, 231.79, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [0, 0, 100], + "t": 55 + }, + { + "s": [200, 200, 100], + "t": 94 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [554.672, 514.579], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-0.736, 0.001], + [-0.084, -3.157], + [0.251, -0.69], + [0.506, -0.531], + [0.677, -0.282], + [0.733, 0.015], + [0.166, 3.157], + [-0.251, 0.693], + [-0.504, 0.536], + [-0.676, 0.293] + ], + "o": [ + [3.151, 0], + [0.048, 0.733], + [-0.251, 0.691], + [-0.507, 0.531], + [-0.677, 0.282], + [-3.069, 0], + [-0.043, -0.736], + [0.252, -0.693], + [0.505, -0.537], + [0.675, -0.293] + ], + "v": [ + [-0.292, -5.691], + [5.679, 0.043], + [5.372, 2.201], + [4.224, 4.054], + [2.428, 5.286], + [0.289, 5.69], + [-5.682, 0.043], + [-5.366, -2.123], + [-4.22, -3.987], + [-2.431, -5.245] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 0.9098, 0.0941], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [192.121, 219.357], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.512, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [0, 0], + [0.322, 2.238], + [-1.278, 0.318], + [0, 0], + [-3.695, -0.853], + [0, 0], + [2.873, -1.47], + [0, 0], + [0.169, -1.461], + [3.725, 0.535], + [0, 0], + [2.272, 0.706], + [-0.071, 2.127], + [0, 0] + ], + "o": [ + [0, 0], + [-0.437, -3.041], + [2.216, -0.646], + [0, 0], + [3.414, 1.074], + [5.096, 0.609], + [-2.187, 1.061], + [0, 0], + [-0.313, 2.395], + [-4.707, -0.676], + [0, 0], + [-2.307, -1.101], + [0.123, -3.696], + [0, 0] + ], + "v": [ + [-14.091, -2.576], + [-15.178, -6.621], + [-12.493, -12.171], + [-8.617, -11.881], + [-1.884, -11.964], + [4.145, -7.643], + [7.211, 5.882], + [3.068, 7.144], + [1.601, 11.174], + [-4.364, 13.997], + [-9.618, 10.718], + [-13.031, 8.525], + [-16.231, 3.49], + [-14.099, -2.576] + ] + } + ], + "t": 55 + }, + { + "s": [ + { + "c": true, + "i": [ + [0, 0], + [2.241, 7.477], + [-8.29, -2.575], + [0, 0], + [-12.104, -3.655], + [0, 0], + [17.167, -7.475], + [0, 0], + [-1.493, -5.652], + [6.717, -1.078], + [0, 0], + [5.636, -1.327], + [1.99, 4.821], + [0, 0] + ], + "o": [ + [0, 0], + [-2.157, -7.559], + [8.293, 2.659], + [0, 0], + [12.108, 3.573], + [12.44, -13.211], + [-6.55, 2.826], + [0, 0], + [0.912, 3.655], + [-17.328, 2.826], + [0, 0], + [-3.984, 0.999], + [-4.894, -11.794], + [0, 0] + ], + "v": [ + [-14.091, -2.576], + [-30.84, -10.718], + [-20.807, -23.015], + [-8.617, -11.881], + [1.249, -26.421], + [4.145, -7.643], + [18.657, 7.809], + [3.068, 7.144], + [11.361, 17.199], + [4.311, 27.251], + [-9.618, 10.718], + [-19.898, 18.525], + [-30.93, 12.045], + [-14.098, -2.576] + ] + } + ], + "t": 94 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [1, 1, 1], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [197.213, 218.988], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 6 + }, + { + "ty": 3, + "nm": "Null 21", + "cl": "null 21", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [0, 0, 100], + "t": 5 + }, + { + "s": [100, 100, 100], + "t": 50 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.012, + "y": 0.14 + }, + "i": { + "x": 0.196, + "y": 1 + }, + "s": [508.5], + "t": 5 + }, + { + "s": [477.5], + "t": 30 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.012, + "y": 0.16 + }, + "i": { + "x": 0.196, + "y": 1 + }, + "s": [762.5], + "t": 5 + }, + { + "s": [660], + "t": 30 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.02, + "y": -0.019 + }, + "i": { + "x": 0.342, + "y": 1 + }, + "s": [60], + "t": 5 + }, + { + "s": [0], + "t": 50 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 7 + }, + { + "ty": 4, + "nm": "Leaf2-Body-Lines", + "cl": "leaf leaf2-body-lines", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [76.172, -100.921, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0.994, -1.494], + [-24.381, -8.394], + [13.02, 0.58], + [-6.956, 3.488], + [-4.642, -2.739], + [14.587, 0.747], + [-1.425, -0.225], + [0, 0], + [-6.884, 3.491], + [-1.324, -0.996], + [-1.906, -1.412], + [13.928, 0.665], + [-6.635, 3.407], + [0, 0], + [13.847, 4.651] + ], + "o": [ + [-25.042, -8.558], + [-0.497, 0.829], + [-11.858, 5.56], + [19.57, 4.987], + [6.22, 2.405], + [-13.102, 6.894], + [1.391, 0.384], + [0, 0], + [20.482, 5.233], + [2.654, 1.745], + [2.157, 1.663], + [-12.604, 6.481], + [20.067, 5.152], + [9.453, 7.477], + [-2.57, -16.196], + [0, 0] + ], + "v": [ + [2.243, -14.831], + [-55.803, -25.88], + [-3.396, -11.091], + [-40.381, -3.948], + [2.566, -8.93], + [18.902, -0.872], + [-22.227, 8.016], + [-17.999, 8.93], + [-18.331, 8.93], + [26.034, 3.696], + [32.003, 8.016], + [38.141, 12.669], + [-1.33, 21.06], + [42.122, 15.826], + [56.299, 27.374], + [2.236, -14.831] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [79.716, 274.778], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 8, + "parent": 7 + }, + { + "ty": 4, + "nm": "Leaf2-Body-Reflection", + "cl": "leaf leaf2-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [76.172, -100.921, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [9.453, 8.649], + [-3.233, -0.334], + [-9.7, -11.797], + [0, 0] + ], + "o": [ + [-1.163, -0.834], + [-9.371, -8.64], + [3.151, 0.241], + [9.699, 11.797], + [0, 0] + ], + "v": [ + [10.7, 10.803], + [-20.892, -8.724], + [-31.426, -20.354], + [24.96, 2.826], + [34.497, 20.688] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [99.452, 267.257], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 9, + "parent": 7 + }, + { + "ty": 3, + "nm": "Null 27", + "cl": "null 27", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [0, 0, 100], + "t": 5 + }, + { + "s": [100, 100, 100], + "t": 30 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [538.5, 865], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 10 + }, + { + "ty": 4, + "nm": "Bottom-Stem-Reflection", + "cl": "bottom-stem-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [15.172, -305.921, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0.071, -0.263], + [0.172, -0.211], + [0.243, -0.124], + [0.272, -0.014], + [0.456, 0.38], + [0.103, 0.586], + [2.984, 11.963], + [0, 0.094], + [-0.032, 0.274], + [-0.141, 0.236], + [-0.226, 0.157], + [-0.27, 0.05], + [-0.488, -0.337], + [-0.146, -0.575], + [-3.151, -12.711], + [0, -0.083] + ], + "o": [ + [0.041, 0.269], + [-0.072, 0.263], + [-0.172, 0.212], + [-0.243, 0.123], + [-0.594, 0.005], + [-0.456, -0.381], + [0, -0.082], + [-2.821, -11.546], + [-0.084, -0.262], + [0.031, -0.273], + [0.141, -0.236], + [0.226, -0.156], + [0.589, -0.068], + [0.488, 0.336], + [0, 0], + [2.987, 12.215], + [0, 0] + ], + "v": [ + [7.457, 26.202], + [7.411, 27.01], + [7.043, 27.73], + [6.413, 28.239], + [5.633, 28.447], + [4.008, 27.865], + [3.143, 26.368], + [-2.576, -6.699], + [-7.386, -25.891], + [-7.465, -26.704], + [-7.203, -27.476], + [-6.646, -28.072], + [-5.893, -28.384], + [-4.223, -27.967], + [-3.24, -26.554], + [1.654, -7.364], + [7.459, 26.202] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [164.721, 371.494], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 11, + "parent": 10 + }, + { + "ty": 4, + "nm": "Leaf2-Body-Background", + "cl": "leaf leaf2-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [76.172, -100.921, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0.525, 3.82], + [4.003, 10.672], + [12.853, 2.577], + [17.664, 0.996], + [-33.75, -20.27], + [-20.064, 0.334], + [-7.023, -4.153] + ], + "o": [ + [0.709, -5.939], + [-8.374, -22.183], + [-2.57, -0.498], + [10.035, 14.207], + [14.259, 8.553], + [13.233, -0.244], + [3.965, -1.453] + ], + "v": [ + [50.99, -21.419], + [47.348, -46.524], + [-6.303, -85.736], + [-90.8, -94.543], + [-41.874, -22.678], + [15.836, -14.46], + [47.799, -11.896] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [93.236, 321.099], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 12, + "parent": 7 + }, + { + "ty": 4, + "nm": "Bottom-Stem", + "cl": "bottom-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.024, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [0.294, 2.574], + [1.025, 1.32], + [-0.535, -1.703], + [-0.13, -2.595], + [0, 0] + ], + "o": [ + [-1.081, -1.051], + [-1.975, -1.93], + [1.465, 2.297], + [0, 0], + [0.373, 2.155] + ], + "v": [ + [83.721, 85.577], + [79.99, 82.331], + [74.549, 80.354], + [75.395, 85.746], + [75.391, 85.746] + ] + } + ], + "t": 0 + }, + { + "s": [ + { + "c": true, + "i": [ + [0.83, 11.302], + [17.357, 18.257], + [-7.023, -4.153], + [-1.469, -25.168], + [0, 0] + ], + "o": [ + [-2.025, -28.331], + [-2.725, -3.93], + [12.59, 19.28], + [0, 0], + [0.669, 11.797] + ], + "v": [ + [89.971, 83.077], + [50.99, -21.419], + [47.799, -11.896], + [71.395, 82.746], + [71.391, 82.746] + ] + } + ], + "t": 30 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [93.236, 321.099], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 13 + }, + { + "ty": 3, + "nm": "Null 22", + "cl": "null 22", + "sr": 1, + "st": 0, + "op": 100, + "ip": 15, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.336, + "y": 1 + }, + "s": [0, 0, 100], + "t": 15 + }, + { + "s": [100, 100, 100], + "t": 65 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.133 + }, + "i": { + "x": 0.503, + "y": 1 + }, + "s": [516.5], + "t": 15 + }, + { + "s": [551], + "t": 45 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.153 + }, + "i": { + "x": 0.503, + "y": 1 + }, + "s": [770.25], + "t": 15 + }, + { + "s": [655.5], + "t": 45 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.336, + "y": 1 + }, + "s": [-60], + "t": 15 + }, + { + "s": [0], + "t": 60 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 14 + }, + { + "ty": 4, + "nm": "Leaf1-Body-Reflection", + "cl": "leaf leaf1-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 15, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [2.672, -96.421, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-3.158, -12.297] + ], + "o": [ + [11.859, -23.266], + [1.325, 5.149] + ], + "v": [ + [-27.696, 13.876], + [26.371, -1.579] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [257.171, 230.288], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 15, + "parent": 14 + }, + { + "ty": 4, + "nm": "Leaf1-Body-Lines", + "cl": "leaf leaf1-body-lines", + "sr": 1, + "st": 0, + "op": 100, + "ip": 15, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [2.672, -96.421, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-18.574, 0.914], + [7.047, 3.658] + ], + "o": [ + [17.167, 9.137], + [-27.445, 7.146], + [0, 0] + ], + "v": [ + [-24.337, -9.513], + [28.897, 2.367], + [-28.898, -5.196] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [281.427, 258.328], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-17.415, 5.983], + [-1.243, -1.912], + [31.426, -11.545], + [5.475, -4.318], + [0, 0] + ], + "o": [ + [31.508, -10.878], + [0.832, 1.163], + [-19.821, 7.313], + [-19.985, 15.785], + [2.239, -20.689] + ], + "v": [ + [-3.937, -18.944], + [69.529, -33.067], + [-0.786, -12.63], + [-40.507, 10.302], + [-70.36, 34.979] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [259.029, 265.762], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 3, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-19.073, 0.998], + [1.742, -0.331], + [0, 0], + [7.214, 3.822], + [0, 0], + [-0.838, -0.416] + ], + "o": [ + [17.661, 9.304], + [-1.824, 0.5], + [0, 0], + [-28.027, 7.313], + [0, 0], + [0.745, 0.416], + [0, 0] + ], + "v": [ + [-22.512, -10.302], + [32.05, 1.826], + [26.742, 2.988], + [27.075, 2.988], + [-32.05, -4.82], + [-27.405, -9.142], + [-24.992, -7.892] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [255.804, 274.25], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 4", + "cl": "group 4", + "ix": 4, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-18.663, 0.916], + [7.048, 3.737] + ], + "o": [ + [17.244, 9.138], + [-27.448, 7.064], + [0, 0] + ], + "v": [ + [-24.382, -9.514], + [28.94, 2.45], + [-28.94, -5.191] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [233.047, 290.313], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 16, + "parent": 14 + }, + { + "ty": 4, + "nm": "Leaf1-Body-Background", + "cl": "leaf leaf1-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 15, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [2.672, -96.421, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [34.328, 2.901], + [13.029, -39.213], + [3.648, -9.389], + [0, 0], + [-2.461, -0.017], + [-18.979, -2.333], + [-29.353, 18.942], + [-14.261, 15.368], + [0.164, 0.665] + ], + "o": [ + [-45.36, -3.899], + [-3.815, 11.799], + [0, 0], + [-2.118, 6.125], + [5.578, 2.426], + [9.535, 1.075], + [20.233, -13.042], + [10.45, -11.216], + [-1.576, -6.229] + ], + "v": [ + [29.356, -65.855], + [-75.956, -16.087], + [-79.274, 18.142], + [-79.386, 18.928], + [-77.043, 29.071], + [-40.3, 38.249], + [24.793, 23.128], + [68.326, -21.07], + [97.931, -44.004] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [257.504, 277.447], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 17, + "parent": 14 + }, + { + "ty": 4, + "nm": "Leaf1-Stem", + "cl": "leaf1-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 15, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [1.02, -0.339], + [0, 0], + [0.121, -2.285], + [-1.409, -2.187], + [0, 0], + [-0.113, 1.183], + [-0.086, 1.733] + ], + "o": [ + [0, 0], + [-0.493, 1.5], + [-0.129, 3.215], + [0, 0], + [-0.099, -3.201], + [0.238, -2.484], + [0.414, -2.267] + ], + "v": [ + [-92.149, 66.892], + [-93.386, 68.803], + [-95.125, 74.839], + [-93.845, 81.241], + [-91.155, 86.504], + [-90.891, 80.621], + [-90.293, 75.196] + ] + } + ], + "t": 15 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [4.52, -4.339], + [0, 0], + [2.936, -7.072], + [0, -10.221], + [0, 0], + [-3.732, 9.055], + [-3.016, 3.271] + ], + "o": [ + [0, 0], + [-1.493, 1.625], + [-4.147, 10.216], + [0, 0], + [0, -9.317], + [1.826, -4.383], + [4.789, -3.517] + ], + "v": [ + [-80.024, 27.267], + [-82.511, 28.428], + [-91.75, 41.714], + [-98.095, 68.991], + [-90.03, 75.629], + [-84.391, 43.996], + [-76.793, 30.446] + ] + } + ], + "t": 35 + }, + { + "s": [ + { + "c": true, + "i": [ + [4.52, -4.339], + [0, 0], + [2.936, -7.072], + [0, -10.221], + [0, 0], + [-3.732, 9.055], + [-3.016, 3.271] + ], + "o": [ + [0, 0], + [-5.818, 4.542], + [-4.147, 10.216], + [0, 0], + [0, -9.317], + [1.826, -4.383], + [4.789, -3.517] + ], + "v": [ + [-74.774, 17.642], + [-74.886, 18.428], + [-91.125, 39.089], + [-98.095, 68.991], + [-89.405, 69.754], + [-83.016, 42.996], + [-72.543, 28.571] + ] + } + ], + "t": 45 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [257.504, 277.447], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 18 + }, + { + "ty": 3, + "nm": "Null 23", + "cl": "null 23", + "sr": 1, + "st": 0, + "op": 100, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.255, + "y": 1 + }, + "s": [0, 0, 100], + "t": 30 + }, + { + "s": [100, 100, 100], + "t": 70 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.167 + }, + "i": { + "x": 0.336, + "y": 1 + }, + "s": [521.5], + "t": 30 + }, + { + "s": [526.5], + "t": 60 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.167 + }, + "i": { + "x": 0.336, + "y": 1 + }, + "s": [376.5], + "t": 30 + }, + { + "s": [251.5], + "t": 60 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [25], + "t": 30 + }, + { + "s": [0], + "t": 70 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 19 + }, + { + "ty": 4, + "nm": "Leaf6-Body-Shadow", + "cl": "leaf leaf6-body-shadow", + "sr": 1, + "st": 0, + "op": 100, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [27.172, 307.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-9.371, 1.745], + [4.642, 13.129], + [-4.399, -16.869], + [-7.132, -7.893] + ], + "o": [ + [0, 0], + [-4.56, -13.127], + [2.072, 8.142], + [5.79, 6.314] + ], + "v": [ + [25.417, 34.645], + [-12.314, -23.264], + [-21.019, -9.637], + [-9.411, 15.87] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5098, 0.7059, 0.1843], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [134.489, 59.719], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 20, + "parent": 19 + }, + { + "ty": 4, + "nm": "Leaf6-Body-Reflection", + "cl": "leaf leaf6-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [27.172, 307.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-0.166, 5.069], + [-7.381, -17.115] + ], + "o": [ + [0, 0], + [0.242, -5.077], + [7.38, 17.031] + ], + "v": [ + [9.952, 26.258], + [-16.169, -21.181], + [8.956, 3.991] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [144.316, 49.082], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 21, + "parent": 19 + }, + { + "ty": 4, + "nm": "Leaf6-Body-Background", + "cl": "leaf leaf6-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [27.172, 307.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-0.064, 2.388], + [13.27, 20.616], + [3.568, -1.91], + [-5.066, -19.025], + [-6.799, -2.826], + [-6.527, -1.664] + ], + "o": [ + [0.987, -9.123], + [-16.416, -25.504], + [-3.564, 1.994], + [5.142, 19.11], + [4.956, 2.12], + [2.143, 0.995] + ], + "v": [ + [27.526, -72.563], + [16.548, -128.072], + [-25.413, -158.894], + [-31.549, -113.781], + [-1.117, -77.307], + [23.069, -70.17] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [140.538, 170.676], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 22, + "parent": 19 + }, + { + "ty": 4, + "nm": "Main-Stem", + "cl": "main-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [0.095, 2.833], + [0.686, 2.263], + [0.268, -1.005], + [0.385, -1.967], + [-0.367, -2.204], + [-0.518, -1.98], + [0, 0], + [0.264, 2.803] + ], + "o": [ + [-0.068, -2.046], + [-0.439, -1.237], + [0.268, 1.495], + [-0.24, 1.658], + [0.423, 2.539], + [0, 0], + [-0.376, -1.651], + [-0.361, -1.322] + ], + "v": [ + [18.406, 170.495], + [17.526, 164.062], + [14.819, 160.455], + [14.077, 164.167], + [14.329, 168.653], + [14.855, 171.804], + [23.839, 187.976], + [19.449, 176.021] + ] + } + ], + "t": 10 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.011, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [-0.068, 10.704], + [5.578, 13.054], + [-0.607, -8.505], + [-0.048, -15.614], + [-1.617, -16.704], + [-2.985, -16.45], + [0, 0], + [0.579, 13.458] + ], + "o": [ + [0.113, -17.636], + [-2.564, -5.362], + [3.341, 12.493], + [-0.365, 12.033], + [1.402, 14.485], + [0, 0], + [-2.818, -15.454], + [-0.736, -13.697] + ], + "v": [ + [31.531, 41.12], + [26.151, -12.938], + [20.069, -10.671], + [21.327, 45.292], + [8.579, 121.528], + [13.23, 160.804], + [25.339, 172.601], + [18.199, 122.521] + ] + } + ], + "t": 30 + }, + { + "s": [ + { + "c": true, + "i": [ + [0.084, 52.508], + [5.578, 13.054], + [-0.357, -1.755], + [-0.048, -15.614], + [-2.155, -46.525], + [-2.985, -16.45], + [0, 0], + [0.579, 13.458] + ], + "o": [ + [-0.049, -17.636], + [-0.439, -1.237], + [3.341, 12.493], + [0.082, 53.17], + [0.663, 14.538], + [0, 0], + [-2.818, -15.454], + [-2.229, -47.934] + ], + "v": [ + [36.531, -26.38], + [27.526, -72.563], + [23.069, -70.17], + [27.827, -27.208], + [10.079, 114.528], + [13.23, 160.804], + [25.089, 158.726], + [19.699, 115.521] + ] + } + ], + "t": 60 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [140.538, 170.676], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 23 + }, + { + "ty": 3, + "nm": "Null 24", + "cl": "null 24", + "sr": 1, + "st": 0, + "op": 100, + "ip": 20, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.372, + "y": 1 + }, + "s": [0, 0, 100], + "t": 20 + }, + { + "s": [100, 100, 100], + "t": 60 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.015, + "y": 0 + }, + "i": { + "x": 0.489, + "y": 1 + }, + "s": [511.5], + "t": 20 + }, + { + "s": [496.5], + "t": 40 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.015, + "y": 0 + }, + "i": { + "x": 0.489, + "y": 1 + }, + "s": [588.5], + "t": 20 + }, + { + "s": [470], + "t": 40 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.116, + "y": 1 + }, + "s": [89], + "t": 20 + }, + { + "s": [0], + "t": 60 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 24 + }, + { + "ty": 4, + "nm": "Leaf4-Body-Lines", + "cl": "leaf leaf4-body-lines", + "sr": 1, + "st": 0, + "op": 100, + "ip": 20, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [57.172, 89.079, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [13.844, 4.738], + [0.994, -1.496], + [-24.379, -8.311], + [13.015, 0.665], + [-6.961, 3.406], + [-5.219, -3.101], + [14.508, 0.747], + [-1.327, -0.249], + [0, 0], + [-6.881, 3.489], + [-1.327, -1.083], + [-1.824, -1.494], + [13.932, 0.747], + [-6.637, 3.406], + [0, 0] + ], + "o": [ + [-25.044, -8.461], + [-0.497, 0.829], + [-11.777, 5.56], + [19.568, 5.077], + [5.653, 2.208], + [-13.102, 6.895], + [1.406, 0.331], + [0, 0], + [20.399, 5.236], + [2.572, 1.746], + [2.157, 1.658], + [-12.522, 6.481], + [20.067, 5.152], + [9.453, 7.398], + [-2.572, -16.196] + ], + "v": [ + [2.242, -14.873], + [-55.806, -25.838], + [-3.482, -11.131], + [-40.382, -3.988], + [2.565, -8.89], + [18.9, -0.912], + [-22.229, 8.062], + [-18.083, 8.972], + [-18.324, 8.972], + [26.036, 3.739], + [32.008, 8.062], + [38.061, 12.709], + [-1.327, 21.02], + [42.127, 15.867], + [56.303, 27.334] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [82.539, 174.539], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 25, + "parent": 24 + }, + { + "ty": 4, + "nm": "Leaf4-Body-Reflection", + "cl": "leaf leaf4-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 20, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [57.172, 89.079, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [9.454, 8.722], + [-3.233, -0.331], + [-9.784, -11.794], + [0, 0] + ], + "o": [ + [-1.081, -0.829], + [-9.371, -8.642], + [3.151, 0.242], + [9.702, 11.882], + [0, 0] + ], + "v": [ + [10.615, 10.8], + [-20.896, -8.723], + [-31.428, -20.356], + [24.958, 2.822], + [34.493, 20.687] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [111.479, 169.305], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 26, + "parent": 24 + }, + { + "ty": 4, + "nm": "Leaf4-Body-Background", + "cl": "leaf leaf4-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 20, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [57.172, 89.079, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-1.146, 3.138], + [6.459, 17.04], + [12.853, 2.492], + [17.664, 1.001], + [-33.75, -20.19], + [-20.067, 0.331], + [-6.858, -1.341] + ], + "o": [ + [1.671, -4.398], + [-8.287, -22.1], + [-2.572, -0.498], + [10.032, 14.209], + [14.261, 8.551], + [9.841, -0.185], + [2.991, 3.493] + ], + "v": [ + [66.262, 22.607], + [64.381, -10.379], + [10.818, -49.513], + [-73.68, -58.404], + [-24.755, 13.466], + [32.958, 21.685], + [58.652, 22.053] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [88.135, 187.006], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 27, + "parent": 24 + }, + { + "ty": 4, + "nm": "Leaf4-Stem", + "cl": "leaf4-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 20, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [0.467, 3.083], + [0.604, 2.013], + [0.089, -1.434], + [-0.188, -2.007], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [-0.361, -2.385], + [-0.646, -5.112], + [-0.161, 2.316], + [0.312, 3.618], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [75.477, 79.38], + [74.887, 74.232], + [72.027, 75.178], + [72.179, 82.002], + [71.89, 89.866], + [74.076, 86.279], + [74.317, 85.529], + [75.562, 85.944] + ] + } + ], + "t": 20 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [1.022, 8.645], + [-0.209, 2.575], + [0.776, -2.247], + [-0.534, -4.943], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [-0.546, -4.517], + [-0.646, -5.112], + [-0.349, 3.503], + [0.862, 8.456], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [68.789, 52.88], + [67.574, 35.419], + [63.839, 35.366], + [64.741, 53.939], + [69.015, 73.429], + [72.138, 72.341], + [72.379, 71.591], + [73.624, 72.007] + ] + } + ], + "t": 30 + }, + { + "s": [ + { + "c": true, + "i": [ + [1.578, 14.207], + [2.607, 3.879], + [-0.786, -2.309], + [-0.879, -7.878], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [-0.731, -6.649], + [-0.646, -5.112], + [2.991, 3.493], + [1.412, 13.294], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [72.102, 38.379], + [63.762, 18.107], + [56.152, 17.553], + [66.304, 39.126], + [66.14, 56.991], + [70.201, 58.404], + [70.442, 57.654], + [71.687, 58.069] + ] + } + ], + "t": 40 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [88.135, 187.006], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 28 + }, + { + "ty": 3, + "nm": "Null 25", + "cl": "null 25", + "sr": 1, + "st": 0, + "op": 100, + "ip": 25, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.329, + "y": 1 + }, + "s": [0, 0, 100], + "t": 25 + }, + { + "s": [100, 100, 100], + "t": 70 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.167 + }, + "i": { + "x": 0.328, + "y": 1 + }, + "s": [521], + "t": 25 + }, + { + "s": [556], + "t": 55 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.167 + }, + "i": { + "x": 0.328, + "y": 1 + }, + "s": [537.5], + "t": 25 + }, + { + "s": [437.5], + "t": 55 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [-25], + "t": 25 + }, + { + "s": [0], + "t": 70 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 29 + }, + { + "ty": 4, + "nm": "Leaf3-Body-Reflection", + "cl": "leaf leaf3-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 25, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-2.328, 121.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-3.154, -12.297] + ], + "o": [ + [11.854, -23.263], + [1.431, 5.162] + ], + "v": [ + [-27.747, 13.875], + [26.316, -1.578] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [245.44, 137.318], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 30, + "parent": 29 + }, + { + "ty": 4, + "nm": "Leaf3-Body-Lines", + "cl": "leaf leaf3-body-lines", + "sr": 1, + "st": 0, + "op": 100, + "ip": 25, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-2.328, 121.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-14.183, 0.662], + [5.474, 2.908] + ], + "o": [ + [13.186, 6.982], + [-20.991, 5.4], + [0, 0] + ], + "v": [ + [-18.658, -7.271], + [22.142, 1.871], + [-22.142, -4.029] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [223.506, 182.306], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-14.259, 0.667], + [5.39, 2.908] + ], + "o": [ + [13.188, 6.979], + [-20.979, 5.4], + [0, 0] + ], + "v": [ + [-18.658, -7.269], + [22.141, 1.869], + [-22.14, -4.03] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [260.572, 157.797], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 3, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-0.995, -1.411], + [24.046, -8.898], + [4.227, -3.321], + [0, 0], + [-13.35, 4.651] + ], + "o": [ + [24.127, -8.308], + [0.579, 0.917], + [-15.174, 5.561], + [-15.34, 12.131], + [1.66, -15.868], + [0, 0] + ], + "v": [ + [-3.025, -14.586], + [53.278, -25.387], + [-0.62, -9.674], + [-31.053, 7.855], + [-53.857, 26.798], + [-3.025, -14.576] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [243.448, 163.535], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 4", + "cl": "group 4", + "ix": 4, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-14.595, 0.747], + [1.324, -0.249], + [0, 0], + [5.55, 2.903], + [0, 0], + [-0.582, -0.334] + ], + "o": [ + [13.512, 7.143], + [-1.325, 0.334], + [0, 0], + [-21.473, 5.56], + [0, 0], + [0.662, 0.333], + [0, 0] + ], + "v": [ + [-17.161, -7.889], + [24.549, 1.415], + [20.57, 2.329], + [20.811, 2.329], + [-24.549, -3.649], + [-20.983, -6.975], + [-19.156, -6.059] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.4118, 0.5961, 0.0549], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [240.915, 169.965], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 31, + "parent": 29 + }, + { + "ty": 4, + "nm": "Leaf3-Body-Background", + "cl": "leaf leaf3-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 25, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-2.328, 121.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-2.985, 8.971], + [-34.744, -2.993], + [-1.161, -4.821], + [8.042, -8.638], + [15.507, -10.051], + [7.296, 0.829], + [5.141, 1.83], + [-0.226, 4.086] + ], + "o": [ + [2.821, -7.146], + [9.952, -30.075], + [26.299, 2.243], + [0.164, 0.413], + [-10.947, 11.717], + [-22.47, 14.541], + [-11.031, -1.332], + [-3.777, -0.234], + [0, 0] + ], + "v": [ + [-55.891, 9.306], + [-53.322, -16.865], + [27.278, -54.999], + [79.77, -38.215], + [57.131, -20.689], + [23.796, 13.125], + [-26.038, 24.676], + [-50.253, 19.191], + [-56.303, 12.371] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [235.78, 177.043], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 32, + "parent": 29 + }, + { + "ty": 4, + "nm": "Leaf3-Stem", + "cl": "leaf3-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 25, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.027, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [0.348, -1.484], + [0.331, -3.035], + [0.283, -1.785], + [0, 0], + [-0.203, 1.665], + [-0.811, 2.394] + ], + "o": [ + [-0.902, 3.141], + [-0.174, 1.601], + [0, 0], + [-0.22, -1.993], + [0.297, -2.21], + [0.649, -1.914] + ], + "v": [ + [-70.753, 69.816], + [-72.486, 77.242], + [-72.562, 83.492], + [-74.434, 82.075], + [-74.202, 76.167], + [-72.803, 69.746] + ] + } + ], + "t": 25 + }, + { + "s": [ + { + "c": true, + "i": [ + [3.473, -1.984], + [2.982, -4.571], + [1.745, -9.14], + [0, 0], + [-6.059, 9.135], + [-5.524, 2.164] + ], + "o": [ + [-4.227, 2.743], + [-5.392, 8.219], + [0, 0], + [1.824, -9.969], + [3.315, -5.077], + [5.524, -2.164] + ], + "v": [ + [-50.253, 19.191], + [-61.111, 30.492], + [-71.562, 57.992], + [-79.934, 55.575], + [-68.327, 25.167], + [-56.303, 12.371] + ] + } + ], + "t": 55 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [235.78, 177.043], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 33 + }, + { + "ty": 3, + "nm": "Null 26", + "cl": "null 26", + "sr": 1, + "st": 0, + "op": 100, + "ip": 30, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [0, 0, 0], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.099, + "y": 1 + }, + "s": [0, 0, 100], + "t": 35 + }, + { + "s": [100, 100, 100], + "t": 80 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.162 + }, + "i": { + "x": 0.499, + "y": 1 + }, + "s": [525.25], + "t": 30 + }, + { + "s": [574], + "t": 60 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.01, + "y": 0.184 + }, + "i": { + "x": 0.499, + "y": 1 + }, + "s": [374.25], + "t": 30 + }, + { + "s": [263.5], + "t": 60 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [-89], + "t": 30 + }, + { + "s": [0], + "t": 80 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ind": 34 + }, + { + "ty": 4, + "nm": "Leaf5-Body-Reflection", + "cl": "leaf leaf5-body-reflection", + "sr": 1, + "st": 0, + "op": 100, + "ip": 30, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-20.328, 295.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-23.963, 10.136], + [3.233, -4.405], + [12.437, -24.005] + ], + "o": [ + [0, 0], + [23.886, -10.139], + [-3.233, 4.404], + [0, 0] + ], + "v": [ + [-29.933, 27.002], + [-1.826, -16.864], + [26.701, -18.688], + [-29.933, 27.001] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.7255, 0.8471, 0.2078], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [226.492, 38.532], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 35, + "parent": 34 + }, + { + "ty": 4, + "nm": "Leaf5-Body-Lines", + "cl": "leaf leaf5-body-lines", + "sr": 1, + "st": 0, + "op": 100, + "ip": 30, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-20.328, 295.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-13.101, 4.735], + [5.79, 1.247] + ], + "o": [ + [14.262, 3.155], + [-18.076, 11.296], + [0, 0] + ], + "v": [ + [-19.157, -3.156], + [21.473, -5.648], + [-21.473, 1.082] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5098, 0.7059, 0.1843], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [249.795, 45.512], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 2", + "cl": "group 2", + "ix": 2, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.113, 8.224], + [-1.332, -1.163], + [19.988, -15.537], + [2.985, -4.402], + [0, 0] + ], + "o": [ + [20.234, -15.039], + [0.83, 0.749], + [-12.522, 9.72], + [-10.857, 16.196], + [-2.896, -16.117] + ], + "v": [ + [-5.851, -13.667], + [43.736, -40.171], + [-2.203, -9.598], + [-25.667, 16.244], + [-41.67, 41.334] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5098, 0.7059, 0.1843], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [234.58, 54.943], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 3", + "cl": "group 3", + "ix": 3, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-13.352, 4.821], + [1.197, -0.6], + [0, 0], + [5.971, 1.329], + [0, 0], + [-0.654, -0.177] + ], + "o": [ + [14.679, 3.322], + [-1.124, 0.729], + [0, 0], + [-18.491, 11.548], + [0, 0], + [0.671, 0.096], + [0, 0] + ], + "v": [ + [-17.991, -4.235], + [23.638, -6.73], + [20.154, -4.735], + [20.395, -4.818], + [-23.637, 1.995], + [-21.224, -2.241], + [-19.234, -1.83] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5098, 0.7059, 0.1843], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [234.863, 63.042], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 4", + "cl": "group 4", + "ix": 4, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-13.102, 4.733], + [5.79, 1.332] + ], + "o": [ + [14.262, 3.16], + [-18.077, 11.299], + [0, 0] + ], + "v": [ + [-19.157, -3.16], + [21.474, -5.65], + [-21.473, 0.996] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.5098, 0.7059, 0.1843], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [222.1, 80.075], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 36, + "parent": 34 + }, + { + "ty": 4, + "nm": "Leaf5-Body-Background", + "cl": "leaf leaf5-body-background", + "sr": 1, + "st": 0, + "op": 100, + "ip": 30, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [-20.328, 295.579, 0], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [25.124, -5.149], + [0.828, -32.393], + [0, 0], + [-1.951, -9.633], + [-5.22, -0.502], + [-10.65, 1.762], + [-16.914, 20.604], + [-6.881, 14.62], + [0.242, 0.413] + ], + "o": [ + [-33.337, 6.812], + [0, 0], + [-0.138, 5.504], + [0, 0], + [5.22, 0.502], + [7.048, -1.168], + [11.692, -14.289], + [5.055, -10.816], + [-2.403, -4.407] + ], + "v": [ + [11.531, -70.66], + [-53.066, -10.423], + [-53.061, -10.41], + [-47.927, 17.827], + [-39.845, 24.297], + [-15.83, 22.906], + [27.455, -2.436], + [49.097, -45.138], + [65.262, -68.829] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [232.375, 78.452], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 37, + "parent": 34 + }, + { + "ty": 4, + "nm": "Leaf5-Stem", + "cl": "leaf5-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 30, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [3.552, -3.528], + [0, 0], + [0.837, -2.733], + [0.233, -1.814], + [0, 0], + [0, 0], + [-0.526, 1.285], + [-0.338, 2.163], + [-0.258, 1.685] + ], + "o": [ + [0, 0], + [-0.41, 1.47], + [-0.562, 1.836], + [-0.142, 1.936], + [0, 0], + [0, 0], + [0.099, -1.09], + [0.301, -1.925], + [0, 0] + ], + "v": [ + [-65.427, 89.077], + [-66.465, 92.953], + [-67.188, 97.212], + [-68.108, 102.363], + [-68.19, 106.059], + [-64.593, 105.029], + [-64.974, 101.764], + [-64.426, 97.223], + [-63.492, 91.988] + ] + } + ], + "t": 30 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [3.552, -3.528], + [0, 0], + [2.563, -3.664], + [0.483, -5.064], + [0, 0], + [0, 0], + [-1.026, 5.91], + [-2.14, 4.55], + [-1.758, 4.935] + ], + "o": [ + [0, 0], + [-1.535, 3.47], + [-3.258, 4.658], + [-0.892, 5.311], + [0, 0], + [0, 0], + [0.974, -4.09], + [3.551, -7.55], + [0, 0] + ], + "v": [ + [-48.927, 28.327], + [-49.715, 29.453], + [-55.063, 42.963], + [-60.608, 57.362], + [-61.19, 75.809], + [-57.093, 76.404], + [-55.224, 61.138], + [-52.176, 49.598], + [-45.367, 33.488] + ] + } + ], + "t": 45 + }, + { + "s": [ + { + "c": true, + "i": [ + [3.552, -3.528], + [0, 0], + [3.371, -4.946], + [2.309, -5.064], + [0, 0], + [0, 0], + [-3.069, 6.981], + [-3.057, 3.992], + [1.008, 8.065] + ], + "o": [ + [0, 0], + [0.636, 5.951], + [-3.202, 4.697], + [-4.896, 10.967], + [0, 0], + [0, 0], + [1.619, -3.561], + [5.212, -6.805], + [-1.008, -8.065] + ], + "v": [ + [-47.927, 13.827], + [-46.965, 26.828], + [-51.188, 43.713], + [-60.608, 59.612], + [-61.19, 75.809], + [-55.718, 71.404], + [-54.224, 62.513], + [-46.426, 50.473], + [-39.617, 26.613] + ] + } + ], + "t": 60 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [232.375, 78.452], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 38 + }, + { + "ty": 4, + "nm": "Flower2-Stem", + "cl": "flower2-stem", + "sr": 1, + "st": 0, + "op": 100, + "ip": 50, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [0, 0], + [-0.133, -1.75], + [0, 0], + [0, 0], + [-0.41, 3.348], + [0, 0.083] + ], + "o": [ + [0, 0.082], + [0.313, 4.109], + [0, 0], + [0, 0], + [0.254, -2.071], + [0, 0] + ], + "v": [ + [6.052, 9.977], + [9.622, 14.077], + [9.951, 19.648], + [6.101, 24.744], + [6.11, 18.773], + [6.362, 14.251] + ] + } + ], + "t": 50 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [-4.187, -3.599], + [-4.309, -9.639], + [0, 0], + [0, 0], + [3.151, 7.061], + [4.248, 4.05] + ], + "o": [ + [4.187, 3.599], + [4.891, 10.965], + [0, 0], + [0, 0], + [-3.73, -8.309], + [-4.248, -4.05] + ], + "v": [ + [-6.698, -12.148], + [7.497, 4.202], + [9.951, 19.648], + [4.476, 15.244], + [2.985, 6.273], + [-9.638, -9.373] + ] + } + ], + "t": 60 + }, + { + "s": [ + { + "c": true, + "i": [ + [-4.187, -3.599], + [-4.309, -9.639], + [0, 0], + [0, 0], + [3.151, 7.061], + [4.248, 4.05] + ], + "o": [ + [4.187, 3.599], + [4.891, 10.965], + [0, 0], + [0, 0], + [-3.73, -8.309], + [-4.248, -4.05] + ], + "v": [ + [-9.448, -19.648], + [9.372, 3.452], + [9.951, 19.648], + [4.476, 15.244], + [2.985, 6.273], + [-14.263, -14.498] + ] + } + ], + "t": 70 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [162.636, 157.049], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 39 + }, + { + "ty": 4, + "nm": "Flower1-Stem", + "cl": "flower1-stem", + "sr": 1, + "st": 10, + "op": 110, + "ip": 50, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [180.336, 254.04, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [200, 200, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [553.672, 559.079], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + { + "c": true, + "i": [ + [0, 0], + [0.226, -2.073], + [0, 0], + [0, 0], + [-1.581, 1.785], + [-0.082, 0] + ], + "o": [ + [-0.082, 0], + [-0.224, 2.06], + [0, 0], + [0, 0], + [1.544, -1.84], + [0, 0] + ], + "v": [ + [-8.492, 13.024], + [-8.939, 17.438], + [-9.215, 21.415], + [-12.604, 14.867], + [-10.582, 9.713], + [-7.811, 6.758] + ] + } + ], + "t": 50 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + { + "c": true, + "i": [ + [2.954, -1.651], + [4.89, -6.396], + [0, 0], + [0, 0], + [-6.551, 8.379], + [-4.795, 2.085] + ], + "o": [ + [-5.599, 3.13], + [-4.148, 5.403], + [0, 0], + [0, 0], + [5.638, -7.479], + [2.898, -1.26] + ], + "v": [ + [7.383, -8.476], + [-5.064, 3.938], + [-8.465, 14.04], + [-12.604, 14.867], + [-8.707, 1.088], + [7.189, -11.367] + ] + } + ], + "t": 60 + }, + { + "s": [ + { + "c": true, + "i": [ + [5.546, -3.224], + [4.89, -6.396], + [0, 0], + [0, 0], + [-6.551, 8.379], + [-4.773, 2.135] + ], + "o": [ + [-5.546, 3.224], + [-4.148, 5.403], + [0, 0], + [0, 0], + [5.638, -7.479], + [4.773, -2.135] + ], + "v": [ + [15.258, -9.476], + [-3.814, 4.813], + [-6.965, 12.29], + [-12.604, 14.867], + [-8.707, 1.088], + [12.189, -14.867] + ] + } + ], + "t": 70 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.6118, 0.7882, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [166.538, 243.252], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 40 + }, + { + "ty": 4, + "nm": "Dust-Body-Bit3", + "cl": "dirt-body-bit3", + "sr": 1, + "st": 3, + "op": 103, + "ip": 3, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [-5.551, 316.252, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [30, 30, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [529.385], + "t": 3 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [518.879], + "t": 6 + }, + { + "s": [511.385], + "t": 9 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.124, + "y": 0.162 + }, + "i": { + "x": 0.475, + "y": 0.975 + }, + "s": [864.252], + "t": 3 + }, + { + "o": { + "x": 0.433, + "y": -0.019 + }, + "i": { + "x": 0.94, + "y": 0.934 + }, + "s": [843.505], + "t": 6 + }, + { + "s": [865.252], + "t": 9 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [0], + "t": 3 + }, + { + "s": [-60], + "t": 9 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "cl": "ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.046, 0], + [0, -11.046], + [11.046, 0], + [-5.172, 9.76] + ], + "o": [ + [11.046, 0], + [0, 11.046], + [-11.046, 0], + [5.565, -10.5] + ], + "v": [ + [0, -20], + [20, 0], + [0, 10.5], + [-20, 0] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [-5, 321], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 41 + }, + { + "ty": 4, + "nm": "Dust-Body-Bit2", + "cl": "dirt-body-bit2", + "sr": 1, + "st": 3, + "op": 103, + "ip": 3, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [-5.551, 316.252, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [60, 60, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.092, + "y": 0.198 + }, + "i": { + "x": 0.472, + "y": 0.405 + }, + "s": [529.385], + "t": 3 + }, + { + "o": { + "x": 0.357, + "y": 0.275 + }, + "i": { + "x": 0.924, + "y": 1.015 + }, + "s": [556.379], + "t": 8 + }, + { + "s": [595.885], + "t": 13 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.124, + "y": 0.379 + }, + "i": { + "x": 0.476, + "y": 0.745 + }, + "s": [864.252], + "t": 3 + }, + { + "o": { + "x": 0.523, + "y": -0.158 + }, + "i": { + "x": 0.94, + "y": 0.839 + }, + "s": [849.505], + "t": 8 + }, + { + "s": [873.252], + "t": 13 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [0], + "t": 3 + }, + { + "s": [60], + "t": 13 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "cl": "ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.046, 0], + [0, -11.046], + [11.046, 0], + [-5.172, 9.76] + ], + "o": [ + [11.046, 0], + [0, 11.046], + [-11.046, 0], + [5.565, -10.5] + ], + "v": [ + [0, -20], + [20, 0], + [0, 10.5], + [-20, 0] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [-5, 321], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 42 + }, + { + "ty": 4, + "nm": "Dust-Body-Bit1", + "cl": "dirt-body-bit1", + "sr": 1, + "st": 3, + "op": 103, + "ip": 3, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [-5.551, 316.252, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [60, 60, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "s": true, + "x": { + "a": 1, + "k": [ + { + "o": { + "x": 0.06, + "y": 0.144 + }, + "i": { + "x": 0.478, + "y": 0.57 + }, + "s": [529.385], + "t": 3 + }, + { + "o": { + "x": 0.477, + "y": 0.539 + }, + "i": { + "x": 0.924, + "y": 0.98 + }, + "s": [488.879], + "t": 8 + }, + { + "s": [459.385], + "t": 13 + } + ], + "ix": 3 + }, + "y": { + "a": 1, + "k": [ + { + "o": { + "x": 0.124, + "y": 0.497 + }, + "i": { + "x": 0.481, + "y": 1.644 + }, + "s": [864.252], + "t": 3 + }, + { + "o": { + "x": 0.595, + "y": 0.209 + }, + "i": { + "x": 0.94, + "y": 0.94 + }, + "s": [853.005], + "t": 8 + }, + { + "s": [892.752], + "t": 13 + } + ], + "ix": 4 + } + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [0], + "t": 3 + }, + { + "s": [-60], + "t": 13 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "cl": "ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [-11.046, 0], + [0, -11.046], + [11.046, 0], + [-5.172, 9.76] + ], + "o": [ + [11.046, 0], + [0, 11.046], + [-11.046, 0], + [5.565, -10.5] + ], + "v": [ + [0, -20], + [20, 0], + [0, 10.5], + [-20, 0] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [-5, 321], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 43 + }, + { + "ty": 4, + "nm": "Dust-Body-Backdrop", + "cl": "dirt-body-backdrop", + "sr": 1, + "st": 0, + "op": 100, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [50.385, 53.564, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [500, 500, 100], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [539.425, 797.822], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "cl": "group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "cl": "path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [-15.179, 17.93], + [7.44, 3.742], + [0.791, 0.78], + [3.737, 0.616], + [0.33, -0.099], + [1.155, 0.065], + [3.472, -2.533], + [3.112, 0.455], + [0, 0], + [0, -4.36], + [0, 0] + ], + "o": [ + [14.187, 10.868], + [1.917, -2.278], + [-3.737, -1.888], + [-2.446, -2.407], + [-3.079, -0.521], + [-4.631, 1.463], + [-1.29, -0.095], + [-2.612, 1.92], + [-7.176, -1.042], + [0, 0], + [0, 4.327], + [0, 0] + ], + "v": [ + [-43.303, 12.72], + [48.625, 8.263], + [35.266, -5.306], + [25.644, -6.999], + [17.907, -16.988], + [-2.694, -21.771], + [-10.266, -18.354], + [-20.021, -15.041], + [-26.275, -8.272], + [-37.518, -6.808], + [-50.084, 5.752], + [-43.305, 12.715] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "cl": "fill 1", + "c": { + "a": 0, + "k": [0.3412, 0.1333, 0.0784], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [0, 0], + "ix": 1 + }, + "s": { + "a": 0, + "k": [100, 100], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [50.686, 85.259], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 44 + } + ], + "v": "5.7.0", + "fr": 30, + "op": 100, + "ip": 0, + "assets": [] +} diff --git a/packages/client/assets/lottie/water-animation.lottie b/packages/client/assets/lottie/water-animation.lottie new file mode 100644 index 0000000000000000000000000000000000000000..ffd34e5949aaac147cc3e67e1b5d70ecb67cd8cd GIT binary patch literal 1594 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 K)Sze;^?v{~UfVVR literal 0 HcmV?d00001 diff --git a/packages/client/assets/png/solar-panel.png b/packages/client/assets/png/solar-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..560a0d036d4b2476b287ccad7221be590abea922 GIT binary patch literal 48734 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

fzg)uW)cJ!0acJ9G^2ApDk#%qf~`FWPN!J zHQ_G=F^)91b~B*}7|9ix(D*muTEsbenc>4!hTQHrEU-O;Pt>>r8x9^6+<45 zVSwVB00=erXWu_hNm0-lRaZAU&UtB#l+Z$K4s9Rr=OJnKP6cC9mbQBvS}E0HLtUK4 z-b8sFBkkVll&;KMly;N1;*9BKr^87@}nMyTe5YtaElfp@be%&QZ9e z7?Yq~+iritIj<(H=n|T`MdxH9I^a$-SW&EVo6qvjSd^=3W}tbDg4-7zbFvU3+N-@> zhV16vF(J<)(@nYGJWUXi4>Ierx3gI`!*-E=dwnHPV@r?f4W7 zRuelHfCSjaHr5Rv(Q)c*93uf3H)DMwCq96dV_<4Qg#<=mhra7=l3(ao$MZ%^or3LC zJ^5q?LQ4C8neXmwC-N@VY*IW_w5{@0HC}USrv1tJp)nPRAC21ivwc$ShBd02pnTrR zP-)68)^6``*Tq!H<%Oy#`Z;smgYpkDWyOxMeO(VZ+09KN6SLNb$B)4PNTng1TC1+j zGF6t(wo;s|krBV`rnF9_quCovuKr>amln<}I)-WHxdC8CXFLoKepY9C6%h7$>QGHC z=XiE=Q{5<#*C@_b<=QfJyOD5;BkiEYgAQEt0Oh^h8k7AJ7I`I9A*`LRe$g`3s+5GG zckuAj1O)o7PSmZr-Xf9mogWu`oRQK$63j#8SoL%Wag*(?n5 zpBSMB+k6;Jiea>&^w1+?L2ri#8Og(F6yJL?ir6~nk;Y($cU^)pv_I4N= zDHg&zl9-6S|L)y*1YVELOYOp19Z&vtwX|-H4iZp2k7LkP~FZ>>ReK7pm4KYqI1Qp?`zE(;TF_skbZ2r44x-?SW(@%zmY zhDH>)IG#4MRsWgb!__lzmJIlbq}K=siv-zS2p&ULmuO;I)9VF>nEu=xHua8z5Vtm2 z_T&k)yUrbfE{2a#29Pe-K?DRh$g-*s=BCc9_hrGScX;yHP|D7kNb9$?Jzt{d z13f)b1}-A-i0@aFK~ePHFGcZNN-5Ko>RbA@qbnYw9aJK!nim3~{hz(86i05R(PlA^ z_6|#356joAy?K8xIc%UjIRVR?jHZAW z9;GT$S8(JeLR&$tb8AG|t6Wn<2KCIubh5QFDZu}=Uhm4USLLg^oQjbIZ%`E86rTuG z3Tdck?Gq}Rc}kR=a_9*X1|IH>mQJv}IJgz}BXrt9+n-g<=n*Ty8fa^UOZ+${CG0TYb2W|ISKk2hh^m8}XNtEdY+=oUhP2c(No7sk~yg2QoX11=Q(gqU;#@RAiQn(^n?15&p z*ME|*E$J(#P(T3uzmVa4WMv^m?vpAfC58uh@Sh}|S*w*#C!E|HU#6*f7cEUrioWyRpL@o-=1A>#pU0y&n1TP%UtI6{(zU3==%gHFX)D z5Flx&L)QH!6m<55YepH(9rdz`^7-DIf?V0gl$BHQxZt&+gnYkeq%`x^{-7Yj*5=^U z&6{)4i^!*iI2_wHu~iUxFlgh&h#M}W4Lu>^`v-}v`11TAi|dLiyo!B**m*+9Xg8Bf zPaU>hEJ_+5lS*NSMXU>NMR`={Zml7E7hbTwXf>Gj`<@9GMYhjx&2sr~3JGs5Ej?PE zhL1~})UW7M40|W7@@bXj1I`=rIkrT)b5-oC4cx*Qs#u0i`yJrN4xhs{PRx*Z;QD~N z*|B`dJhC>2R9juO`M9JWbwgw;9ICH3or%G<76rxI^abMdNt~N#DuR|)mK~L>9QRhv z9u{mL5k3(X1FS0xU%TSV=t!Hjhy09YHEPUATV>D%_M|N_hW1}Loh_pjAj>D`m(qcC zpOCK9@dXXwT5^2r&tffvh(*nabIr%M ze)PprFS7V%wLzfP z@@aCCNA(nCw1*Oh*688kSpHqCk9|-!(1Wj&q+ZTSnMQw&sFCYCf`r<70H9BVLil5h zyKx0L;>RvABkapK#jZYbh6zzO#W9n2{??pR<>%)Ziw~d2ioA2!fi2c#fM&O1Drc9a1FobYr#`tYV zh1QQ)Z_2mr^qh22aVRcLnl@9#ixo_gk+CM#T0oRFb-R>A+#G%uQai zM=IJW2bH)A7R2rTzU&{{mWfb!_i;ahj9kkA<&7$u9{ZsrStUP^0<{CcJQ6WW%q~*F zP4NLj7@LQ6|EQmx3-od)oXO4n^>A_xoMb&I#mDWfGOiQ*4$P;^ZwU$D;Z4IhZ$Ap|;YT-93zb8Uy=#n%_?OAG zpf0>!_W^HkGrDdznv;Q!hq&&Dv8I_WAL%rPiUM>tjiBHhd_|jN?X}+NiFdx2sYN+4 z7a>EY!P!M!ed*f7BG)MR82(8!z@3ZYJX>cs&J`3~x4)a4Hp*FBZC!roN<2@3o7Jyz zA3}Io*7q?V*wev1(+CSbC*jFmK7XaONv)byPtMG&CYUPYMrE#*GQzx7ctzCqQedAQ zqSXoi8TzwhGi}FhU{d*r&qF$#A{afTaN3?<}#J-4j+W8jD*^-@rml=cj zo>6ziq#O_PZDE?#lVdG$ydK`PLEOajnQ$=^l&1&pu`|AtDAZ2`!fW#j!|WOF0{^{s zvd3&AJ@5l;+*RZc`e?vjaObCt7N89HSC$dv8HavVm=+*#PDhlO`jz~;?^lWr#rsMX zU1NRajLvR#2rFTh2XIV|1WnKv*&HhhicDH##T6e^B(Lory`sR%C{uzZ7%?xQr4i`n z9#wmeNfeK>cq{?YOT<8lCo6ou1}>}}B2BpFqVA-tKp_jDwSl{*dWg?OyTQVLbMf>} zcjJm@mrFQK+%*jO1A13$JA`$Bcl*=aAoT70d<3PT7LRldJM?RBPY#mW+Q!IHC+i3#6;@P*>lzB}iM zfbAm-wJOp2eTDR`o|QP&5(mDSsIQ=dY%!MxM@xX5?Z`QXxzl-wJ$=A9!aMwBbi5k!t!ZyV?kr}-e*8VQ$=gU zXMwtn76K=D&7l{wKglLGuhfkNyK4CQ8oiac857s77Qapdxhz&7NfgGxE3LkP zA_xbg8<^iv$=N#p=_D0%5D_DfdND<|+0wzFt4pA_k3XF^x6g5DoN6-Ku&xFX>blcz zeK^1}I)MNl^P^urJ&>aKCuEHbkUv)xbAyY!>ODImwW0I@QNij1$f@d(%KzPCJoq(Q zw+7l>cSivfwxS`&nA^GabYG;#=9SB_Xn8Z_jy?a~d3B5FKV5;^nPA)VOfBk^utaAe zcN5Q=i{cuFJ?h%G8Lc8#V8cu5cJ*~hTg8lN3bR2s&N<&Mq_@4nMzlPr7-#S2{1WD1 z?w^~M;>NlmeH+(IGpixYc7!u?nh)OJ{t9 zy%{x&SWaBgk*BMeI*8WIiGQ(jVy?9L<-8wD7GXQ-7CG?QgGfwNIBwj*XTd8sW4Cu> z3Dj9l_O4T{{Wk~wzy=p+tNZ_B0q#I_)F&s5pOh@2xU8^uNgT|?#4|LSLxR4sOY^HU z`AKF-BsAHKQ|e3hF{-1OKbrW{4gb}AGxONl(C!?b9PJF~a*}7@Y-|demhvf2qR#?K zif~=GbQFg)7k?kl`UDHuwC3!t=cHt5#!V zYZFbHM3<~>2+1v8P!3zh0;uC&BC6B;&mIwgm(d$3%IfMWrQVRQ<+Z4Z>4WB$YR7k@JM$ZhLrId+eEoI zbpPBTY2|r0NuRK&qkaMR9fM<|zJmUe8)Hp`o_9JDL z(@z`V@PjY}d>KaqqzeUrMOSynFf=6?%ZecpZ0Bup7@e_dbmPEY;H*Z4`Qcqr9@3hj zO%C$u#JPf>zXAZav>+cK+Q~E^t)10o?qjI*y~#~fl?+4uK~Xu+pwV8pTbRX3Z5z)m zg-%6EdU!;F?H-Z0^~r}4+RV(Lsf6li>2*N$;}MdOcac-q^(5?vzUP7|S1}6&TtwG8 zXLk3Hi%`8BBL75byS=6$s=g<;yc$jnocfSON(BZ(GnFNW<8f~~LfG@eS2)?wTxrHJ ze^<@ymX163`Th)6VIfOnjcZGF%qqs~n;xd>^hSwTI{LQ<^Pg7KjANjdE9ThP+x8q3 zjg*q0qsZhbmy5*zOU+Oro6u&5W#xsgXh&i`+jnMJBRsW#-9V zj(=)+KUIv=kF0QdXI=pn-7v-%P_4bpEau3hG@bJ```X${Qr|(;+C> zjHrp}WGQm*rasE!#XkNF|Al{_UqNI(dLY30w>4fBU1rni`riu*WFx&K^`KD#aUV&s z1G5csUp?Eo8dyr8<7Fd|SU-EgQ#X8KctJ?3nbZ7Tn0$L!RJfObfxO&O=tMhfz~4Fi zS243-oh&%IY-SbB*2;%BQjuqQzg|R}N?|->I!!;oEP2x3ahSJaC`Mpk2y9!3 zaI%eP*DicS3VTh=QksppcSHU~B>i7W?}SF0Yg(%;d~FHrN3=@ts%0u2O6|20Ou>Mm z{8f=4Hyl*|&1a?a=E3qy0UmS$oMZblY2bI+X91ZGo>~wct;>GNf*g?+Q8~n@xYYSQ z)1OPlhUS&b7P1uwt%|U`&>k=zmO{L_h_T;sQ2bZh(s=nt$-ufV>+p9Ggb7B;v~L3= zbn#P}1e{EZgXSRXIw{_NjTD4`!`V|^|CnB@s^^m6%o~+BTaPHnS)FT{YPL5Cft@gh zG8c1MOR)VOK|4Z56hFKvM-ZHxVJ)#4Cc?1u4%5q(4}E}!I_|s4?DCP_yKMk zf8Jk0x30f=A)srY0CUlQjhW2W?`q1YgdVFzjkf`Di^9xD`8h{c7u}Qm4BIhzNi1j! zK9Bnu`z`KOH&>u9UT&JU%a$;s#@Ai?M)xq8cfVb@MVgv9`$tq0AJ`o7q|GbIPR#!K zUJoXb#XC^D#<*f-cK&L8B%4L^}$_)IXpRWVb)I~IVFc# z_XCUs8t-VkP7U#`;gK$vI578~7o$U8udmI@1+RTQAg;9kn`Yrfmz^o=GMfk?niNQF z|21RBPMh2M3+@Hsoy#Zw-W{Ab`vJueu2-A0&U{|?RvzNjllO5~hheG?%&8o7SAZc3 zb-->BXCw_75w=r$7DZ{#+PwPBb60n{D4ia7U)nu4kB<{kZLm2)N9Gtro^+)|p=zbX zX&Ap)On%Q7!9WWw&q1_s!%FBdS=ttn!M#7gwr-s}BW$kVSbBNkTTo>PGmvj@*Tt`) z$s-TR;Sxy+V0ko@2t-Xjk31#=tlg=P?=xj-N3fjKUGeV~=6~%7=^9bGIIHbr=`5Pa zy9P*SpK58U*v{H}T#sl3cFhi6(&PXD0eh$beFPfi__}6xLk$jXzUy$zn9-Q_DQWwXw- z6hZjdkg9UkbQ0>rgiQD#m{?S^=vJHd7(Sq)nP!K#zOEG|b~GzaqvhL$-Z{eNe9r#O z0rqnBv#wWIu!#C4m z6E4dQPSme65=+Sl+XkVj$^mh4bE^y!SL570U_vk)# zWd!L`{oJn=<5X%dwu3oI*+w{zJEOueJrGA8iLk^7$N}|JABVQp63xz=+h`Ltj%Xs0jTxH^KIY zD1&Ofw_-{K{M9gViVo9p>3X4+z?*&DH&MtR@{yBRN0a*Jy7C5SO42+#s*&Z?+0-eV zia2`o4RDANnDmb%cg_?>kvatyits6|94{-~6x~SXv;;@5-8j@J^qcewz#i9nhT48V zH&HDzJRydOW^{~(1a)pkeXW~l$=pnGI`CG^O<3>IuRH}uFraqJ$<7HlmyW~$soM`m z?3k*8mW><++UzqI3#*zKn&f!th;9P=+v&3kYMM3-;Ybq&2EWg;7kt?;W89>jVy^$r zNw_$Hi}67%2e)U;(Sf&_zTNZ8Oax}b9R1cIZpzB5CspBDMP1ct`Je%6E|_#3`H4|IoaR;TeHM} z^08Wp$iKPyIa1Vl4ZFb8DmE`+uUR~s$324e?QZ-2cK>D z`K-Wd0{?$%Lj3(t8uhnr*6csPa~GhCe#!HGTzFOzTKus0ws%Z=d)?b<%`$C}TXT!Y zMdY4oAh(Ue^@G*q8>3x~;oW2G5E%}1BHfbIHwoI^oQ;i^G+ZyskzZxbt!kJ*4`io;&1|eWI7>79b0o+)XcaL%NPv} zc0dXU0z#r3)NBqPstEI?oqW{}!_>$Q@yLY2Z5+0H3e#ET?S8P)kBO{e0iKPUW78 z?Ts>ltdWEsw3O&AC-mwVPqA zW(0q!KBzJ)rje|hB#pN%{Kyt^`UxnRMo1I~-@A_+rF{jX=s?b@^6^gxF_`k@FL^U@#>ObVy7^WQ+wYz%0ti;*VJG=s z@ir7WZv!{Je*kwGjf{FpkfWq>FXn|59nUMiIcS1WaARRJtQhCd7@Z_x-O~anY^2R4s9|raB*>1ni z<}P-*n`%>?R=7Vuv!r`grp0@JfetrJ&Vy&9CnQOeRR$T03mSig#A-pu*86h@2au>d z4Sr|=gw8ht!eTm8u8pE4@9KMxE^i6H`V1uf^%Q%?1X$TsvLccMUxNoyQ^S# z;qfAG5}>}+P*?3*%T(#AW<*w~xf)D%ygk3{A*5d;>_)~so+PPktsJz}oE#^<+;SyS ze1cszEQpQs!%N85JA&HA@|1p{lTt0GEQYo_Z8Gk%O~WGA?mLsZzrQ{vlLwMKq+PXc zwtI;`s}!*^kwBr3LsDmEHK+X6LHQ`xw3U{W_vj&)0o97~1)VOs^0X1&Afv2-O3U42 zDg$U`A|8!OhVJ;`q5~1vNf+wcGDX8PCEjfkhe1EBb-#M5wknvLjBW7(7fKht2fRqF z&W#7STee7wOuSoKcU0G#B3f?!eOVD){iCAU*_(%kriV(mgFbM!fh_{Z-U)D%UBK$p zYWb&i&5{9n9tniUa~B3u-j-_uS2@BGgozFwg!oC$QEhyR7qPx6tH<1LOzVCs!}D-q zAN8vvLLS&-%VW|LGML#{$u?9;cFtP}6yH>*S-jEh=}Zo4C2iB^k#{tUAJzgj5l^L!;VcLYNQmjrIDr zkBnP8Uqd5|OLBs8+ht|rUrUX^#W&jSD#@v7vBKX+Wg)s{o?Wkk7!8x7>DgiHprepM zdO29Adhw6DMzLMXyWPTy3CHcla+&{Z$0~aHyncvcSyxDiCXwqf-ene{U&7$EksC5A zr?AV-jh{O9^74RO7!A1-S-(dQKIK$j{Oq3+nh{Ev8Q5K#tn@x*)&|#-V#;oTNOY0~ z=+o|`P^_}hu5)h}2b0CnJ~=XpRameh-@#~&FHxIZe7y$wRk)?jN=BA33tps)Uta9- z@@_6QzXM6l3G4hqa`#1B0pbIyq__RwxSJBLZfXrK{!y@lgLBs6&hWDU@q#D2h(+a> zkB*y(-8kOmY5~(#U;yJ3=?z%O1N7It@T_GiYNV!^zi(NK?R-!M`ck@KQWKt=bzM@N z`@J4B2)$6q&lky}C0hsg_Ev>p_`SHT@Sh!6iNEM?R-A#&^n}>+lypvsLL&eM`b7F1 z9EO_8*OQ|(kCnj8R#~hJcJSjc$#%d4%tCY!?FjUvJD{M-<+SH`#^+vN&G#b)Wa3VV zC1Em`-!}FXS}t;RkB*41b6Zmtn0vW2=?c7!m&nNxAD1j3I3?)Er=c^fr;k?2l=)Zj z%P7lts6>q0)D{3FoptD|0AS4plU9q=%!@jsGtZ~VA{Baw@6Nh{uEJk$Maf||z1 zeK8h09XO4QdZPV&r+3iqGaDUzGb)V`wM1Zc`st#Yg`LJ86r!RzTXHv!zj{X@%SJEk z-Z`C@3K%c@lI<2(06{DA13OdUR3BdeyJ5x6SMMY13FfuZ(g zLk=c{!B)_~L)6#SoFjMthqOWrqe_=UMdHdzLQy+c(CnkZ+FeD|K@Qkmao?m?1JFc4 z{Sv_^kozd5FG4%v-27>k9V@sJ+Q^nDlj9)FPqg^yvZ9w|qTN{0KGy4kiik#CLnY#Tdw)8u`fvy5?eSw&%mtok&;YrnJX+;PwT$cdfg_w~@sZey$ z)i}25>dAa)UROSR>%%HMAokfU0S1i6n0E7bo7+)P-6k3Ji?BZWb+!qOKTvxtIyy%t z4^T>XbrH>R_nm@Hm+;(r)U zd7(jT3_cTxPLwvgUY%4#L(G5WyyabblUh{*H>Q0zhvx1vx)~%Z6s&Yl@MUDQ-P*%Z z3nF+c5BX}@`{C!?N|}p{!3w&0fZsut&nUDy`Go-a@nU(c)>E5>RjlRyTmQV#1!Hj2 zr~w@|u%}LQZI)kvc>BSu*qphmWEwoPZsT6HBdfvbpBTIm!PWJc&T$BsXJ@2+d!E2M zzfZAQiV*l3=>Avg8>At5S|(GmdY6^k%cYtotTO6^0B`2|rULb{A+DKzqtBwrRQRt7 zboeCjHmug}Hjh2CK8u#iXYueJwcT=AdD363AdUanbgU*N4L;k2h?Bl>?|(% zCavOVJ56}h*imom-w|4{r_Bps>wm9l79*xzMeM7nfcyqBWbK&ju z2m#H?nt&(4=5YelVodCFRQ{uqqffBlPBs#Brx!URzU5Rc+fXQ5QqT7qkqgoc+&J3t z3DVqbKm}-gH1UtQ#*RIME8IsvCIy1Fm#2G_BzxmO1wPeYj01-64>73_mH0Jf@eR!m zHee2*g-6;)`OEdg2JT=CAZCrF51)81$kG|MZzXv>KX^iCO3EO$tO02?8@PUNp&JUs zl>>{sI)_a{087^E{u<9yOrI=?#4c4Vh%eiJ>Hb(Yj6uV@+e~w^2~NKpc<`ou5M?7@ z&qE$n9lKqy^;6xGYqgj^-XcNPB0u|h{}ol6Hh!#MqQxceX&WrY=MDOQ<(OL0YC}5fygIsGs23bRpP82OxY55t~Tbb$DkX zjy!LgBB`1^_=rJmE@4}U+nKiItKF=q_kwnAu@WFYtXkJz?j>_{{&%B8!8iH^3E&R? zik&duR7>+}X?Z*A3Bv6f5KcPac!}QL*#aC>h*L5@9+uojFn4Cm5RIsUdgPfFS4W;q zBF4a@B7Z#RDETbQ_xq0WTyA9wp0npF>>yC7Xo?z!L;qm%!x_>|Jlxw+Jt_cu>B*Rf z@@sPSc2kf4fo%MmJ^uzISWeWfo_4V>sB%KL?S+C$lmei_5CU!LbvCun{#yA*LG_6s zBh$g5pZJ1da_sPAjDl|9<4*@ocqQc@`0*0=)z17(%v)^LENJF&R>GzSKpmah@t*dB?m-2}7{u#_qcofk5!cxP z5O%*=07=h7!_(fOu?~36_;gfQv89G?yj2Ezq}1}HWg*296Dmq9%GnO{NIO3t4p{)^ zfO&3kNxd*U{kdL53xO=Ilv>`i0rdOZ62 zI5e=DV1WhW2?|QG)3aA(x7Bt+ZGOS#W3E7oMj3 zZGELFhQIK(h;SlqVWVQH3RV&Fu`hs9W_@pRYEEzOVEVohENInndPu6s%s{`jk_RXv zD8v!#T^(|h2EQAzrxWE31f@8N4z6L7oG(!S6ak1N!sZ|C(eu>f4egcl9i^qxh=&1U zlBvlB5UgZrhSbA~W8D8ZjT9yEYe}+x+wnkPNnV}f4id#-VFvWm9%H2RkUY9ReT(E1e5-UCh-1 z1OM%d(0H=R2+hwCSnGXRcu^Vb-9kf0eJiWdJ6j_f^&%56t{ytKa{SZ`gZ7Vevtd!| z%P5EIi|hV)53uCm%>(^!)>qZpBEQGT&43BQb`o+*kPiLUV+mGAA*Iri|9&Qfev}r2lL=3uG z0CMdqzjm$wTmsT!rkn0gMku7)eshk0F3%59dp(?_Basup)fy+rfNU)Ar0Xgt9X1x{ zDG#`z+GIq*GVYhsLUCV7whVBuhk%zG`)fRt0O#-V-4c%DVJywJlRo@uJHm|x1C6X= z$_a|b5#aFA5}?h}kij#yVdS>BbcTmHij{FTwgrAa6E1F$&&dxXd+N*{8bU$@Ha?iQTxd!T@VRF zg__Y(u|EA2pDlB}9tI?3!K5d>M3~=54wOUsUv)H?)csA*$fh2Kvp4+U|5$+KdFsXn zrtYYn)2~n=E-5Ak{og=k9vSsB7}#E)z>ENO-x*Jr6(hch`>bYpgP@~f*23szRv9RI zbxiPx3Q%0fTl>)AVu^P5?0HLo45(<}<_DIpT1>kbuIwI|l5(h@7!4OmD{7v{#I!eB zNN$vU{%ij8l9c-*vO(?Xc{fhZe(~;GM)#l*m@|7))HhJeo;>llH{Oi0NtNRs%;oVS z)xH{Y;yA5!eOg|zEa)tky7idj+m&In^jWLWoKrEPQ5#AC3o5)4K|v?I^3**gOWvM@$(^o#5@Ere zFKR@0c#mJ#w($-|s#i*?w`IBne!Ft;MIH1Eszg@`1L+iG>!MmP!r(tHQ2+ zMkZPZmev(h56_HX#d5ANq0&hn)E64%K5EUBr_>{OOYZ^n(@I~9G|AhJWU`@q!bhzD5Jpb}Q!>?5&Af`e$>6^>5u0NK~4KyW$W zVue&PNVTj>XztM2QvSiI@ylyyHXzg!<6EF{dpH(%bxL`yobb7y_}88#JIZv9e;DKl zLd%C14pzR|VZxdFop6AG2BF7AbLFd4rEm+BXTO_BNjU_s}6U=XWLvVt- zySsaEg1ftGaDuzLhhRClOK`UXyp!u$_fL4wT6|&k%yd_m?AqPc4V11-D|vZ`OlXlR zKmnx?A*ia!<$vss0@Yl$epxXI3fk#v1O#!n*s=p#;k$WI6yCMIc+!-A)`L2(z;fpp zw5puwE|`eiyr&X?*tbKgjmZ0AV}7Y4mG~;^wGk>rK7886X`ae_>QvC#;gtD4jjQBE zfU6d^tI(Oj3!at4yV%i7Kv8 z*+o_Q3?VFZTz@%o$)!3I3$B-SHJ6m8hTK9_#4Nf8og5E@PxTQ`-GFOs7&y;abYwPz z2%x_F9R6>wx7Sx_$earc06EK#_fd#V_H#{Wl%2gywZzMljx$qh!ea^fd6hy1lkM?5 zv}HRTv?9F@PP{D}1jfQT$b2CE7w|HTz9pi&kD;ffyss zmX4n`#T8w-M?%?rUM8}mj|vkj+qgRdc%%n7Y^N+ljWS6-=4tL&-HxO~MO3D-uvJ#- z+0vEcspG^NH5F6G5K@-#A!3t{f`e8KV^3$X$VVxi^2MXy075f+2Z4k>Nc4(5U&dfv zh+9@ACr8=B-p(X0*7Ff8^q8%@fP@wm{|IR(2QFwl`yj3c=1Sb&GHNh44?z5*MP#89 zCFZ8J&+i+cDYDn6kMeHdk%9c$i(Kl0>I_7u4M06j(y@CKnP`ca4%5y`tHf%744F%> z0V#cgD2(Kp$a?HFLl+yweg6GxDwXesnjI<|TE+3fPv2Tr?vgs?3P-<1Ir&eC?@#s$ z*`}G+Lxd50yU(}A8q}a&_9AvjfJLNL+Q2DUm$|dad%?emF8qcEYH=Ay>CzckoQvgE z&f<<-KtYU}+Rv7aiP~YkvL{TpY@9vP$+YG)sUV8DlQ>$y>M1?FMGNe2UgFax{{(3K=zLU0{?M+!)0UO_$HSHT zVCmekLsQFsQUc1!b~NLCy@fb}XTipZMxMgucmK=pkbO~AXXm9?0Q%UuVd>iR(gsrI zSKD7^eny0PC4LY!jm!d=OM$ww62MbIro^)}6G;7mykeSd)&AH(D)Dg1rn9s{f|9>4 zTi>QB9XyvgXx}?$8i6@toclHy5a?m%+s$BTfq0_)_7hFV^xzyZ7r=@3A^{0{W z7}gCdiVP%@(6HyNg7+N~JeXkGUtd)@@!GvmNddDoN^flXZ&>7LEoTxUX+Uq+cW+>jECOAllE5CSub@FK3Y#C=%BMD97Saeqd4lI@!ME)PQ2F z(Euo9#m~aSzu&*n{%_%=bW-~vMecZtK`?}GE-$`2V7x|CIXyp znD#9r3)4UaCdNT~3;}o5&rO zd_HaIgd8OciKgdS#*ppsr)0@7B=rf%X@3(IV~x#~^Sz@{ZahKaWQp3GZf8Buk7pQ7 z$2Ty=u9ZJQr3IvMzMCaXKXLQQy|0}40jYRFw1J~H7du1kG^6tMNSGXcRug`fR!A~i zRXO!IjVUd5-;Go}a#wN|+L3T>jR8*RF$D_>VRWASh(#~jSoh==n#&`-kk2^|5_I_~XxHM9skzzUKLABeC&sm|hdK1^~ zsW19igWoHCmcJsxZ4eOQueSFMisM<%5{kp^Z%|5elQ*3OhLuBzQ7?aXb^#gHJ5m;) z?rn=E;I6?wE3J}uvNh|5j_7$(G4X3yOl3z)TCDTSKJt`J9O3)x$@y&@R#q8WoD_NI z#|mEEX-HR3VK&1?R<#^cg=^)C-K$TXiUAs#qAL_831O4&vEw*f;^23eVqgz*#c~8i zBKMnt_dOobl3Ok!gvSHl>l`FJ2_hD+D{m;*R&6rXaW1Qhl9fupS|V@uNZL4~>;Ri~ zF@SByc_Vamv3Qhisj^5T&?zbu)yXJ;D^|(JKRg+Fb=>E^fW~Okp;&_WT+ZQg-@bmo zpOislJIGO4UrO>H$X_0J_Gz_)7v#5CR~HIGANg2qq&vHWSl6rMPZL<49?GU7Wy&5g zj6~HLL#W#7BG}NaG{gqQg}%7T*^{qfe5y&5E@6;beE77$m>mHMM0fYrHQ|VLFzQq`CW%G#yu?Lsc4ujgZjS3M~W*2n^hnLm$r#q3ra@CM4*) ziwW_k7W89{Jdj@XTO?CGDa+|?I$mb-w6vwo9#)VyWlqfA__ThUJs9>p@oOQwYjlPV zMi}B#>M4t2z=aWc2BQ z2sL74R`ExEO~uc}9t&u;hjlQ%r8tE5n^JYCjn4K(6H}qwc`tn~f~rVL)XD%84vmky z9z22Eb;pccNa4dG3ratpcQ+hdfI`HD$eH*C7k=pn&c>_!C=(X>_5k zubXEz%wHO2ef!4VAf_MQu5nl(4Lx47NrE8q;&=Yu>^Zl)kkzKIHaN3d;jkCiE@t7B z`&=KcTC-cb=#bNduix6WKcd`@sxtrPW8z$fKUEB9!R!tRtnZY|UTv-jCHzwx@Ubg|@G+FWzt_ zR*+ps%!4@@zWCN(V~=kh{Gn--II#oci@eaS{$KAJ2$`}ohI$^}GkLG7BkOK_?%!Yd z_?~cBx5Cu=EZ$(cQNvJo!D$9R@A$D0PS_Nh5|q5qYxu-Z+#Z8VmmpnGr7JF@XOz_U z%M@Ybi&n%WdJA-owR&9afzDDsyrd;&|U) z4@c!s(A#${4B3*g8ldzC{VMtXRpEW{?`w@18@h?hE#&K{L;9f}SZmbiL7*RV1)F4D zy!aE?Zvs0NrI_76zXVo3|Bd2&lmRuMMS!#Syh|{9XE+v=M#l0|*=j(F@)qydddLFa zjOIOI0*!374E_{;FFk%Ziuiym&+xipn)B&FQ3fHcwkB+#&asA%onU}$gah_=`;^7u z?%^_m0sQu&kR5Go5K$|DU%tW;!E`d}w_{>U894$!!Gb@L1Jc*6-2R(72sZ=l4P-|q zS7}RoF6l*MIE5T$av0~A1)^$!FhJVBHrpoAXzJF(>r~}}D!%@#X!?orC`lhUGR^B~ z?Y=d(N)qsC1--R?F63`y2-Sk6$j}Bs#?a9qB41O35N;V$VqLKT05hm;w=;aulx zF%(p@5&yz3M4B?Zg&5K0_fF)z{BBhb&bBgdXg^nidjITNLCUhj+k5=A378SBXkS6Q zGI9wCQxo2zC#YS6MW(3Un-7cMj<=k#o1ZZiN`LxG4z1UnygOjDQ3P}(WV$q@p=nQCVDpEykY~YF7pfK1V^5dGDQ zUPG4op|GWLEPM-_0X2Fj!30m%GKIo-&GyVXt2dRN>L8~3PSg6!0W9J2m$wZy={jyy z1!%2_`|h<;4UHU++xw`ZlGvD0>61qqQ3{-F=k*W0@fG}$g+f!U36g20Wb*vgTO+j! z+cU@=3@nc@y*>NfJm=25jxrkPHQQ=!3>ESEnhRgaij^H&j^w0w%hrfemET-zmzqM8 z1knIZDWhH=t1p{klG`kLakT z^3mRb4zgU7u}Xu0JzCff7Gjm=5|?czeVB28aG; zI`7#@8hP8~CcrR?g)%Gp#`FEi$xYrF)gx=FK zG5Un|3xnx_z5?cM-@*@wR?{RsKKyKR(RCS*bWo9`jxHMTdz{Nij>1C=T|+(ch?7l6 zIT?DJ@p-)n(?lD7Hyq+%M6brnb{`{{8sFvzwF5nV z;44t0*41^k6p8;KVTuJRzw`E{)vv(j%3C64Y57+;mwYTP>tde^MylS`jM-Hy zSM34cQKK93^mlu$CVX&T{@%j*b3}Y^plScY-ZhWl6la%M)Cg<<5~bTg7|2R;tv!+z zC3KjyO{R%4aiz3pmiM#gO>k&5Zx5fGof(h4RTc+H#R+~g_m}lAp)(FP!VU+J`e6wv z@&n3OQ`!-xkly6^rYx_n8al>qP1s0mgjrUzxj316=sbmNOh-td(vDk8^VaPSIISON zVnumX;LsR}_V(eiZ?;Ns<`?BUC5WaKAnn1>jKz1I4kN=phKHd`-a znF!3{tCem-4HpLo@SHf}cT2dR>+PiAX&_o*5HRfc@O?nQ`-s+Qwl6VO4g?I>NTsM0&P7ao9E>nwIO1TAs^q^bY7-E?m)SXglp(2&D^+bT{S44!!X%k9d zp~(Y0SwqXgPQ||={R*ldWI?0MW5L((B*8`o3S=y%IiInM3fj?In!rWj@{Din+A-i! z$nSRhG>jHk%1u^J`|c`|pqbjJEm0e5MWuZf_luS;m2MA8@&YrOjrSltj*ug;(;)i! z+Z)xM@_9JwtTzi3@j#UUQz7(n*KiCqn!ZRvuZ$P|&!VyJ4Z@_t4{@Kz^*`lzv|+b2 zGIiNQgQ{v0TW4_k1wM_>&Z>6mVAjDh3q%3Yn?r9%))T2A0Z-DzJ`H^qIvo^W;N`_H zh}BD2G(1s;F1l0jJ+G&GByivPS>K(fwq@(l1YAjOf4#7|-Tnw1V^}%Na5+28Ot@OS zSy(gteWWekRl=B;8co5}VUDguj2wGV))GC_e61o(Y~mvZh*g*WtP=w@w7Tbq3exsi zKV|6ONY>SLeNSj3I0ZRQLu2<><#16Yz*8ZmOhblUXnSKAoP4Z`BJH|9I`Tx#IY}-B z8sZ{^xY+GUlB*!fPQ{XBbUVhttW7b1NXh;QrP_e$cR!7wvF<=V?PuPU7gdOH)vS;|^8W&aZ|^f4h$y4`L3`)8gGpOm>QwZBfRpM}_$Fs@OlQelxAygp#YO znOAcrD$S+m<_MA7=OBfN(E$UXMLMTla*4k}D;hpN{@cGb7oy?aRWlM(BmL|bcrzh! z^38_(c;-pF@>0kj+UW3O6Irqg^W9E2+!nwguPsASm0?N)5?RP z?e=s+Cy)cCBGd#iI~|*wd9VMm<(T?r5m8qeqi=tjwpH)j8P+aIPJ&Adr!%A_B|dz3 zK(cgy!&;MG&vM-^&1(jWAB5J00t~4l5ULGP#1{s>n)4$(bgQ-R*S?u^K8${h*KM~N zx@I8RJXv?%^7m)W2}Ok_)G!+RZ7hWtOzING(eU~iJ;N1!>)|BvlR&wmx4Z7X2@5f4 zkmLJ+$ngUV2dT}OX#AO#^;j6HdZrMj;n-Z-8?5qhd75lVE)!nYtz&;PdyiSFH%nO{ z+;cro)>zY;n^U1hGWcFmk?sItqVV{(y_=R~29HDE#+Po`0*MZF6A13l6`12uE*D*g z#hBb|=4X9vrq(rb4y0cr;Aq@}3+E6*sR}0gYia!AzcQKN3!4JQu8OYgqW9it(st9S z4K-cXTmY*Fmmp@Lwaph1D^wO+?h{w}zUaa}@`JcB&+-j)I7NSYCc#(Uq@raMG%a{Q zNDX+NmIl3SwjYde}?22A?C=c-`_W@(sRF&3I|wiFucS%{A5Ghx3g z{m%QlZTaReZK-Gyf_M4L=zLtplQiBMb+=px5Rs60{(x_Xd zn+sRJRqlNLgu4*Y`(B;6kcV>xs$|dDcJiBzP6scd;h5StOp^R#LULuRWbf5)f(ANT zu`4SU7Xy8nC85S;<`mJ#E8DG|wUuSH7z&^|u`{Nn%o}Vz-6FZJ|eh#IJYn)o^-X?|;z2DO%y2XwvF9?1nHg-x>Zyw7x`mE|SKDK8E$G29k#%*-MwmO+8T&~sT z*$oxOlHZJtMflQ#*Sfldq*T1~Vx?wGNscz5)vZB_j$-8H4vn|4yyrb}bMgsWOcnQd z-M0|S!jM@2He5|2Iz_TXQN5w&{UNW`7rUr#4`!6C*-R|6fX(^<^ zvZk8$@XW`evvucLvwEjr=LMkqz8tNs_D4DQ+7p3#l_ISkNk7Vx z-a72OTnH{yE*HnZ)x}aw zch^J98ajP9VLj-CvPp2c0(5#t&d}`KL4Dqd#gjr~q0{>S`X5bd(KgC{ePx%+pFTNm zK1lY>I2=|D6A(mo;Q!I6+*x|+fA}+$Vp&tk_`tzLo(d`r8vXJ((Iy&SOUN5L@B`kn zIxf6^+XGZz71%d90cyr&Nv$~!{~>ze&W_1HTyV|yFfyB2wE}fpS*uq90ukg%i3zI` z27b~pce3&j_zYLYPOnb;QOsHQ2nM9K;OKn8PZ@;6xLZUGee8AG0GH4EyPA*l9!vi` zBYZtf2V|<1@bh~3FTNYPkl*pS7IoxzF=b)iqW)9blO@0FzwkHg!%ptBAugA!!K_Hu zpLu&xc4ADu0j!hcP*6 z)<0d-XFY;wYPIpwz^3{X>m&3QB$MGQ6jbz^h>gGIwZ0Gnmd4h0II;|#mnYi=N zt4#s4i2bDAaVIlM^ob+4wg@9k9%r3-)G`5=S%5BKOv#ZNJ<8;*kBpnebDFd1Ii}Rg z7GBJh9PmA#))#8l&~e$UJKHPZgH33PLg^&0y6n6fBrEYczd4;<59#0&4+b6#e^m#pT8xky!V8{#2 z;t)Y#X~5)23m{AY9YVIf}X{rJ}E6D z5a)E9sbg)_^aN1aZZ?eKRzecS*tI`VU=BUxT#6xukC;u{_~NMz)ddQ}T9AeI+&TCE z=M|7ZU}cY%3pz!=k+RG7%&g1hI-l`F{qzbbHWFg|i7$@;0lR7mdPeCs8{cJui-Q7W z4uK`s`Sf`nS^6*ypCy%%;%^01oVV4tx*C|-Rx#_qtFF2CO-Br9Lj{I8Gha#q)D^@2$ht5$vJjt7#&gi%KUz#P1o8sVInp14siLRSUZ%`j6=8xnhS7q#w-vNr)5V zw=Tw@29qL01~@)6_!p+c05)P%sS%Y=*)&6M_CXw>QwP_87&leY;%dcS{s%?rcl66* zv1Zceii)kn45&`$!!im=f4*%z5UB~^@>h=UzY${fvV{mR5Fg0>fo?D&#uQ$x^g1s& z7Gh>!s^D6o;6OBV^+94Hg-_JAS9bW9dkwcDxW9Hj;%BQ(8yge{tu4>J}mWPUhN4@ zLHGzGgln&m>g^;h>LjU0$d;P9`FxKnZrS+ifI$cl3?hhuZhc|eABNbbR+nZ&;824Z zN@x^CJ~uPqis9VaVrtWI({d|lPDHgSmJTEa4^Z>KzDJRn;v6m!pPxqYgT~G9*yMYi zzAlKLB`LEj0lZcFo0j`N@KH%wkfqkuEq4zr$qbD0yFqA&VM%7Ftq zf1~o9%!me>+3{f@M`h4+(}SUA0y#2S5hF^{P>>T|-*F!UoyhxyL4ua>4Pb-n7nZ0( z;Xb!OBj{c*SzO;mHeh;U{9f3(ZaYIW-dcd|L*^5o>$M3G3;j2?%q6-+X!*Qg{`mU= zkx7I@A^-?8o}OYwSz}SBy7v5ROs_z#wgq|#zV;ITy|lAT8t~RR`qezR5aN-yv~YOq z^;%cfH(O}NstZNTiVhH6Xu+tNOUF+zX>(wNz>N?g_6Y-T5upw{`puK88h1!o;yW$t zYg7nJ&x*Pt198LxbBSC-}ikMXA z@GszH6B5!vsCbe;JCV`Auoyslsh=i#b;Wa5uPqd;sQ>-}wu0;B3`AE_0v=+GkI&YK zqDYW*gbNrIk_Cl_|Ch^)!6$P5g}3BN7~T6f-hYpg7Gi}Xg3!=rkp^J{MiuYc;0(Ev zl57oS|9MU^c%-lWr{*Ic7@9 zMYbKcuYxt@)h{2@CiYO>m!WVE@;l!9(S1+QU_x5Y2J|_~^)bgoJ-K`e=t$*r`oPvGum3U+$(b@F%EN;N>MRg8(C80niGsxZ~P4UyF9z!%rM)94NdwHG5s+=0&=DK@)Fn zs_N?V8mg&pH|=~xyo7RFXE5H~ZiS--XyC=G*8sBdfyJz|ju|jFmaV0=k0n^)bs{}L z$j$DwJ#~28gwNi4(?VcrL&Mx%R!n^m3#5J7ynb~w!GBgUQeji+D?>CT|LGVw*qJ(D zU<>m$CdNap^moCXj=TR0j>79E%4BTBs5D@+kxecKqD^D0FJBiHI6QFO>NnI=KpF@w zBd7MZ_K!?U{wLQ4v4j12ychEW-v1s#YMqp#`@NXu@mBC#kwr~I!=I}57Tot+L%pJ+ zB6C@1Ij?g+Hf(+Mu3*L$9~Cp9+6gW|J(+=P)!W<5ZUKcBXcTz`4XBr9M6i&Z-l=(Y zg|p>K_5GW#C%4!6Y*Adv6mrxkz%N;fxBlJt?jrPfoU!?9%^79ZeJ_Wz@5q}nTw3Z4 zeCw?2@AAt^E&pSXLplM5QaO-Io7ufQZFnrz5=Gf`H`ffe{NR9Z<){ny56Uu ztF&aKd+u5Czj1kE!HYfddIX2v;~b=fSA`LUH`?koUBA{g)@C6uaLjKQRE*_?flkXS z+S|Jdx=x1(S_B`qOO{ToIr#_+l{Wz*kZ6rcMNs@MH%&<%Pgdjicr7wPnvgTkS9c$JX3oS7rSV&NpSY^7dO8qHy+k!!ghN@;ELDkRMY-t?ILEROj>h|ql z3oZV4kI~WoyD1|?$XNt931|;$5w=z<3_Xh;Qv@ho;9tM5TGTTjQ1(!mQS5EK-$k9m z+e6!rtt&tMXkPPr%S#6+ZehT4H2-e0(fFoNb@$BC#L*G`Kh_NrGe{EyLNz=W2ybUBxn)1K-od?*`C~q z`!N|CWm)&Hee=uWbDo2hmESUB5^&log4K_?TTT{yTsFSo>~$-?RTVIw_tC<=PydN$ zIQE2*J4o!kl-1sbTbn>(eFeIE*_I$1Ta3~h0-#|^YFcLQ-0z)vG1=$UG6{yi7tZ1m z`tS4b->ycPht=n+(nhenrL%EkR3R&Tg#7vU!XNNLLx6=K$jj~36w-tF!%qP80#@fu864aBs>H?%?eM0ps;2e)ivTnk`rY%j zDTI?Xt_^}!gevYwY>XuMHLT2 zHt&AEH3ccEEu1(y|7QQVW3rQuPsCJ}pR_3;RFCoxzLq3PWplgZ-hPa^xVtOr?CWwU}W$~xY=UBhNyO@r-ye>n~i_;Adlps64PYNUp&6#Z!9@HR!8d&Q&L_6 z8fRiT@8C}TK61numw-^1A6w_ikaq?Y?+d)}eHQz!Ohqy;^s5puOZgomVT;Yk2t&*F z@N60Ev4n!r1qCku#J8-yGKFk4i#|r4>;I_Mc{gk%X|<+zDa#ua;E&mNgtr5a1@KXK zz;a2|@l|+lu+xAUD_*vMFM8mtlIQcYl7@!E>ZUk)g!skp%IDeN^O16&IEzZ#hfm_2 zf4dUALnat@Vd{!D9S2CEA5@gggt%d)HWDZ^umS(jb2ay+C+1g_uE5Y?N>A@+C3Ss! zz|7cLIASewz45=)0(MpvHeps>9o<)eb^^ZV2UO*sS!^jH6alJ&!yvo`q-g&XrN&el zWG4Q}&)f^Cfo;z6_++?Zp>oSr`}s6~qOHDPluQ(`G6Ej~UsM_DKua<3)21!LOy>i7 zYz}Y3Ze1izimb7#DQv>_JNJOHH{G{VTlm+@a<$r;<+TS75@t9+Ml9m-VnNn(yY`Vl5QH=BCQ!v)cs z@K13{1b`a%r{87seESeMYxMB+q@+ zLG74+y?k!Rw+deS7&cHWge^74p3U!qE?Ok|$8lD|)vZSR_hZ0)#x4j7)`&2&h&iH=8GX z7MHDrsIN(%Nf!{lH(t{cq;;OPHwOQ3Qx1=iOgT_Z{-0`Sspr&0=7WVnk|pRac404m z|HNe#)I87!#^Z1CCsKEFHyIfEq_jVF&b-(Ai#gY4pGS5|bL&mWzQ7RmH9@JEAu0bS zI`MznL9fQ30Xja}2^AIYv}$M`5G6a$v=p zC5x!$fe5kBwLO=#(2`7f%_iJgiqwxUq}63yw~k2Ns#=K7d5fG*?=%3&41=lpkzc6=4C-`p;Y_ zlgz`Mg+(^E3QW8O?SRxGst*7y^k7{^RMty;A;Rx$D(N4m^Q*fED!sh6oVA{-DcmA3 ze#oZ-Ay~N_6EZ-C5GDcyV9!K=hay^hO)gAfz~&No~;0jfs+rv(%}aA5Sp(fd68-Co>OlLH9KQ?ex96`7T7tc zzUl`*A?4_WA7lZKiWqj{ma8vvhE&AyI#^5OO!~12I z*2u}uS@6T-1d!Y+E;$QBX41ig8ijV}&4iTttr9@*=FcU9L9ksBx=cyjXcGCC*= z)O=M{TeE7ZRu@Nbt@$gg;lYI&m4?MwB1;(*Ft+FYo+?OL=?kCp%~4(^0iqHKFlVQY zt`2JjG*?D?DjHb?GTp28TCslXaPVX~ZC^q#MYK)=G274hu?fpqI9xB!zh zU(yExiRkKK=0hbd0yfE*6*x^b%O|7?F5FCFcQB08Mt-lcXX0&dr{8dIMa?WVo)io{ zijd;dPl|(i>iP8L^~4~P03l)aA5Q-LyXD1PPR&2xMmq~!w>zPt4qsclfo&FoBPwm^ zZjS#tt5k-!vKBoDx4VHtaQ@7GQ5_BLL&bstcz{%G@0K@vi780#yqitS$wXmkGjjJj zM_E;~-^!M5VFERvL6YQE;0YrV^s8`D55HZ=m_U&Eh={5zkaj#SH&=Illl3!DW9u*+ z*tormm3O^=*mP|Ju)!?r5j(VB4@2#(R5%{VMejx3kGI(q&2Z^HccMtKN9*$*cRk)5 zKh-6+Pm{3}29a}CfJp(U&dV5jC(y~VeX8bGxB_*1CM@psB@>*0n(~jfVA1wj5v;NL z+v28I$;FrIqo%4}FtQT%Gz{M$nlaM6^i-TI65e$d{k&r_&2K+Zi6|xmL_u}@*}p4K z8*F%|Ht6lAnMNF(fc~|hnC){TPg=44!myHS=|%7x%mVP(G(j%3#7L< zx&}BZiGr$Xx5$!KmG^;)u*-bybrl^e$=6VsrACuPy*InC#i#bS5$W+y8lm$1*LDqL zB&=E0Umn7v7iT@D%&a(GFyvI8r+{HHrhTgP^|iFJ38C)O(Gnr$=7|Z|Kv8R2Y5G#| zo`wjIw_xqvNrTRXm^jdH1R``FVfWW%mqG^cBo>f}KLsqVpE9&F5-rS6y1CQoJ=?ErEhv5t zG59p^Mt}jpDO{qkc{dm``iSHJ$c*Sn-eaEmI}uYeAnkXyytD67Pg_RO&|cY6WJUn= z{Wso<<)u=2!bflEmbJlTOyi4P*iId{#8(N_ zmc6DgPRm=pUuTHEJ+%UP3>XdrR45MKv%mfL)|9h?e1CI0aGJY;FZ@4z3_jP+6VsIT zG1}c-51T>`8MOy!q`d;S(neBBAX9W@$jBCk_uJr!WOyouj*li9SXgHx<(Lg`M8Q>W&G6RF zs$~VHrDOGk8JjYMG5GafRC=e2`$-d^rovM{{iCpKF6~~DOOO1^kAeLpb-Tv5SRk4q zMDcqc&%^nie`+!74D9_Y^HY42;~r27wDu89ab_i7acl zt{9Hid6bfvI$`Hay{|Wf&ZiZ5yuKdEeaZv}qE=%9t)%m(T3)2(=KKo(R?M7eg5Fbr zl%+`q^(hKYc|Ghms=!;Q)j;kOE?qX(a_gcz_olhjB+a(-Qv{kAPJ$o##l!+d(7SgY z*n2|_biU-k^3wiIMomtT+DKl@hz$dTIEWQki%hWcET;lZObP5U`4~U9{W5t%T?eSMs8_Y<~FlL9#o9^F8`Q_ zfaiA7a!fxt9Qz*uNV@FR^0E?L@oGe~jGRUb6(6r6vaK>el?zt6!67T`1PrJ?(Qait zYh?GHLv4+MBvXAp;^kOIIMros%qE8Zm)FRBakQ$x5t;fMjj zy-8L-b~J`JmNDpt-=ik50LrALDRaKyVP(C~*IvVk%Tu$WhupGavKt?d`U9(Ajl=Z> zToj5d`=8N|!e@5ryeZB#Z6vgxu^RJ}X@JO0#bz&t3RGqwqw!D?W#qsM!D0p*shRPN zepMA2e8g#Y>m1Zjzc7JQ5MBotP@sEincSF3X&C^~a?XK!UJ_L$yjADsUqwb7y~j7* zv2sC@;Trr_dt??fXBpIqEqcf`l$OVp zTR*iAL3~?&e70XAwTF_FEEx4)9Ej=RWxdigE_Xsta03LbEwS9WQuEvOCEE#YdP0n~LJ=Xr#oaeo2=D61hM;!FKfS=oW z_b3mGMU0dc5AYOb$6gjuTrVHhWCW@Ao>!19%E z{sySA@0f3G76B0&8XA^Tl*5Yu(P78F?7cXjpp84d*#GYz7~+q46|g5Qiq!)G Oep2G{Vl^U$-~S&$a#DE! literal 0 HcmV?d00001 diff --git a/packages/client/assets/svg/Loading.svg b/packages/client/assets/svg/Loading.svg new file mode 100644 index 0000000..64ad659 --- /dev/null +++ b/packages/client/assets/svg/Loading.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/client/assets/svg/PatchDry.svg b/packages/client/assets/svg/PatchDry.svg new file mode 100644 index 0000000..d7651f5 --- /dev/null +++ b/packages/client/assets/svg/PatchDry.svg @@ -0,0 +1,1186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/assets/svg/PatchNormal.svg b/packages/client/assets/svg/PatchNormal.svg new file mode 100644 index 0000000..2e87d7f --- /dev/null +++ b/packages/client/assets/svg/PatchNormal.svg @@ -0,0 +1,1186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/assets/svg/PatchWet.svg b/packages/client/assets/svg/PatchWet.svg new file mode 100644 index 0000000..19c382d --- /dev/null +++ b/packages/client/assets/svg/PatchWet.svg @@ -0,0 +1,1186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/assets/svg/produce/apple.svg b/packages/client/assets/svg/produce/apple.svg new file mode 100644 index 0000000..182b8e4 --- /dev/null +++ b/packages/client/assets/svg/produce/apple.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/beet.svg b/packages/client/assets/svg/produce/beet.svg new file mode 100644 index 0000000..3af1764 --- /dev/null +++ b/packages/client/assets/svg/produce/beet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/cabbage.svg b/packages/client/assets/svg/produce/cabbage.svg new file mode 100644 index 0000000..f84b33c --- /dev/null +++ b/packages/client/assets/svg/produce/cabbage.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/carrot.svg b/packages/client/assets/svg/produce/carrot.svg new file mode 100644 index 0000000..9088b0c --- /dev/null +++ b/packages/client/assets/svg/produce/carrot.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/assets/svg/produce/cherry.svg b/packages/client/assets/svg/produce/cherry.svg new file mode 100644 index 0000000..5348537 --- /dev/null +++ b/packages/client/assets/svg/produce/cherry.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/corn.svg b/packages/client/assets/svg/produce/corn.svg new file mode 100644 index 0000000..6ee0a30 --- /dev/null +++ b/packages/client/assets/svg/produce/corn.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/cucumber.svg b/packages/client/assets/svg/produce/cucumber.svg new file mode 100644 index 0000000..918e1ba --- /dev/null +++ b/packages/client/assets/svg/produce/cucumber.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/kiwi.svg b/packages/client/assets/svg/produce/kiwi.svg new file mode 100644 index 0000000..786dd79 --- /dev/null +++ b/packages/client/assets/svg/produce/kiwi.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/leek.svg b/packages/client/assets/svg/produce/leek.svg new file mode 100644 index 0000000..51bb03d --- /dev/null +++ b/packages/client/assets/svg/produce/leek.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/lettuce.svg b/packages/client/assets/svg/produce/lettuce.svg new file mode 100644 index 0000000..5f3cf69 --- /dev/null +++ b/packages/client/assets/svg/produce/lettuce.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/peas.svg b/packages/client/assets/svg/produce/peas.svg new file mode 100644 index 0000000..524c6c4 --- /dev/null +++ b/packages/client/assets/svg/produce/peas.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/plum.svg b/packages/client/assets/svg/produce/plum.svg new file mode 100644 index 0000000..8e1af85 --- /dev/null +++ b/packages/client/assets/svg/produce/plum.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/potato.svg b/packages/client/assets/svg/produce/potato.svg new file mode 100644 index 0000000..47632b5 --- /dev/null +++ b/packages/client/assets/svg/produce/potato.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/radish.svg b/packages/client/assets/svg/produce/radish.svg new file mode 100644 index 0000000..c7bd98e --- /dev/null +++ b/packages/client/assets/svg/produce/radish.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/raspberry.svg b/packages/client/assets/svg/produce/raspberry.svg new file mode 100644 index 0000000..ddeefd2 --- /dev/null +++ b/packages/client/assets/svg/produce/raspberry.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/strawberry.svg b/packages/client/assets/svg/produce/strawberry.svg new file mode 100644 index 0000000..2db7831 --- /dev/null +++ b/packages/client/assets/svg/produce/strawberry.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/assets/svg/produce/tomato.svg b/packages/client/assets/svg/produce/tomato.svg new file mode 100644 index 0000000..9cee538 --- /dev/null +++ b/packages/client/assets/svg/produce/tomato.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/client/index.html b/packages/client/index.html new file mode 100644 index 0000000..0973901 --- /dev/null +++ b/packages/client/index.html @@ -0,0 +1,26 @@ + + + + + + Tom's Allotment + + + + + + + +

+ + + diff --git a/packages/client/package-lock.json b/packages/client/package-lock.json new file mode 100644 index 0000000..a0fa6ca --- /dev/null +++ b/packages/client/package-lock.json @@ -0,0 +1,3192 @@ +{ + "name": "@toms-allotment/client", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@toms-allotment/client", + "version": "0.0.0", + "dependencies": { + "antd": "^5.29.3", + "blurhash": "^2.0.5", + "dayjs": "^1.11.13", + "fflate": "^0.8.2", + "lottie-react": "^2.4.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-icons": "^5.6.0", + "react-responsive": "^10.0.1", + "react-router-dom": "^7.13.1", + "recharts": "^3.8.1", + "simplebar-react": "^3.3.2", + "socket.io-client": "^4.8.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.10", + "vite-plugin-svgo": "^2.0.0", + "vite-plugin-svgr": "^4.5.0" + } + }, + "../../node_modules/.pnpm/@vitejs+plugin-react@4.7.0_vite@5.4.21_@types+node@25.5.0_/node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "devDependencies": { + "@vitejs/react-common": "workspace:*", + "babel-plugin-react-compiler": "19.1.0-rc.2", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "rolldown": "1.0.0-beta.27", + "tsdown": "^0.12.9", + "vitest": "^3.2.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom": { + "version": "18.3.1", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "../../node_modules/.pnpm/react@18.3.1/node_modules/react": { + "version": "18.3.1", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../../node_modules/.pnpm/socket.io-client@4.8.3/node_modules/socket.io-client": { + "version": "4.8.3", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "../../node_modules/.pnpm/vite@5.4.21_@types+node@25.5.0/node_modules/vite": { + "version": "5.4.21", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "devDependencies": { + "@ampproject/remapping": "^2.3.0", + "@babel/parser": "^7.25.6", + "@jridgewell/trace-mapping": "^0.3.25", + "@polka/compression": "^1.0.0-next.25", + "@rollup/plugin-alias": "^5.1.0", + "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-dynamic-import-vars": "^2.1.2", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "15.2.3", + "@rollup/pluginutils": "^5.1.0", + "@types/escape-html": "^1.0.4", + "@types/pnpapi": "^0.0.5", + "artichokie": "^0.2.1", + "cac": "^6.7.14", + "chokidar": "^3.6.0", + "connect": "^3.7.0", + "convert-source-map": "^2.0.0", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "debug": "^4.3.6", + "dep-types": "link:./src/types", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", + "es-module-lexer": "^1.5.4", + "escape-html": "^1.0.3", + "estree-walker": "^3.0.3", + "etag": "^1.8.1", + "fast-glob": "^3.3.2", + "http-proxy": "^1.18.1", + "launch-editor-middleware": "^2.9.1", + "lightningcss": "^1.26.0", + "magic-string": "^0.30.11", + "micromatch": "^4.0.8", + "mlly": "^1.7.1", + "mrmime": "^2.0.0", + "open": "^8.4.2", + "parse5": "^7.1.2", + "pathe": "^1.1.2", + "periscopic": "^4.0.2", + "picocolors": "^1.0.1", + "picomatch": "^2.3.1", + "postcss-import": "^16.1.0", + "postcss-load-config": "^4.0.2", + "postcss-modules": "^6.0.0", + "resolve.exports": "^2.0.2", + "rollup-plugin-dts": "^6.1.1", + "rollup-plugin-esbuild": "^6.1.1", + "rollup-plugin-license": "^3.5.2", + "sass": "^1.77.8", + "sass-embedded": "^1.77.8", + "sirv": "^2.0.4", + "source-map-support": "^0.5.21", + "strip-ansi": "^7.1.0", + "strip-literal": "^2.1.0", + "tsconfck": "^3.1.4", + "tslib": "^2.7.0", + "types": "link:./types", + "ufo": "^1.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.24.0.tgz", + "integrity": "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rc-component/async-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.1.0.tgz", + "integrity": "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.3.tgz", + "integrity": "sha512-bk/FJ09fLf+NLODMAFll6CfYrHPBioTedhW6lxDBuuWucJEqFUd4l/D/5JgIi3dina6sYahB8iuPAZTNz2pMxw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.1.1.tgz", + "integrity": "sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.3.1.tgz", + "integrity": "sha512-ORENF39PeXTzM+gQEshuk460Z8N4+6DkjpxlpE7Q3gYy1iBpLrx0FOJz3h62ryrJZ/3zCAUIkT1Pb/8hHWpb3A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "resolved": "../../node_modules/.pnpm/@vitejs+plugin-react@4.7.0_vite@5.4.21_@types+node@25.5.0_/node_modules/@vitejs/plugin-react", + "link": true + }, + "node_modules/antd": { + "version": "5.29.3", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.29.3.tgz", + "integrity": "sha512-3DdbGCa9tWAJGcCJ6rzR8EJFsv2CtyEbkVabZE14pfgUHfCicWCj0/QzQVLDYg8CPfQk9BH7fHCoTXHTy7MP/A==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.2.1", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.1.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.3.0", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.34.0", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.3.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.1", + "rc-image": "~7.12.0", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.4", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.8", + "rc-slider": "~11.1.9", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.54.0", + "rc-tabs": "~15.7.0", + "rc-textarea": "~1.10.2", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.11.0", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz", + "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/blurhash": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz", + "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==", + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/css-mediaquery": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", + "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==", + "license": "BSD" + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "2" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "license": "MIT", + "peer": true + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.328", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz", + "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-toolkit": { + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", + "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lottie-react": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.1.tgz", + "integrity": "sha512-LQrH7jlkigIIv++wIyrOYFLHSKQpEY4zehPicL9bQsrt1rnoKRYCYgpCUe5maqylNtacy58/sQDZTkwMcTRxZw==", + "license": "MIT", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.13.0.tgz", + "integrity": "sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==", + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/matchmediaquery": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.4.2.tgz", + "integrity": "sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==", + "license": "MIT", + "dependencies": { + "css-mediaquery": "^0.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/rc-cascader": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.34.0.tgz", + "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.3.0.tgz", + "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.1.tgz", + "integrity": "sha512-vKeSifSJ6HoLaAB+B8aq/Qgm8a3dyxROzCtKNCsBQgiverpc4kWDQihoUwzUj+zNWJOykwSY4dNX3QrGwtVb9A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.12.0.tgz", + "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.5.0.tgz", + "integrity": "sha512-Lm/v9h0LymeUYJf0x39OveU52InkdRXqnn2aYXfWmo8WdOonIKB2kfau+GF0fWq6jPgtdO9yMqveGcK6aIhJmg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.1.tgz", + "integrity": "sha512-izj1Nw/Dw2Vb7EVr+D/E9lUTkBe+kKC+SAFSU9zqr7WV2W5Ktaa9Gc7cB2jTqgk8GROJayltaec+DBlYKc6d+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.8", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.9", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.9.tgz", + "integrity": "sha512-h8IknhzSh3FEM9u8ivkskh+Ef4Yo4JRIY2nj7MrH6GQmrwV6mcpJf5/4KgH5JaVI1H3E52yCdpOlVyGZIeph5A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.54.0", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.54.0.tgz", + "integrity": "sha512-/wDTkki6wBTjwylwAGjpLKYklKo9YgjZwAU77+7ME5mBoS32Q4nAwoqhA2lSge6fobLW3Tap6uc5xfwaL2p0Sw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.7.0.tgz", + "integrity": "sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.2.tgz", + "integrity": "sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.11.0.tgz", + "integrity": "sha512-ZUyT//2JAehfHzjWowqROcwYJKnZkIUGWaTE/VogVrepSl7AFNbQf4+zGfX4zl9Vrj/Jm8scLO0R6UlPDKK4wA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rc-virtual-list": { + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.19.2.tgz", + "integrity": "sha512-Ys6NcjwGkuwkeaWBDqfI3xWuZ7rDiQXlH1o2zLfFzATfEgXcqpk8CkgMfbJD81McqjcJVez25a3kPxCR807evA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "resolved": "../../node_modules/.pnpm/react@18.3.1/node_modules/react", + "link": true + }, + "node_modules/react-dom": { + "resolved": "../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom", + "link": true + }, + "node_modules/react-icons": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz", + "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT", + "peer": true + }, + "node_modules/react-responsive": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-10.0.1.tgz", + "integrity": "sha512-OM5/cRvbtUWEX8le8RCT8scA8y2OPtb0Q/IViEyCEM5FBN8lRrkUOZnu87I88A6njxDldvxG+rLBxWiA7/UM9g==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.0", + "matchmediaquery": "^0.4.2", + "prop-types": "^15.6.1", + "shallow-equal": "^3.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/react-router": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", + "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz", + "integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==", + "license": "MIT", + "dependencies": { + "react-router": "7.13.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/recharts": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", + "integrity": "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts/node_modules/@reduxjs/toolkit": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", + "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/recharts/node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz", + "integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/recharts/node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT", + "peer": true + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/shallow-equal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz", + "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==", + "license": "MIT" + }, + "node_modules/simplebar-core": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/simplebar-core/-/simplebar-core-1.3.2.tgz", + "integrity": "sha512-qKgTTuTqapjsFGkNhCjyPhysnbZGpQqNmjk0nOYjFN5ordC/Wjvg+RbYCyMSnW60l/Z0ZS82GbNltly6PMUH1w==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "lodash-es": "^4.17.21" + } + }, + "node_modules/simplebar-react": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-3.3.2.tgz", + "integrity": "sha512-ZsgcQhKLtt5ra0BRIJeApfkTBQCa1vUPA/WXI4HcYReFt+oCEOvdVz6rR/XsGJcKxTlCRPmdGx1uJIUChupo+A==", + "license": "MIT", + "dependencies": { + "simplebar-core": "^1.3.2" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/socket.io-client": { + "resolved": "../../node_modules/.pnpm/socket.io-client@4.8.3/node_modules/socket.io-client", + "link": true + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/victory-vendor/node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/vite": { + "resolved": "../../node_modules/.pnpm/vite@5.4.21_@types+node@25.5.0/node_modules/vite", + "link": true + }, + "node_modules/vite-plugin-svgo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgo/-/vite-plugin-svgo-2.0.0.tgz", + "integrity": "sha512-WaiOUlmt1fKw1w/WWJnx9gVk42D1BASKZmGCPpy6iTLE5iIemN2lim3MwI7Rffyt3aQnPrLfLSLnI8ZUJ9s49g==", + "dev": true, + "license": "ISC", + "dependencies": { + "svgo": "3.3.2" + }, + "peerDependencies": { + "typescript": ">=4.9.4", + "vite": ">=4.0.2" + } + }, + "node_modules/vite-plugin-svgr": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", + "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.2.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=2.6.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 0000000..d9009d5 --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,32 @@ +{ + "name": "@toms-allotment/client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "antd": "^5.29.3", + "blurhash": "^2.0.5", + "dayjs": "^1.11.13", + "fflate": "^0.8.2", + "lottie-react": "^2.4.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-icons": "^5.6.0", + "react-responsive": "^10.0.1", + "react-router-dom": "^7.13.1", + "recharts": "^3.8.1", + "simplebar-react": "^3.3.2", + "socket.io-client": "^4.8.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.10", + "vite-plugin-svgo": "^2.0.0", + "vite-plugin-svgr": "^4.5.0" + } +} diff --git a/packages/client/src/App.css b/packages/client/src/App.css new file mode 100644 index 0000000..d46d0ec --- /dev/null +++ b/packages/client/src/App.css @@ -0,0 +1,219 @@ +:root { + /* Mirrors .sidebar width: 25% of viewport with 420px minimum */ + --sidebar-width: max(25vw, 380px); + --app-main-padding-top: 18vh; + --app-main-padding-bottom: 18vh; + --app-main-padding-right: 10vw; + --app-main-padding-left: 10vw; + --bg: #0f1419; + --surface: #1a222c; + --border: #2a3544; + /* Same language as .btn default border (Button.css) */ + --border-ui-width: 2px; + --border-ui-color: color-mix(in srgb, var(--text) 8%, transparent); + --danger-border-color: color-mix(in srgb, var(--danger) 8%, transparent); + --text: #e8eef5; + --muted: color-mix(in srgb, var(--text) 75%, transparent); + --accent: #9cc815; + --accent-dim: #1fa86a; + --danger: #e56868; + --bg-spot: #1a2838; + --sidebar-bg: #0c1218; + --link-hover: color-mix(in srgb, var(--text) 8%, transparent); + --on-accent: #0a120e; + --warn: #e6b35c; + --font: "Rubik", system-ui, sans-serif; + --mono: "JetBrains Mono", ui-monospace, monospace; +} + +html { + height: 100%; + overflow: hidden; + overscroll-behavior: none; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + height: 100%; + overflow: hidden; + overscroll-behavior: none; + background: var(--bg); + color: var(--text); + font-family: var(--font); + font-size: 15px; + line-height: 1.5; +} + +#root { + height: 100%; +} + +.app-shell { + position: relative; + width: 100vw; + height: 100dvh; + overflow: hidden; +} + +.app-main { + width: 100vw; + height: 100dvh; + min-width: 0; + display: flex; + flex-direction: column; + padding: 0; +} + +.app-shell-inner { + transition: transform 0.35s cubic-bezier(0.33, 1, 0.68, 1); + transform-origin: 0% 50%; +} + +.app-shell--mobile .app-shell-inner { + transform-origin: 50% 50%; +} + +.page-title { + margin: 0; + font-size: 1.5rem; + font-weight: 700; + line-height: 1.2; + letter-spacing: -0.02em; +} + +.overview-page { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; +} + +.overview-section.wide { + width: 100%; +} + +.sub { + margin: 0.35rem 0 0; + color: var(--muted); + font-size: 0.9rem; +} + +.dot { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; +} + +.dot.ok { + background: var(--accent); +} + +.dot.bad { + background: var(--warn); +} + +.user { + color: var(--muted); + font-size: 0.9rem; +} + +.grid { + display: grid; + gap: 1.25rem; +} + +.metrics.metrics--horizontal > * { + flex: 1 1 140px; + min-width: 0; +} + +.metrics .label { + display: block; + font-size: 0.75rem; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.25rem; +} + +.metrics strong { + font-size: 1.35rem; + font-weight: 600; +} + +.field { + display: flex; + flex-direction: column; + margin-bottom: 1rem; + font-size: 0.9rem; + color: var(--muted); +} + +.field select { + display: block; + margin-top: 0.35rem; + width: 100%; + max-width: 320px; + padding: 0.5rem 0.65rem; + border-radius: 8px; + border: var(--border-ui-width) solid var(--border-ui-color); + background: var(--bg); + color: var(--text); + font-family: inherit; +} + +.hint { + font-size: 0.85rem; + color: var(--muted); +} + +.muted { + color: var(--muted); + font-size: 0.85rem; +} + +.sessions { + list-style: none; + margin: 0; + padding: 0; +} + +.sessions li { + padding: 0.65rem 0; + border-bottom: var(--border-ui-width) solid var(--border-ui-color); + display: grid; + gap: 0.35rem; +} + +.sessions li:last-child { + border-bottom: none; +} + +.mono { + font-family: var(--mono); + font-size: 14px; + font-weight: 600; +} + +.animated { + transition: + transform 0.35s cubic-bezier(0.33, 1, 0.68, 1), + opacity 0.35s cubic-bezier(0.33, 1, 0.68, 1); + opacity: 0; + transform: translateY(20px); +} + +.animated.visible { + transform: translateY(0); + opacity: 1; +} + +.animated.hidden { + transform: translateY(-20px); + opacity: 0; +} diff --git a/packages/client/src/App.jsx b/packages/client/src/App.jsx new file mode 100644 index 0000000..a562f07 --- /dev/null +++ b/packages/client/src/App.jsx @@ -0,0 +1,153 @@ +import React, { + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, +} from "react"; +import { + BrowserRouter, + Navigate, + Route, + Routes, + useLocation, +} from "react-router-dom"; +import AnimatedOutlet from "./components/AnimatedOutlet.jsx"; +import { PageScroll } from "./components/PageScroll.jsx"; +import { Sidebar } from "./components/Sidebar.jsx"; +import { AuthProvider } from "./contexts/AuthContext.jsx"; +import { ApiProvider } from "./contexts/ApiContext.jsx"; +import { LottieFileProvider } from "./contexts/LottieFileContext.jsx"; +import { ThemeProvider, useTheme } from "./contexts/ThemeContext.jsx"; +import { PatchesPage } from "./pages/PatchesPage.jsx"; +import { PowerPage } from "./pages/PowerPage.jsx"; +import { WaterTankPage } from "./pages/WaterTankPage.jsx"; +import { WateringSessionPage } from "./pages/WateringSessionPage.jsx"; +import { WaterSchedulesPage } from "./pages/WaterSchedulesPage.jsx"; + +const SITE_TITLE = "Tom's Allotment"; + +const ROUTES = [ + { + path: "/patches", + element: , + title: "Patches", + scrollable: true, + }, + { + path: "/water-tank", + element: , + title: "Water tank", + scrollable: true, + }, + { + path: "/power", + element: , + title: "Power", + scrollable: true, + }, + { + path: "/watering-sessions", + element: , + title: "Watering sessions", + scrollable: true, + }, + { + path: "/water-schedules", + element: , + title: "Watering schedules", + scrollable: true, + }, +]; + +const REDIRECT_ROUTES = [ + { path: "/", to: "/patches" }, + { path: "/overview", to: "/patches" }, +]; + +function normalizePathname(pathname) { + if (pathname.length > 1 && pathname.endsWith("/")) { + return pathname.slice(0, -1); + } + return pathname; +} + +function routeMetaForPathname(pathname) { + const key = normalizePathname(pathname); + const route = ROUTES.find((r) => normalizePathname(r.path) === key); + return route + ? { title: route.title, scrollable: route.scrollable } + : { title: SITE_TITLE, scrollable: true }; +} + +function AppLayout() { + const { isMobile, pageTransitionDuration } = useTheme(); + const location = useLocation(); + const { title: pageTitle, scrollable: routeScrollable } = useMemo( + () => routeMetaForPathname(location.pathname), + [location.pathname], + ); + + const [scrollable, setScrollable] = useState(routeScrollable); + const prevPathnameRef = useRef(location.pathname); + + useEffect(() => { + if (prevPathnameRef.current === location.pathname) return; + + prevPathnameRef.current = location.pathname; + const id = window.setTimeout(() => { + setScrollable(routeScrollable); + }, pageTransitionDuration); + + return () => { + window.clearTimeout(id); + }; + }, [location.pathname, routeScrollable, pageTransitionDuration]); + + useEffect(() => { + document.title = + pageTitle === SITE_TITLE ? SITE_TITLE : `${pageTitle} · ${SITE_TITLE}`; + }, [pageTitle]); + + return ( +
+
+ +
+ + + +
+
+
+ ); +} + +export default function App() { + return ( + + + + + + + }> + {REDIRECT_ROUTES.map(({ path, to }) => ( + } + /> + ))} + {ROUTES.map(({ path, element }) => ( + + ))} + + + + + + + + ); +} diff --git a/packages/client/src/components/AnimatedOutlet.css b/packages/client/src/components/AnimatedOutlet.css new file mode 100644 index 0000000..3d108bd --- /dev/null +++ b/packages/client/src/components/AnimatedOutlet.css @@ -0,0 +1,82 @@ +.animated-outlet-container { + position: relative; + width: 100%; +} + +.animated-outlet { + width: 100%; + will-change: opacity, transform; +} + +/* Stable view: stays in document flow so scroll height matches content */ +.animated-outlet.visible { + position: relative; + z-index: 10; + opacity: 1; + transform: translateY(0); + will-change: auto; +} + +/* New route: overlays while old still defines block height */ +.animated-outlet.enter { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 20; + min-height: 100%; + opacity: 0; + transform: translateY(20px); + animation: animatedOutletEnter var(--page-transition-duration, 500ms) ease + forwards; +} + +/* Outgoing route: same flow as visible; motion matches AnimatedText exit */ +.animated-outlet.exit { + position: relative; + z-index: 10; + opacity: 1; + transform: translateY(0); + animation: animatedOutletExit var(--page-transition-duration, 500ms) ease + forwards; +} + +@keyframes animatedOutletEnter { + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes animatedOutletExit { + to { + opacity: 0; + transform: translateY(-20px); + } +} + +/* Back / forward: enter from top, exit downward */ +.animated-outlet.enter.reverse { + transform: translateY(-20px); + animation: animatedOutletEnterReverse var(--page-transition-duration, 500ms) + ease forwards; +} + +.animated-outlet.exit.reverse { + animation: animatedOutletExitReverse var(--page-transition-duration, 500ms) + ease forwards; +} + +@keyframes animatedOutletEnterReverse { + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes animatedOutletExitReverse { + to { + opacity: 0; + transform: translateY(20px); + } +} diff --git a/packages/client/src/components/AnimatedOutlet.jsx b/packages/client/src/components/AnimatedOutlet.jsx new file mode 100644 index 0000000..38c815f --- /dev/null +++ b/packages/client/src/components/AnimatedOutlet.jsx @@ -0,0 +1,184 @@ +import React, { + useRef, + useState, + useEffect, + useLayoutEffect, +} from "react"; +import { useOutlet, useLocation, useNavigationType } from "react-router-dom"; +import { useTheme } from "../contexts/ThemeContext.jsx"; +import "./AnimatedOutlet.css"; + +function AnimatedOutlet() { + const { pageTransitionDuration } = useTheme(); + const location = useLocation(); + const outlet = useOutlet(); + const navigationType = useNavigationType(); + const [outlet1, setOutlet1] = useState(outlet); + const [outlet2, setOutlet2] = useState(null); + const [activeOutlet, setActiveOutlet] = useState(1); + const [isTransitioning, setIsTransitioning] = useState(false); + const [isReversed, setIsReversed] = useState(false); + const timeoutRef = useRef(null); + const prevPathnameRef = useRef(location.pathname); + const isTransitioningRef = useRef(false); + const activeOutletRef = useRef(1); + /** Latest route to animate to after the in-flight transition finishes (coalesces rapid navigations). */ + const pendingNavigationRef = useRef(null); + const pageTransitionDurationRef = useRef(pageTransitionDuration); + pageTransitionDurationRef.current = pageTransitionDuration; + const containerRef = useRef(null); + const outlet1Ref = useRef(null); + const outlet2Ref = useRef(null); + + activeOutletRef.current = activeOutlet; + + useLayoutEffect(() => { + const container = containerRef.current; + if (!container) return; + + if (!isTransitioning) { + container.style.minHeight = ""; + return; + } + + const exitEl = activeOutlet === 1 ? outlet1Ref.current : outlet2Ref.current; + const enterEl = activeOutlet === 1 ? outlet2Ref.current : outlet1Ref.current; + if (!exitEl || !enterEl) return; + + const hOld = exitEl.scrollHeight; + const hNew = enterEl.scrollHeight; + + if (hNew > hOld) { + container.style.minHeight = `${hNew}px`; + } else { + container.style.minHeight = ""; + } + }, [isTransitioning, activeOutlet, outlet1, outlet2]); + + const completeTransition = () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + + const current = activeOutletRef.current; + const nextActive = current === 1 ? 2 : 1; + if (current === 1) { + setOutlet1(null); + setActiveOutlet(2); + } else { + setOutlet2(null); + setActiveOutlet(1); + } + + const pending = pendingNavigationRef.current; + const shouldChain = + pending && pending.pathname !== prevPathnameRef.current; + + if (shouldChain) { + pendingNavigationRef.current = null; + prevPathnameRef.current = pending.pathname; + setIsReversed(pending.navigationType === "POP"); + if (nextActive === 1) { + setOutlet2(pending.outlet); + } else { + setOutlet1(pending.outlet); + } + isTransitioningRef.current = true; + setIsTransitioning(true); + timeoutRef.current = setTimeout( + completeTransition, + pageTransitionDurationRef.current, + ); + } else { + isTransitioningRef.current = false; + setIsTransitioning(false); + } + }; + + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + }; + }, []); + + useEffect(() => { + if (location.pathname !== prevPathnameRef.current && outlet) { + if (isTransitioningRef.current) { + pendingNavigationRef.current = { + pathname: location.pathname, + outlet, + navigationType, + }; + return; + } + + const isBackward = navigationType === "POP"; + setIsReversed(isBackward); + + isTransitioningRef.current = true; + setIsTransitioning(true); + prevPathnameRef.current = location.pathname; + + const current = activeOutletRef.current; + if (current === 1) { + setOutlet2(outlet); + } else { + setOutlet1(outlet); + } + + timeoutRef.current = setTimeout( + completeTransition, + pageTransitionDurationRef.current, + ); + } + }, [location.pathname, outlet, navigationType]); + + const getOutlet1Class = () => { + if (!outlet1) return ""; + const baseClass = isReversed ? "reverse" : ""; + if (isTransitioning && activeOutlet === 1) + return `exit ${baseClass}`.trim(); + if (isTransitioning && activeOutlet === 2) + return `enter ${baseClass}`.trim(); + if (activeOutlet === 1) return "visible"; + return ""; + }; + + const getOutlet2Class = () => { + if (!outlet2) return ""; + const baseClass = isReversed ? "reverse" : ""; + if (isTransitioning && activeOutlet === 2) + return `exit ${baseClass}`.trim(); + if (isTransitioning && activeOutlet === 1) + return `enter ${baseClass}`.trim(); + if (activeOutlet === 2) return "visible"; + return ""; + }; + + return ( +
+ {outlet1 && ( +
+ {outlet1} +
+ )} + {outlet2 && ( +
+ {outlet2} +
+ )} +
+ ); +} + +export default AnimatedOutlet; diff --git a/packages/client/src/components/AnimatedText.css b/packages/client/src/components/AnimatedText.css new file mode 100644 index 0000000..452ea66 --- /dev/null +++ b/packages/client/src/components/AnimatedText.css @@ -0,0 +1,46 @@ +.animated-text-container { + position: relative; + overflow: visible; +} + +.animated-text { + white-space: nowrap; +} + +.animated-text-current { + opacity: 1; + transition: opacity 0s; + transform: translateY(0); + width: max-content; +} + +.animated-text-hidden { + opacity: 0; +} + +.animated-text-exiting { + position: absolute; + top: 0; + left: 0; + width: 100%; + opacity: 1; + transform: translateY(0); +} + +.animated-text-exiting-visible { + opacity: 0; + transform: translateY(-20px); +} + +.animated-text-entering { + opacity: 0; + position: absolute; + top: 0; + left: 0; + transform: translateY(20px); +} + +.animated-text-entering-visible { + opacity: 1; + transform: translateY(0); +} diff --git a/packages/client/src/components/AnimatedText.jsx b/packages/client/src/components/AnimatedText.jsx new file mode 100644 index 0000000..eca1769 --- /dev/null +++ b/packages/client/src/components/AnimatedText.jsx @@ -0,0 +1,198 @@ +import React, { useState, useEffect, useRef } from "react"; +import "./AnimatedText.css"; + +function AnimatedText({ + text, + transitionDuration = 500, + transitionDelay = 0, + style = {}, + animateWidth = true, + animateEnterenceExitWidth = true, +}) { + const [enteringText, setEnteringText] = useState(""); + const [currentText, setCurrentText] = useState(text); + const [exitingText, setExitingText] = useState(""); + const [isEntering, setIsEntering] = useState(false); + const [isExiting, setIsExiting] = useState(false); + const delay = 10; + const [isTransitioning, setIsTransitioning] = useState(false); + const isTransitioningRef = useRef(false); + const prevTextRef = useRef(text); + const currentTextRef = useRef(currentText); + const textRef = useRef(text); + const timeoutRefs = useRef([]); + const enteringTextRef = useRef(null); + const [textWidth, setTextWidth] = useState(0); + const initialLoad = useRef(true); + + // Helper function to clear all timeouts + const clearAllTimeouts = () => { + timeoutRefs.current.forEach((timeoutId) => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }); + timeoutRefs.current = []; + }; + + useEffect(() => { + const prevText = prevTextRef.current; + + // Check if text changed + const textChanged = prevText != text; + + // Only trigger transition if text actually changed + if (textChanged) { + // Cancel any in-progress transition + clearAllTimeouts(); + + // Reset transition states immediately + setIsExiting(false); + setIsEntering(false); + setExitingText(""); + setEnteringText(""); + + // Only apply entrance delay when transitioning from "" to text + const entranceOnly = prevText === "" && text !== ""; + const effectiveDelay = entranceOnly ? transitionDelay : 0; + + // Get the actual current text (from ref to avoid stale state) + const actualCurrentText = currentTextRef.current || prevText; + + // Set exiting text to current text (starts visible) + setExitingText(actualCurrentText); + + // Update current text immediately to the new value + setCurrentText(text); + currentTextRef.current = text; + + // Set entering text to new text + setEnteringText(text); + + setIsTransitioning(true); + isTransitioningRef.current = true; + + // Start exit animation (no delay - exit is immediate) + const exitTimeout = setTimeout(() => { + setIsExiting(true); + }, delay); + timeoutRefs.current.push(exitTimeout); + + // Start enter animation (with delay only for entrance: "" to text) + const enterTimeout = setTimeout(() => { + setIsEntering(true); + }, delay + effectiveDelay); + timeoutRefs.current.push(enterTimeout); + + // Clear exiting text after transition completes + const cleanupTimeout = setTimeout( + () => { + // When animateEnterenceExitWidth is false, set width after effect has finished (before clearing ref) + if (!animateEnterenceExitWidth && enteringTextRef.current) { + setTextWidth(enteringTextRef.current.clientWidth); + } + setIsExiting(false); + setIsEntering(false); + setExitingText(""); + setEnteringText(""); + setIsTransitioning(false); + isTransitioningRef.current = false; + }, + transitionDuration + effectiveDelay + delay, + ); + timeoutRefs.current.push(cleanupTimeout); + + prevTextRef.current = text; + } else { + // Update text without transition for updates without change + currentTextRef.current = text; + setEnteringText(""); + setExitingText(""); + setIsEntering(false); + setIsExiting(false); + setIsTransitioning(false); + isTransitioningRef.current = false; + setCurrentText(text); + } + + // Cleanup function + return () => { + clearAllTimeouts(); + }; + }, [text, transitionDuration, transitionDelay, animateEnterenceExitWidth]); + + useEffect(() => { + if (enteringTextRef.current) { + if (animateWidth && isTransitioning) { + setTextWidth(enteringTextRef.current.clientWidth); + } + } + if ( + (!animateWidth || !animateEnterenceExitWidth) && + !isTransitioning && + textRef.current + ) { + setTextWidth(textRef.current.clientWidth); + } + if (initialLoad.current == true && textRef.current) { + initialLoad.current = false; + setTextWidth(textRef.current.clientWidth); + } + }, [enteringText, animateWidth, animateEnterenceExitWidth, isTransitioning]); + + // Keep currentTextRef in sync + useEffect(() => { + currentTextRef.current = currentText; + }, [currentText]); + + const transitionStyle = { + transition: `opacity ${transitionDuration}ms ease, transform ${transitionDuration}ms ease`, + }; + + return ( +
+
+ {currentText} +
+ {exitingText && ( +
+ {exitingText} +
+ )} + + {enteringText && ( +
+ {enteringText} +
+ )} +
+ ); +} + +export default AnimatedText; diff --git a/packages/client/src/components/Button.css b/packages/client/src/components/Button.css new file mode 100644 index 0000000..0f40dbf --- /dev/null +++ b/packages/client/src/components/Button.css @@ -0,0 +1,125 @@ +/* Matches tombutcher-ui .tb-button (components.css) — uses app :root --text / --bg */ + +.btn { + appearance: none; + -webkit-appearance: none; + box-sizing: border-box; + padding: 8px 14px; + background-color: transparent; + color: var(--text); + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 18px; + transition: + background-color 0.3s ease, + color 0.3s ease, + fill 0.3s ease, + stroke 0.3s ease, + transform 0.5s ease, + border-color 0.3s ease, + filter 0.3s ease; + display: inline-flex; + align-items: center; + justify-content: center; + margin: 0; + line-height: 1; + min-height: 30px; + font-weight: 500; + font-family: inherit; + font-size: 0.9rem; + position: relative; + transform-origin: center center; + transform: scale(1); + width: max-content; + cursor: pointer; + text-decoration: none; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn:not(:disabled):hover { + background-color: var(--text); + color: var(--bg); + transform: scale(1.02); +} + +.btn:not(:disabled):active { + background-color: var(--text); + color: var(--bg); + transform: scale(0.975); +} + +.btn > svg { + fill: var(--text); + stroke: var(--text); + height: 16px; + width: auto; + margin-right: 8px; + flex-shrink: 0; + transition: + fill 0.3s ease, + stroke 0.3s ease; +} + +.btn:not(:disabled):hover > svg { + fill: var(--bg); + stroke: var(--bg); +} + +/* Filled CTA — emphasis while keeping pill + motion language */ +.btn--primary { + background-color: var(--accent); + color: var(--on-accent); + border: var(--border-ui-width) solid transparent; + font-weight: 600; +} + +.btn--primary:not(:disabled):hover { + filter: brightness(1.06); + background-color: var(--accent); + color: var(--on-accent); +} + +.btn--danger:not(:disabled):hover { + background-color: var(--danger); + color: var(--on-warn); + border: var(--border-ui-width) solid transparent; +} + +.btn--primary:not(:disabled):active { + filter: brightness(0.98); + transform: scale(0.975); +} + +.btn--primary > svg { + fill: var(--on-accent); + stroke: var(--on-accent); +} + +.btn--primary:not(:disabled):hover > svg, +.btn--primary:not(:disabled):active > svg { + fill: var(--on-accent); + stroke: var(--on-accent); +} + +.btn--primary:disabled { + filter: none; +} + +/* Lighter outline; same hover invert as default */ +.btn--ghost { + border-color: color-mix(in srgb, var(--text) 8%, transparent); +} + +.btn--small { + padding: 6px 10px; + min-height: 26px; + font-size: 0.8rem; +} + +.btn--small > svg { + height: 14px; + margin-right: 6px; +} diff --git a/packages/client/src/components/Button.jsx b/packages/client/src/components/Button.jsx new file mode 100644 index 0000000..b3f6b18 --- /dev/null +++ b/packages/client/src/components/Button.jsx @@ -0,0 +1,47 @@ +import "./Button.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * @param {object} props + * @param {'default' | 'primary' | 'ghost'} [props.variant] + * @param {'middle' | 'small'} [props.size] + * @param {string} [props.href] — if set, renders `` + * @param {string} [props.className] + * @param {import('react').ReactNode} props.children + */ +export function Button({ + variant = "default", + size = "middle", + href, + className, + type = "button", + danger = false, + children, + ...rest +}) { + const classes = cx( + "btn", + variant === "primary" && "btn--primary", + variant === "ghost" && "btn--ghost", + size === "small" && "btn--small", + danger && "btn--danger", + className, + ); + + if (href) { + return ( + + {children} + + ); + } + + return ( + + ); +} diff --git a/packages/client/src/components/DateTimeInput.css b/packages/client/src/components/DateTimeInput.css new file mode 100644 index 0000000..2a1afe1 --- /dev/null +++ b/packages/client/src/components/DateTimeInput.css @@ -0,0 +1,184 @@ +.date-time-input { + display: block; + width: 100%; + min-width: 0; +} + +.date-time-input .popover-wrapper { + display: block; + width: 100%; +} + +.date-time-input__trigger { + cursor: pointer; + width: 100%; +} + +.date-time-input__trigger--readonly { + cursor: default; +} + +.date-time-input__field { + cursor: inherit; +} + +.date-time-input__icon { + display: inline-flex; + align-items: center; + color: var(--muted); + line-height: 0; + pointer-events: none; +} + +.popover-root.date-time-input__popover { + min-width: 280px; + max-width: min(320px, calc(100vw - 24px)); +} + +.date-time-input__panel { + padding: 4px 2px 2px; + min-width: 0; +} + +.date-time-input__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 10px; + padding: 0 4px; +} + +.date-time-input__month { + font-size: 0.9rem; + font-weight: 600; + color: var(--text); + flex: 1; + text-align: center; +} + +.date-time-input__nav { + flex: 0 0 auto; +} + +.date-time-input__weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; + margin-bottom: 4px; + padding: 0 2px; +} + +.date-time-input__weekday { + text-align: center; + font-size: 0.7rem; + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.02em; +} + +.date-time-input__grid { + display: flex; + flex-direction: column; + gap: 2px; + margin-bottom: 12px; +} + +.date-time-input__row { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; +} + +.date-time-input__day { + margin: 0; + padding: 0; + min-height: 32px; + border: none; + border-radius: 8px; + background: transparent; + color: var(--text); + font-size: 0.85rem; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: + background-color 0.12s ease, + color 0.12s ease; +} + +.date-time-input__day:hover:not(:disabled):not( + .date-time-input__day--disabled + ) { + background: color-mix(in srgb, var(--accent) 14%, transparent); +} + +.date-time-input__day--outside { + color: color-mix(in srgb, var(--muted) 85%, var(--text)); + opacity: 0.55; +} + +.date-time-input__day--today { + box-shadow: inset 0 0 0 2px var(--accent); +} + +.date-time-input__day--selected { + background: var(--accent); + color: var(--bg); +} + +.date-time-input__day--selected:hover:not(:disabled) { + background: color-mix(in srgb, var(--accent) 88%, var(--text)); + color: var(--bg); +} + +.date-time-input__day--disabled { + opacity: 0.35; + cursor: not-allowed; +} + +.date-time-input__time-row { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 6px 4px; + border-top: 1px solid var(--border-ui-color); +} + +.date-time-input__time-label { + font-size: 0.8rem; + font-weight: 600; + color: var(--muted); + white-space: nowrap; +} + +.date-time-input__time { + flex: 1 1 auto; + min-width: 0; + box-sizing: border-box; + font-family: inherit; + font-size: 0.9rem; + font-weight: 500; + color: var(--text); + background: var(--bg); + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 12px; + padding: 6px 10px; + outline: none; +} + +.date-time-input__time:focus-visible { + border-color: var(--accent); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); +} + +.date-time-input__time:disabled { + opacity: 0.55; + cursor: not-allowed; +} + +.date-time-input__footer { + display: flex; + justify-content: flex-start; +} diff --git a/packages/client/src/components/DateTimeInput.jsx b/packages/client/src/components/DateTimeInput.jsx new file mode 100644 index 0000000..465d5db --- /dev/null +++ b/packages/client/src/components/DateTimeInput.jsx @@ -0,0 +1,406 @@ +import { + forwardRef, + useCallback, + useEffect, + useId, + useMemo, + useRef, + useState, +} from "react"; +import dayjs from "dayjs"; +import { + IoCalendarOutline, + IoChevronBack, + IoChevronForward, + IoCloseCircle, +} from "react-icons/io5"; +import { Button } from "./Button.jsx"; +import { IconButton } from "./IconButton.jsx"; +import { Popover } from "./Popover.jsx"; +import "./Input.css"; +import "./DateTimeInput.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +const sizeClass = { + small: "sm", + middle: "md", + large: "lg", +}; + +/** Day.js has no `dayjs.invalid()` (that is Moment.js API). */ +const INVALID_DAYJS = dayjs(new Date(NaN)); + +/** + * @param {unknown} v + * @returns {import('dayjs').Dayjs} + */ +function toDayjs(v) { + if (v == null || v === "") return INVALID_DAYJS; + const d = dayjs(v); + return d.isValid() ? d : INVALID_DAYJS; +} + +/** + * Ant Design–like datetime field: Input-styled trigger, calendar + time in Popover. + * + * @param {object} props + * @param {Date | string | number | null} [props.value] + * @param {Date | string | number | null} [props.defaultValue] + * @param {(date: Date | null) => void} [props.onChange] + * @param {string} [props.format='YYYY-MM-DD HH:mm'] + * @param {string} [props.placeholder] + * @param {boolean} [props.disabled] + * @param {boolean} [props.readOnly] + * @param {boolean} [props.allowClear] + * @param {boolean} [props.bordered=true] + * @param {'large' | 'middle' | 'small'} [props.size='middle'] + * @param {'' | 'error' | 'warning'} [props.status] + * @param {(d: import('dayjs').Dayjs) => boolean} [props.disabledDate] + * @param {boolean} [props.open] + * @param {(open: boolean) => void} [props.onOpenChange] + * @param {string} [props.placement='bottomLeft'] + * @param {string} [props.className] + * @param {import('react').CSSProperties} [props.style] + * @param {string} [props.id] + * @param {string} [props.name] + * @param {string} [props.inputMode] + */ +export const DateTimeInput = forwardRef(function DateTimeInput( + { + value, + defaultValue, + onChange, + format = "YYYY-MM-DD HH:mm", + placeholder = "Select date and time", + disabled = false, + readOnly = false, + allowClear = false, + bordered = true, + size = "middle", + status, + disabledDate, + open: openProp, + onOpenChange, + placement = "bottomLeft", + className, + style, + id, + name, + showTime = true, + inputMode = "none", + ...rest + }, + ref, +) { + const uid = useId(); + const timeInputId = id ? `${id}-time` : `date-time-input-time-${uid}`; + const sz = sizeClass[size] ?? "md"; + const innerRef = useRef(null); + const setRefs = useCallback( + (node) => { + innerRef.current = node; + if (typeof ref === "function") ref(node); + else if (ref) ref.current = node; + }, + [ref], + ); + + const isControlled = value !== undefined; + const [innerValue, setInnerValue] = useState(() => + defaultValue != null ? toDayjs(defaultValue).toDate() : null, + ); + + useEffect(() => { + if (!isControlled && defaultValue !== undefined) { + const d = toDayjs(defaultValue); + setInnerValue(d.isValid() ? d.toDate() : null); + } + }, [defaultValue, isControlled]); + + const resolvedDate = useMemo(() => { + const raw = isControlled ? value : innerValue; + const d = toDayjs(raw); + return d.isValid() ? d : null; + }, [isControlled, value, innerValue]); + + const [uncontrolledOpen, setUncontrolledOpen] = useState(false); + const isOpenControlled = openProp !== undefined; + const open = isOpenControlled ? openProp : uncontrolledOpen; + + const setOpen = useCallback( + (next) => { + if (!isOpenControlled) setUncontrolledOpen(next); + onOpenChange?.(next); + }, + [isOpenControlled, onOpenChange], + ); + + const [viewMonth, setViewMonth] = useState(() => + (resolvedDate ?? dayjs()).startOf("month"), + ); + const [draft, setDraft] = useState(() => resolvedDate ?? dayjs()); + + useEffect(() => { + if (!open) return; + const base = resolvedDate ?? dayjs(); + setDraft(base); + setViewMonth(base.startOf("month")); + }, [open, resolvedDate]); + + const emitChange = useCallback( + (nextDayjs) => { + const next = nextDayjs.isValid() ? nextDayjs.toDate() : null; + if (!isControlled) setInnerValue(next); + onChange?.(next); + }, + [isControlled, onChange], + ); + + const handleClear = (e) => { + e.preventDefault(); + e.stopPropagation(); + if (disabled || readOnly) return; + emitChange(INVALID_DAYJS); + setOpen(false); + innerRef.current?.focus?.(); + }; + + const weeks = useMemo(() => { + const start = viewMonth.startOf("month").startOf("week"); + const rows = []; + let cursor = start; + for (let w = 0; w < 6; w++) { + const row = []; + for (let d = 0; d < 7; d++) { + row.push(cursor); + cursor = cursor.add(1, "day"); + } + rows.push(row); + } + return rows; + }, [viewMonth]); + + const weekdayLabels = useMemo(() => { + const start = dayjs().startOf("week"); + return Array.from({ length: 7 }, (_, i) => + start.add(i, "day").format("dd"), + ); + }, []); + + const displayText = resolvedDate ? resolvedDate.format(format) : ""; + + const timeStr = draft.isValid() ? draft.format("HH:mm") : "00:00"; + + const statusMod = + status === "error" ? "error" : status === "warning" ? "warning" : null; + + const showClear = + allowClear && + !disabled && + !readOnly && + resolvedDate != null && + resolvedDate.isValid(); + + const pickerDisabled = disabled || readOnly; + + const panel = ( +
e.preventDefault()} + > +
+ setViewMonth((m) => m.subtract(1, "month"))} + > + + + + {viewMonth.format("MMMM YYYY")} + + setViewMonth((m) => m.add(1, "month"))} + > + + +
+
+ {weekdayLabels.map((l) => ( + + {l} + + ))} +
+
+ {weeks.map((row, ri) => ( +
+ {row.map((cell) => { + const inMonth = cell.isSame(viewMonth, "month"); + const selected = draft.isValid() && cell.isSame(draft, "day"); + const isToday = cell.isSame(dayjs(), "day"); + const cellDisabled = Boolean(disabledDate?.(cell)); + return ( + + ); + })} +
+ ))} +
+ {showTime && ( +
+ + + { + const v = e.target.value; + if (!v) return; + const [hh, mm] = v.split(":").map((x) => parseInt(x, 10)); + if (!Number.isFinite(hh) || !Number.isFinite(mm)) return; + const base = draft.isValid() ? draft : dayjs(); + const next = base.hour(hh).minute(mm).second(0); + setDraft(next); + emitChange(next); + }} + /> +
+ )} +
+ +
+
+ ); + + const trigger = ( + + { + if (pickerDisabled) return; + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + setOpen(true); + } + }} + {...rest} + /> + + {showClear ? ( + + ) : null} + + + + + + ); + + return ( +
+ + {trigger} + +
+ ); +}); + +DateTimeInput.displayName = "DateTimeInput"; diff --git a/packages/client/src/components/Drawer.css b/packages/client/src/components/Drawer.css new file mode 100644 index 0000000..4fcb0bf --- /dev/null +++ b/packages/client/src/components/Drawer.css @@ -0,0 +1,458 @@ +/* Drawer panel + mask (Ant Design–style). Main content scale lives on .app-main. */ + +.drawer-root { + position: fixed; + inset: 0; + z-index: 1000; + pointer-events: none; + width: 100vw; + height: 100dvh; +} + +.drawer-root.drawer-root--active { + pointer-events: auto; +} + +.drawer-mask { + position: absolute; + inset: 0; + background: color-mix(in srgb, #000 45%, transparent); + opacity: 0; + transition: opacity 0.5s ease; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.drawer-root.drawer-root--visible .drawer-mask { + opacity: 1; +} + +.drawer-wrap { + position: absolute; + display: flex; + pointer-events: none; +} + +.drawer-wrap--right { + inset: 0 0 0 auto; + flex-direction: row; + justify-content: flex-end; +} + +.drawer-wrap--left { + inset: 0 auto 0 0; + flex-direction: row; + justify-content: flex-start; +} + +.drawer-wrap--top { + inset: 0 0 auto 0; + flex-direction: column; + justify-content: flex-start; +} + +.drawer-wrap--bottom { + inset: auto 0 0 0; + flex-direction: column; + justify-content: flex-end; +} + +.drawer-panel--has-header-backdrop { + position: relative; +} + +.drawer-header-backdrop { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + box-sizing: border-box; + pointer-events: none; + transition: height 0.35s cubic-bezier(0.33, 1, 0.68, 1); +} + +.drawer-header-backdrop-inner { + width: 100%; + height: 100%; + z-index: 1; +} + +.drawer-header-backdrop-blur { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 2; + filter: blur(6px); + transform: scale(1.05); + transition: opacity 0.35s cubic-bezier(0.33, 1, 0.68, 1); +} + +.drawer-panel { + pointer-events: auto; + display: flex; + flex-direction: column; + max-width: 100%; + max-height: 100%; + background: var(--surface); + color: var(--text); + box-shadow: -12px 0 40px color-mix(in srgb, #000 35%, transparent); + transition: transform 0.35s cubic-bezier(0.33, 1, 0.68, 1); +} + +.drawer-wrap--right .drawer-panel { + height: 100%; + border-right: none; + transform: translateX(100%); +} + +.drawer-wrap--left .drawer-panel { + height: 100%; + border-left: none; + box-shadow: 12px 0 40px color-mix(in srgb, #000 35%, transparent); + transform: translateX(-100%); +} + +.drawer-wrap--top .drawer-panel { + width: 100%; + border-top: none; + box-shadow: 0 12px 40px color-mix(in srgb, #000 35%, transparent); + transform: translateY(-100%); +} + +.drawer-wrap--bottom .drawer-panel { + width: 100%; + border-bottom: none; + box-shadow: 0 -12px 40px color-mix(in srgb, #000 35%, transparent); + transform: translateY(100%); +} + +.drawer-root.drawer-root--visible .drawer-wrap--right .drawer-panel, +.drawer-root.drawer-root--visible .drawer-wrap--left .drawer-panel, +.drawer-root.drawer-root--visible .drawer-wrap--top .drawer-panel, +.drawer-root.drawer-root--visible .drawer-wrap--bottom .drawer-panel { + transform: translate(0, 0); +} + +.drawer-header { + flex-shrink: 0; + display: flex; + top: 0; + left: 0; + right: 0; + position: absolute; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + padding: 4vw 4vw 0; + min-height: 52px; + z-index: 100; +} + +.drawer-panel--has-header-backdrop .drawer-header { + padding-bottom: 4vw; +} + +.drawer-panel--mobile .drawer-header { + padding: var(--app-main-padding-left) var(--app-main-padding-right) 0; +} + +.drawer-panel--has-header-backdrop.drawer-panel--mobile .drawer-header { + padding-bottom: var(--app-main-padding-left); +} + +.drawer-panel--has-header-backdrop .drawer-header .drawer-title, +.drawer-panel--has-header-backdrop .drawer-header .drawer-close { + color: #ffffff; + text-shadow: none; +} + +.drawer-footer { + flex-shrink: 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; + display: flex; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; + gap: 0.75rem; + padding: 0 4vw max(4vw, env(safe-area-inset-bottom, 0px)); + min-height: 52px; + z-index: 100; + box-sizing: border-box; +} + +.drawer-panel--mobile .drawer-footer { + padding-left: var(--app-main-padding-left); + padding-right: var(--app-main-padding-right); + padding-bottom: var(--app-main-padding-left); +} + +.drawer-title { + margin: 0; + font-size: 28px; + line-height: 1; + font-family: "Libre Baskerville", serif; + text-shadow: 0 0 20px var(--surface); + font-weight: 700; + letter-spacing: -0.02em; + flex: 1; + min-width: 0; +} + +.drawer-close { + appearance: none; + -webkit-appearance: none; + margin: 0; + padding: 0.35rem; + line-height: 1; + border: none; + border-radius: 10px; + background: transparent; + color: var(--text); + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + transition: + background-color 0.2s ease, + color 0.2s ease; +} + +.drawer-close:hover { + background: var(--link-hover); + color: var(--text); +} + +.drawer-close svg { + width: 24px; + height: 24px; +} + +.drawer-body { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; + position: relative; + overflow: hidden; + padding: 0; +} + +.drawer-scroll-wrapper { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; + position: relative; +} + +.drawer-scroll-top-gradient { + position: absolute; + inset: 0; + top: -24px; + left: 0; + right: 0; + z-index: 2; + opacity: 1; + pointer-events: none; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255) 50%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255) 50%, + rgb(255 255 255 / 0%) 100% + ); +} + +.drawer-scroll-top-gradient--has-header-backdrop { + mask-image: linear-gradient( + to bottom, + rgb(255 255 255 / 0%) 0%, + rgb(255 255 255) 65%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + rgb(255 255 255 / 0%) 0%, + rgb(255 255 255) 65%, + rgb(255 255 255 / 0%) 100% + ); + transition: top 0.35s cubic-bezier(0.33, 1, 0.68, 1); +} + +.drawer-scroll-backdrop-header-top-gradient { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 2; + opacity: 1; + pointer-events: none; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255 / 0%) 100% + ); +} + +.drawer-scroll-bottom-gradient { + position: absolute; + top: unset; + bottom: -30px; + left: 0; + right: 0; + z-index: 2; + opacity: 1; + pointer-events: none; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + mask-image: linear-gradient( + to top, + rgb(255 255 255) 0%, + rgb(255 255 255) 25%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to top, + rgb(255 255 255) 0%, + rgb(255 255 255) 25%, + rgb(255 255 255 / 0%) 100% + ); +} + +.drawer-scroll-vscroll { + flex: 1; + min-height: 0; + width: 100%; + max-height: none; + height: auto; + margin: 0; + padding: 0; + mask: linear-gradient( + 180deg, + transparent 0%, + black var(--drawer-scroll-top-gradient-height, 50px), + black var(--drawer-scroll-bottom-gradient-height, 50px), + transparent 100% + ); + -webkit-mask: linear-gradient( + 180deg, + transparent 0%, + black var(--drawer-scroll-top-gradient-height, 50px), + black var(--drawer-scroll-bottom-gradient-height, 50px), + transparent 100% + ); +} + +.drawer-scroll-vscroll .simplebar-vertical { + margin-left: 0.35rem; + width: var(--border-ui-width); + border-radius: 18px; + overflow: hidden; + opacity: 0; + transition: opacity 0.3s ease; + margin-top: var(--drawer-scroll-simplebar-track-margin-top, 0); + margin-bottom: var(--drawer-scroll-simplebar-track-margin-bottom, 0); + margin-right: calc(4vw / 2); +} + +.drawer-scroll-vscroll::before { + content: ""; + position: absolute; + right: 0; + top: 0; + bottom: 0; + z-index: 1; + opacity: 0; + transition: opacity 0.3s ease; + width: var(--border-ui-width); + border-radius: 18px; +} + +.drawer-scroll-vscroll.simplebar-scrolling::before { + opacity: 1; +} + +.drawer-scroll-vscroll.simplebar-scrolling .simplebar-vertical { + opacity: 1; +} + +.drawer-scroll-content { + display: flex; + flex-direction: column; + gap: 1.25rem; + box-sizing: border-box; + padding: 4vw; + min-height: 100%; + margin: 0; +} + +.drawer-scroll-start { + scroll-snap-align: start; + scroll-snap-stop: normal; + display: block; +} + +.drawer-scroll-vscroll .simplebar-scrollbar::before { + top: 0; + bottom: 0; + left: 0; + right: 0; + background: var(--border-ui-color); + border-radius: 18px; +} + +.drawer-scroll-vscroll .simplebar-scrollbar.simplebar-visible, +.drawer-scroll-vscroll .simplebar-scrollbar.simplebar-visible::before { + opacity: 1; +} + +.drawer-panel--mobile .drawer-scroll-content { + padding: var(--app-main-padding-left) var(--app-main-padding-right); +} + +.drawer-panel--mobile .drawer-scroll-vscroll .simplebar-vertical { + margin-right: calc(var(--app-main-padding-right) / 2); +} + +.drawer-body--flush .drawer-scroll-content { + padding: 0; + gap: 0; +} + +.app-shell-inner.app-shell--drawer-open { + transform: scale(0.94); +} + +.drawer-panel.drawer-panel--has-header-backdrop .drawer-footer { + bottom: unset; + color: #ffffff; + transition: + top 0.35s cubic-bezier(0.33, 1, 0.68, 1), + opacity 0.2s ease; +} diff --git a/packages/client/src/components/Drawer.jsx b/packages/client/src/components/Drawer.jsx new file mode 100644 index 0000000..3175d07 --- /dev/null +++ b/packages/client/src/components/Drawer.jsx @@ -0,0 +1,508 @@ +import { + useCallback, + useEffect, + useId, + useLayoutEffect, + useRef, + useState, +} from "react"; +import { createPortal } from "react-dom"; +import { IoClose } from "react-icons/io5"; +import SimpleBar from "simplebar-react"; +import "simplebar-react/dist/simplebar.min.css"; +import { useTheme } from "../contexts/ThemeContext.jsx"; +import "./Drawer.css"; + +const DRAWER_SCROLL_GRADIENT_HEIGHT = 40; +const SCROLL_BACKDROP_HEIGHT_DEBOUNCE_MS = 300; + +/** @type {number} */ +let appMainDrawerDepth = 0; +function syncAppMainDrawerClass() { + const shell = document.querySelector(".app-shell-inner"); + if (!shell) return; + shell.classList.toggle("app-shell--drawer-open", appMainDrawerDepth > 0); +} + +function pushAppMainDrawer() { + appMainDrawerDepth += 1; + syncAppMainDrawerClass(); +} + +function popAppMainDrawer() { + appMainDrawerDepth = Math.max(0, appMainDrawerDepth - 1); + syncAppMainDrawerClass(); +} + +const TRANSITION_MS = 350; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * Ant Design–style drawer: slides from an edge with a mask. While open, scales `.app-main`. + * + * @param {object} props + * @param {boolean} props.open + * @param {() => void} props.onClose + * @param {import('react').ReactNode} [props.title] + * @param {'left' | 'right' | 'top' | 'bottom'} [props.placement] + * @param {number | string} [props.width] — right/left drawer width + * @param {number | string} [props.height] — top/bottom drawer height + * @param {string} [props.className] — on panel + * @param {boolean} [props.maskClosable] + * @param {boolean} [props.closable] + * @param {boolean} [props.destroyOnClose] + * @param {import('react').ReactNode} [props.footer] — pinned below scroll, like header above + * @param {import('react').ReactNode} [props.headerBackdrop] — behind title/close, height `headerBackdropHeight`, centered; scroll content gets `padding-top` of that height + * @param {number | string} [props.headerBackdropHeight] + * @param {import('react').ReactNode} props.children + */ +export function Drawer({ + open, + onClose, + title, + placement = "right", + width = 378, + height = 256, + className, + maskClosable = true, + closable = true, + destroyOnClose = false, + footer, + headerBackdrop = undefined, + showHeaderBackdrop = false, + headerBackdropHeight = 120, + children, +}) { + const { isMobile } = useTheme(); + const effectivePlacement = isMobile ? "bottom" : placement; + const [mounted, setMounted] = useState(open); + const [visible, setVisible] = useState(open); + const closeTimerRef = useRef(null); + const scrollContentRef = useRef(null); + const animatedRevealTimeoutsRef = useRef([]); + const headerMeasureRef = useRef(null); + const footerMeasureRef = useRef(null); + const [headerClientHeight, setHeaderClientHeight] = useState(0); + const [footerClientHeight, setFooterClientHeight] = useState(0); + const numericBackdrop = typeof headerBackdropHeight === "number"; + const [scrolledBackdropHeaderHeight, setScrolledBackdropHeaderHeight] = + useState(() => + typeof headerBackdropHeight === "number" + ? headerBackdropHeight + : Number(headerBackdropHeight) || 120, + ); + /** Footer opacity vs scroll: 1 at top → 0 over the same range as backdrop height collapse. */ + const [footerScrollOpacity, setFooterScrollOpacity] = useState(1); + + const titleId = useId(); + + useEffect(() => { + if (!numericBackdrop) return; + setScrolledBackdropHeaderHeight(headerBackdropHeight); + }, [headerBackdropHeight, numericBackdrop]); + + useEffect(() => { + if (!visible || !showHeaderBackdrop) return; + let active = true; + let removeListener = () => {}; + + const maxH = headerBackdropHeight; + const minH = headerClientHeight; + const scrollRange = + minH > 0 && typeof maxH === "number" ? Math.max(0, maxH - minH) : 0; + + const attach = () => { + const content = scrollContentRef.current; + const wrapper = content?.closest(".simplebar-content-wrapper"); + if (!wrapper || !active) return; + + let scrollDebounceTimer = 0; + /** @type {number | null} */ + let queuedScrollTop = null; + + /** Apply header backdrop height and footer opacity from scroll position `y`. */ + const flushScrollDerivedUi = (y) => { + if (!numericBackdrop || scrollRange <= 0) { + setFooterScrollOpacity(1); + } else { + const t = Math.min(1, Math.max(0, y / scrollRange)); + setFooterScrollOpacity(1 - t); + } + if (numericBackdrop) { + const next = Math.max(minH, maxH - Math.min(y, scrollRange)); + setScrolledBackdropHeaderHeight(next); + } + }; + + const scheduleScrollDebounceTimeout = () => { + scrollDebounceTimer = window.setTimeout(() => { + scrollDebounceTimer = 0; + if (queuedScrollTop != null) { + const yq = queuedScrollTop; + queuedScrollTop = null; + flushScrollDerivedUi(yq); + scheduleScrollDebounceTimeout(); + } + }, SCROLL_BACKDROP_HEIGHT_DEBOUNCE_MS); + }; + + const onScroll = () => { + const y = wrapper.scrollTop; + if (!numericBackdrop) { + flushScrollDerivedUi(y); + return; + } + if (scrollDebounceTimer === 0) { + flushScrollDerivedUi(y); + scheduleScrollDebounceTimeout(); + } else { + queuedScrollTop = y; + } + }; + + flushScrollDerivedUi(wrapper.scrollTop); + wrapper.addEventListener("scroll", onScroll, { passive: true }); + removeListener = () => { + window.clearTimeout(scrollDebounceTimer); + scrollDebounceTimer = 0; + queuedScrollTop = null; + wrapper.removeEventListener("scroll", onScroll); + }; + }; + + let innerRaf = 0; + const outerRaf = requestAnimationFrame(() => { + innerRaf = requestAnimationFrame(attach); + }); + + return () => { + active = false; + cancelAnimationFrame(outerRaf); + cancelAnimationFrame(innerRaf); + removeListener(); + }; + }, [ + visible, + showHeaderBackdrop, + numericBackdrop, + headerBackdropHeight, + headerClientHeight, + children, + ]); + + useEffect(() => { + if (!visible || !showHeaderBackdrop) setFooterScrollOpacity(1); + }, [visible, showHeaderBackdrop]); + + const measureHeaderFooter = useCallback(() => { + setHeaderClientHeight(headerMeasureRef.current?.clientHeight ?? 0); + setFooterClientHeight(footerMeasureRef.current?.clientHeight ?? 0); + }, []); + + useLayoutEffect(() => { + if (!visible) return; + measureHeaderFooter(); + const headerEl = headerMeasureRef.current; + const footerEl = footerMeasureRef.current; + const ro = new ResizeObserver(() => measureHeaderFooter()); + if (headerEl) ro.observe(headerEl); + if (footerEl) ro.observe(footerEl); + return () => ro.disconnect(); + }, [visible, title, closable, footer != null, measureHeaderFooter]); + + const clearCloseTimer = useCallback(() => { + if (closeTimerRef.current != null) { + clearTimeout(closeTimerRef.current); + closeTimerRef.current = null; + } + }, []); + + useEffect(() => { + if (open) { + clearCloseTimer(); + setMounted(true); + const id = requestAnimationFrame(() => + setTimeout(() => setVisible(true), 10), + ); + return () => cancelAnimationFrame(id); + } + setVisible(false); + if (destroyOnClose) { + closeTimerRef.current = window.setTimeout(() => { + closeTimerRef.current = null; + setMounted(false); + }, TRANSITION_MS); + } + return () => clearCloseTimer(); + }, [open, destroyOnClose, clearCloseTimer]); + + useEffect(() => { + if (!visible) return; + pushAppMainDrawer(); + return () => popAppMainDrawer(); + }, [visible]); + + useEffect(() => { + if (!visible) return; + const prev = document.body.style.backgroundColor; + document.body.style.backgroundColor = "var(--surface)"; + return () => { + document.body.style.backgroundColor = prev; + }; + }, [visible]); + + useEffect(() => { + if (!visible || !onClose) return; + const onKeyDown = (e) => { + if (e.key === "Escape") onClose(); + }; + document.addEventListener("keydown", onKeyDown); + return () => document.removeEventListener("keydown", onKeyDown); + }, [visible, onClose]); + + useEffect(() => { + if (!visible) return; + + const clearAnimatedRevealTimers = () => { + animatedRevealTimeoutsRef.current.forEach((id) => clearTimeout(id)); + animatedRevealTimeoutsRef.current = []; + }; + + const stripVisibleFromAnimated = () => { + const root = scrollContentRef.current; + if (!root) return; + const animated = document.getElementsByClassName("animated"); + for (let i = 0; i < animated.length; i += 1) { + const el = animated[i]; + if (root.contains(el)) el.classList.remove("visible"); + } + }; + + const startId = window.setTimeout(() => { + const root = scrollContentRef.current; + if (!root) return; + const allAnimated = document.getElementsByClassName("animated"); + const inside = []; + for (let i = 0; i < allAnimated.length; i += 1) { + const el = allAnimated[i]; + if (root.contains(el)) inside.push(el); + } + for (let i = 0; i < inside.length; i += 1) { + const el = inside[i]; + el.style.zIndex = inside.length - i; + } + inside.forEach((el, index) => { + const id = window.setTimeout(() => { + el.classList.add("visible"); + }, index * 100); + animatedRevealTimeoutsRef.current.push(id); + }); + }, 10); + + return () => { + clearTimeout(startId); + clearAnimatedRevealTimers(); + stripVisibleFromAnimated(); + }; + }, [visible]); + + const onMaskClick = () => { + if (maskClosable) onClose?.(); + }; + + const w = typeof width === "number" ? `${width}px` : width; + const h = isMobile + ? "95dvh" + : typeof height === "number" + ? `${height}px` + : height; + const panelStyle = + effectivePlacement === "right" || effectivePlacement === "left" + ? { width: w } + : { height: h }; + + const backdropH = + typeof headerBackdropHeight === "number" + ? `${headerBackdropHeight}px` + : headerBackdropHeight; + + const backdropDisplayH = numericBackdrop + ? `${scrolledBackdropHeaderHeight}px` + : backdropH; + + const backdropLayoutPx = + showHeaderBackdrop && numericBackdrop + ? scrolledBackdropHeaderHeight + : typeof headerBackdropHeight === "number" + ? headerBackdropHeight + : parseFloat(String(headerBackdropHeight)) || 0; + + if (!mounted) return null; + + const wrapClass = `drawer-wrap drawer-wrap--${effectivePlacement}`; + const rootClass = cx( + "drawer-root", + visible && "drawer-root--visible", + visible && "drawer-root--active", + ); + + const node = ( +
+
+
+
+ {headerBackdrop != null && showHeaderBackdrop && ( +
+
+ {headerBackdrop} +
+
+ {headerBackdrop} +
+
+ )} + {(title != null || closable) && ( +
+ {title != null ? ( + typeof title === "string" ? ( +

+ {title} +

+ ) : ( +
+ {title} +
+ ) + ) : ( + + )} + {closable && ( + + )} +
+ )} + {showHeaderBackdrop && ( +
+ )} +
+
+
+
+ + +
+ {children} +
+
+
+
+ {footer != null && ( +
+ {footer} +
+ )} +
+
+
+ ); + + return createPortal(node, document.body); +} diff --git a/packages/client/src/components/Flex.css b/packages/client/src/components/Flex.css new file mode 100644 index 0000000..559abd2 --- /dev/null +++ b/packages/client/src/components/Flex.css @@ -0,0 +1,6 @@ +/* Base shell; direction, alignment, and gap come from inline style (Ant Design–style API). */ +.ta-flex { + display: flex; + min-width: 0; + box-sizing: border-box; +} diff --git a/packages/client/src/components/Flex.jsx b/packages/client/src/components/Flex.jsx new file mode 100644 index 0000000..756c8d0 --- /dev/null +++ b/packages/client/src/components/Flex.jsx @@ -0,0 +1,70 @@ +import "./Flex.css"; + +function mapJustifyAlign(value) { + if (value == null || value === "normal" || value === "stretch") return value; + if (value === "start") return "flex-start"; + if (value === "end") return "flex-end"; + return value; +} + +function gapToStyle(gap) { + if (gap == null) return undefined; + if (typeof gap === "number") return `${gap}px`; + if (Array.isArray(gap)) { + const [row, col] = gap; + const a = typeof row === "number" ? `${row}px` : row; + const b = col != null ? (typeof col === "number" ? `${col}px` : col) : a; + return `${a} ${b}`; + } + return gap; +} + +/** + * Flex container similar to Ant Design `Flex`: vertical, justify, align, gap, wrap. + * + * @param {object} props + * @param {boolean} [props.vertical] + * @param {boolean | 'wrap' | 'nowrap' | 'wrap-reverse'} [props.wrap] + * @param {import('react').CSSProperties['justifyContent'] | 'start' | 'end'} [props.justify] + * @param {import('react').CSSProperties['alignItems'] | 'start' | 'end'} [props.align] + * @param {number | string | [number | string, number | string]} [props.gap] + * @param {import('react').CSSProperties['flex']} [props.flex] + * @param {keyof JSX.IntrinsicElements} [props.component] + */ +export function Flex({ + vertical = false, + wrap = "nowrap", + justify = "normal", + align = "normal", + gap, + flex: flexProp, + component: Component = "div", + className = "", + style, + children, + ...rest +}) { + const flexWrap = + wrap === true ? "wrap" : wrap === false ? "nowrap" : wrap; + + const merged = { + flexDirection: vertical ? "column" : "row", + flexWrap, + justifyContent: + justify === "normal" ? undefined : mapJustifyAlign(justify), + alignItems: align === "normal" ? undefined : mapJustifyAlign(align), + gap: gapToStyle(gap), + flex: flexProp, + ...style, + }; + + return ( + + {children} + + ); +} diff --git a/packages/client/src/components/HistoryLineChart.css b/packages/client/src/components/HistoryLineChart.css new file mode 100644 index 0000000..ff45732 --- /dev/null +++ b/packages/client/src/components/HistoryLineChart.css @@ -0,0 +1,125 @@ +.history-line-chart { + display: flex; + flex-direction: column; + gap: 14px; + min-width: 0; +} + +.history-line-chart__toolbar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; +} + +.history-line-chart__period { + min-width: 200px; +} + +.history-line-chart__plot { + position: relative; + width: 100%; + min-width: 0; + /* Let --history-chart-height control size (drawer charts use small heights). */ + min-height: 240px; + height: var(--history-chart-height, 280px); + color: var(--muted); +} + +.history-line-chart__plot .recharts-wrapper { + max-width: 100%; +} + +.history-line-chart__x-tick { + font-family: var(--font); +} + +.history-line-chart__loading-overlay, +.history-line-chart__empty-overlay { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 10px; + pointer-events: none; + font-size: 14px; + color: var(--history-chart-muted, rgba(0, 0, 0, 0.55)); +} + +.history-line-chart__loading-overlay { + background: color-mix( + in srgb, + var(--history-chart-surface, #fff) 72%, + transparent + ); +} + +.history-line-chart__empty-overlay { + background: color-mix( + in srgb, + var(--history-chart-surface, #fff) 55%, + transparent + ); +} + +.history-line-chart__spinner { + width: 28px; + height: 28px; + border: 2px solid color-mix(in srgb, currentColor 22%, transparent); + border-top-color: currentColor; + border-radius: 50%; + animation: history-line-chart-spin 0.7s linear infinite; +} + +.history-line-chart__loading-label { + font-size: 13px; +} + +@keyframes history-line-chart-spin { + to { + transform: rotate(360deg); + } +} + +/* Match prior chart: slightly heavier grid lines */ +.history-line-chart__plot .recharts-cartesian-grid line { + stroke: var(--border); + stroke-width: 2px; +} + +.history-line-chart__state { + display: flex; + align-items: center; + justify-content: center; + min-height: var(--history-chart-height, 280px); + color: var(--history-chart-muted, rgba(0, 0, 0, 0.45)); + font-size: 14px; +} + +.history-line-chart__error { + color: var(--history-chart-error, #cf1322); +} + +/* Recharts portals the tooltip to document body */ +.recharts-tooltip-wrapper .history-line-chart__tooltip-panel { + font-family: var(--font); + font-size: 12px; + font-variant-numeric: tabular-nums; + line-height: 1.35; + color: var(--text); + background: var(--surface); + + border-radius: 8px; + padding: 8px 10px; + box-shadow: 0 10px 28px color-mix(in srgb, #000 45%, transparent); + white-space: nowrap; +} + +.recharts-wrapper, +*:focus-visible, +.recharts-wrapper, +*:focus-within { + outline: none; +} diff --git a/packages/client/src/components/HistoryLineChart.jsx b/packages/client/src/components/HistoryLineChart.jsx new file mode 100644 index 0000000..9a9f07a --- /dev/null +++ b/packages/client/src/components/HistoryLineChart.jsx @@ -0,0 +1,481 @@ +import React, { + useCallback, + useEffect, + useId, + useLayoutEffect, + useMemo, + useRef, + useState, +} from "react"; +import { + Area, + AreaChart, + CartesianGrid, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from "recharts"; +import { useApi } from "../contexts/ApiContext.jsx"; +import { Select } from "./Select.jsx"; +import "./HistoryLineChart.css"; + +function parseHistoryPath(path) { + if (!path || typeof path !== "string") { + throw new Error("historyPath is required"); + } + const parts = path.trim().split(".").filter(Boolean); + if (parts.length < 2) { + throw new Error(`Invalid historyPath: ${path}`); + } + const root = parts[0].toLowerCase(); + + if (root === "patch") { + if (parts.length < 3) { + throw new Error("Expected patch.."); + } + return { + kind: "patch", + patchId: parts[1], + field: parts.slice(2).join("."), + }; + } + + if (root === "power" || root === "powerstate") { + const fieldParts = parts + .slice(1) + .map((p) => (p.toLowerCase() === "batter" ? "battery" : p)); + if (!fieldParts.length) { + throw new Error("Expected power."); + } + return { kind: "power", fieldParts }; + } + + if (root === "watertank") { + const fieldParts = parts.length > 1 ? parts.slice(1) : ["level"]; + return { kind: "waterTank", fieldParts }; + } + + throw new Error(`Unknown history path root: ${parts[0]}`); +} + +/** + * Series styling and tooltip unit by semantic property type (key = classifyHistoryPropertyType). + * Colors: temperature orange, humidity / level blue, default grey. + */ +const PROPERTY_TYPE_MAP = { + temperature: { color: "#ea580c", unit: "\u00B0C" }, + percent: { color: "#3CD3FE", unit: "%" }, + neutral: { color: "#9ca3af", unit: "" }, +}; + +function classifyHistoryPropertyType(path) { + if (!path || typeof path !== "string") return "neutral"; + const p = path.toLowerCase(); + if ( + p.includes("soiltemperature") || + p.includes("temperature") || + p.endsWith(".temp") + ) { + return "temperature"; + } + if ( + p.includes("soilhumidity") || + p.includes("humidity") || + p.includes(".level") || + p.endsWith("level") + ) { + return "percent"; + } + return "neutral"; +} + +function getHistorySeriesMeta(path, lineColorOverride) { + const key = classifyHistoryPropertyType(path); + const entry = PROPERTY_TYPE_MAP[key] ?? PROPERTY_TYPE_MAP.neutral; + return { + propertyType: key, + color: lineColorOverride ?? entry.color, + unit: entry.unit, + }; +} + +/** Safe display: formatted number + static unit suffix (no raw path / user strings). */ +function formatHistoryTooltipValue(raw, unitSuffix) { + const n = Number(raw); + if (!Number.isFinite(n)) return "\u2014"; + const formatted = new Intl.NumberFormat(undefined, { + maximumFractionDigits: 2, + minimumFractionDigits: 0, + }).format(n); + return unitSuffix ? `${formatted}${unitSuffix}` : formatted; +} + +function getNested(obj, pathParts) { + let x = obj; + for (const key of pathParts) { + x = x?.[key]; + } + return x; +} + +function rowsToChartPoints(rows, parsed) { + const out = []; + for (const row of rows) { + const t = new Date(row.sampledAt); + if (Number.isNaN(t.getTime())) continue; + + let raw; + if (parsed.kind === "power") { + raw = getNested(row.power, parsed.fieldParts); + } else if (parsed.kind === "waterTank") { + raw = getNested(row.waterTank, parsed.fieldParts); + } else { + raw = row[parsed.field]; + } + + const y = Number(raw); + if (!Number.isFinite(y)) continue; + out.push({ t, y }); + } + return out; +} + +const PERIODS = [ + { value: "30m", label: "Last 30 minutes", ms: 30 * 60 * 1000 }, + { value: "1h", label: "Last hour", ms: 60 * 60 * 1000 }, + { value: "4h", label: "Last 4 hours", ms: 4 * 60 * 60 * 1000 }, + { value: "8h", label: "Last 8 hours", ms: 8 * 60 * 60 * 1000 }, + { value: "12h", label: "Last 12 hours", ms: 12 * 60 * 60 * 1000 }, + { value: "1d", label: "Last day", ms: 24 * 60 * 60 * 1000 }, + { value: "1w", label: "Last week", ms: 7 * 24 * 60 * 60 * 1000 }, + { value: "1M", label: "Last month", ms: 30 * 24 * 60 * 60 * 1000 }, + { value: "1y", label: "Last year", ms: 365 * 24 * 60 * 60 * 1000 }, +]; + +function rangeForPeriod(periodValue) { + const p = PERIODS.find((x) => x.value === periodValue) ?? PERIODS[1]; + const end = new Date(); + const start = new Date(end.getTime() - p.ms); + return { start, end }; +} + +/** Bottom axis: time on first line, date on second (multi-line via tspans). */ +function formatPrimaryAxisTickTwoLines(periodValue, date) { + const entry = PERIODS.find((x) => x.value === periodValue) ?? PERIODS[1]; + const ms = entry.ms; + + if (ms >= 365 * 24 * 60 * 60 * 1000) { + const top = new Intl.DateTimeFormat(undefined, { month: "short" }).format( + date, + ); + const bottom = new Intl.DateTimeFormat(undefined, { + year: "numeric", + }).format(date); + return `${top}\n${bottom}`; + } + + const timeOpts = + ms <= 30 * 60 * 1000 + ? { hour: "numeric", minute: "2-digit", second: "2-digit" } + : { hour: "numeric", minute: "2-digit" }; + + const dateOpts = + ms <= 24 * 60 * 60 * 1000 + ? { weekday: "short", month: "short", day: "numeric" } + : { month: "short", day: "numeric", year: "numeric" }; + + const timeLine = new Intl.DateTimeFormat(undefined, timeOpts).format(date); + const dateLine = new Intl.DateTimeFormat(undefined, dateOpts).format(date); + return `${timeLine}\n${dateLine}`; +} + +function asDate(value) { + if (value instanceof Date) return value; + const d = new Date(value); + return Number.isNaN(d.getTime()) ? null : d; +} + +function HistoryTimeAxisTick({ x, y, payload, period }) { + const d = asDate(payload?.value); + if (!d) return null; + const lines = formatPrimaryAxisTickTwoLines(period, d) + .split("\n") + .map((l) => l.trim()) + .filter(Boolean); + return ( + + + {lines.map((line, i) => ( + + {line} + + ))} + + + ); +} + +function HistoryChartTooltip({ active, payload, unit }) { + if (!active || !payload?.length) return null; + const raw = payload[0]?.value; + return ( +
+ {formatHistoryTooltipValue(raw, unit)} +
+ ); +} + +function chartDataFromPoints(points) { + return points.map((p) => ({ t: p.t.getTime(), y: p.y })); +} + +/** Pixel size of an element; updates on resize (flex/drawer/scroll layouts need this for Recharts). */ +function useObservedSize(elementRef) { + const [size, setSize] = useState({ width: 0, height: 0 }); + useLayoutEffect(() => { + const el = elementRef.current; + if (!el) return undefined; + const measure = () => { + const r = el.getBoundingClientRect(); + setSize({ width: r.width, height: r.height }); + }; + measure(); + if (typeof ResizeObserver === "undefined") return undefined; + const ro = new ResizeObserver(measure); + ro.observe(el); + return () => ro.disconnect(); + }, []); + return size; +} + +/** + * @param {object} props + * @param {string} props.historyPath — e.g. `patch.${patchId}.soilHumidity`, `power.battery.voltage`, `waterTank.level` + * @param {string} [props.lineColor] — overrides automatic orange (temperature) / blue (humidity) / grey default + * @param {string} [props.className] + * @param {React.CSSProperties} [props.style] + * @param {number|string} [props.chartHeight=280] — number is treated as px; string passes through (e.g. `15vh`) + */ +export function HistoryLineChart({ + historyPath, + lineColor: lineColorProp, + className = "", + style, + chartHeight = "280px", +}) { + const { getHistory, isConnected } = useApi(); + const [period, setPeriod] = useState("1h"); + const [rows, setRows] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const parsed = useMemo(() => { + try { + return parseHistoryPath(historyPath); + } catch (e) { + return null; + } + }, [historyPath]); + + const parseError = useMemo(() => { + try { + parseHistoryPath(historyPath); + return null; + } catch (e) { + return e?.message || "Invalid history path"; + } + }, [historyPath]); + + const { color: lineColor, unit: valueUnit } = useMemo( + () => getHistorySeriesMeta(historyPath, lineColorProp), + [historyPath, lineColorProp], + ); + const fillGradientId = `hlc-area-${useId().replace(/:/g, "")}`; + const plotRef = useRef(null); + const plotSize = useObservedSize(plotRef); + + const load = useCallback(async () => { + if (!parsed) return; + const { start, end } = rangeForPeriod(period); + setLoading(true); + setError(null); + try { + const payload = { + kind: parsed.kind, + start: start.toISOString(), + end: end.toISOString(), + }; + if (parsed.kind === "patch") { + payload.patchId = parsed.patchId; + } + const data = await getHistory(payload); + setRows(Array.isArray(data) ? data : []); + } catch (e) { + setRows([]); + setError(e?.message || "Failed to load history"); + } finally { + setLoading(false); + } + }, [getHistory, parsed, period]); + + useEffect(() => { + if (!parsed || !isConnected) return; + load(); + }, [parsed, period, isConnected, load]); + + const points = useMemo(() => { + if (!parsed) return []; + return rowsToChartPoints(rows, parsed); + }, [rows, parsed]); + + const chartData = useMemo(() => chartDataFromPoints(points), [points]); + + const chartPixelW = Math.max(1, Math.floor(plotSize.width)); + const chartPixelH = Math.max(1, Math.floor(plotSize.height)); + const canRenderRecharts = + chartData.length > 0 && plotSize.width > 0 && plotSize.height > 0; + + const timeTickRenderer = useMemo( + () => (props) => , + [period], + ); + + const heightCss = + typeof chartHeight === "number" ? `${chartHeight}px` : chartHeight; + + const rootClass = ["history-line-chart", className].filter(Boolean).join(" "); + const plotStyle = { + ...style, + "--history-chart-height": heightCss, + }; + + if (parseError) { + return ( +
+
+ {parseError} +
+
+ ); + } + + return ( +
+
+ + {suffix || showClear ? ( + + {suffix} + {showClear ? ( + + ) : null} + + ) : null} + + ) : ( + + ); + + if (addonBefore != null || addonAfter != null) { + return ( + + {addonBefore != null ? ( + {addonBefore} + ) : null} + {inputEl} + {addonAfter != null ? ( + {addonAfter} + ) : null} + + ); + } + + return inputEl; +}); diff --git a/packages/client/src/components/Label.css b/packages/client/src/components/Label.css new file mode 100644 index 0000000..843b898 --- /dev/null +++ b/packages/client/src/components/Label.css @@ -0,0 +1,3 @@ +.label { + margin: 0 0 3px 0; +} diff --git a/packages/client/src/components/Label.jsx b/packages/client/src/components/Label.jsx new file mode 100644 index 0000000..82e6cba --- /dev/null +++ b/packages/client/src/components/Label.jsx @@ -0,0 +1,19 @@ +import "./Label.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * @param {object} props + * @param {import('react').ReactNode} props.label + * @param {'dt' | 'span' | 'label'} [props.as='dt'] + * @param {string} [props.className] + */ +export function Label({ label, as: Component = "dt", className, ...rest }) { + return ( + + {label} + + ); +} diff --git a/packages/client/src/components/LifecyclePhase.css b/packages/client/src/components/LifecyclePhase.css new file mode 100644 index 0000000..500a37d --- /dev/null +++ b/packages/client/src/components/LifecyclePhase.css @@ -0,0 +1,70 @@ +.lifecycle-phases-edit__row { + padding: 5px 0 5px 20px; +} + +.lifecycle-phases-edit__row-wrapper { + position: relative; + border-left: 2px solid + color-mix(in srgb, var(--border-ui-color) 70%, transparent); +} + +.lifecycle-phases-edit__phase-title { + font-size: 18px; + font-weight: 500; + line-height: 1.2; + margin: 0; + font-family: "Libre Baskerville", serif; +} + +.lifecycle-phases-edit__phase-timescale { + font-size: 18px; + font-weight: 400; + margin: 0; + line-height: 1; + font-style: italic; + font-family: "Libre Baskerville", serif; +} + +.lifecycle-phases-edit__remove { + position: absolute; + top: 1px; + right: 1px; +} + +.lifecycle-phases-edit__row-wrapper:last-of-type { + border-bottom: none; +} + +.lifecycle-phases-edit__configs { + width: 100%; +} + +.lifecycle-phases-edit__field { + flex: 1 1 7rem; + min-width: 0; +} + +.lifecycle-phases-edit__field--narrow { + flex-grow: 1; +} + +.lifecycle-phases--readonly .lifecycle-phases-edit__row-wrapper { + border-left: none; + flex-flow: row-reverse !important; + min-height: 91.5px; +} + +.lifecycle-phases--readonly .lifecycle-phases-edit__row { + padding: 0; + padding-left: 10px; + padding-bottom: 25px; +} + +.lifecycle-phases-edit__plant { + width: 130px; + margin-top: -5px; +} + +.lifecycle-phases--readonly .lifecycle-phases-edit__plant { + width: 90px; +} diff --git a/packages/client/src/components/LifecyclePhase.jsx b/packages/client/src/components/LifecyclePhase.jsx new file mode 100644 index 0000000..8b66472 --- /dev/null +++ b/packages/client/src/components/LifecyclePhase.jsx @@ -0,0 +1,371 @@ +import dayjs from "dayjs"; +import isoWeek from "dayjs/plugin/isoWeek"; +import utc from "dayjs/plugin/utc"; +import { useId } from "react"; +import { IoTrashOutline } from "react-icons/io5"; +import { Flex } from "./Flex.jsx"; +import { IconButton } from "./IconButton.jsx"; +import { Input } from "./Input.jsx"; +import { Label } from "./Label.jsx"; +import { Slider } from "./Slider.jsx"; +import { Plant } from "./allotment/Plant.jsx"; +import "./LifecyclePhase.css"; + +dayjs.extend(utc); +dayjs.extend(isoWeek); + +const MAX_CAL_WEEK = 52; +const MAX_PHASE_LEAVES = 6; +const MAX_PHASE_FLOWERS = 3; + +/** Jan 4 is always in ISO week 1; anchor a stable 0..52 grid for perennials. */ +const PERENNIAL_REF_YEAR = 2024; + +function perennialWeekGridStart() { + return dayjs.utc(`${PERENNIAL_REF_YEAR}-01-04`).startOf("isoWeek"); +} + +function dateAtPerennialWeekIndex(weekIndex) { + const w = Math.max( + 0, + Math.min(MAX_CAL_WEEK, Math.floor(Number(weekIndex)) || 0), + ); + return perennialWeekGridStart().add(w, "week"); +} + +function parsePlantedAtAnchor(raw) { + const s = typeof raw === "string" ? raw.trim() : ""; + if (!s) { + return dayjs.utc(`${PERENNIAL_REF_YEAR}-01-01T12:00:00Z`).startOf("day"); + } + if (/^\d{4}-\d{2}-\d{2}$/.test(s)) { + return dayjs.utc(`${s}T12:00:00Z`).startOf("day"); + } + const d = dayjs.utc(s); + return d.isValid() + ? d + : dayjs.utc(`${PERENNIAL_REF_YEAR}-01-01T12:00:00Z`).startOf("day"); +} + +/** + * @param {import('dayjs').Dayjs} d + */ +function earlyLateMonthLabel(d) { + if (!d?.isValid()) return ""; + const day = d.date(); + const month = d.format("MMMM"); + if (day <= 10) return `Early ${month}`; + if (day <= 20) return `Mid ${month}`; + return `Late ${month}`; +} + +/** + * @param {'biennial' | 'perennial'} variant + * @param {object} phase + * @param {number} weeks — span in weeks (same as the Weeks field) + * @param {string} [plantedAt] + */ +function phaseCalendarRangeLabel(variant, phase, weeks, plantedAt) { + const w = Math.max(0, Math.floor(Number(weeks)) || 0); + if (w <= 0) return null; + + let start; + let end; + + if (variant === "perennial") { + const startWeek = Math.floor(Number(phase?.startWeek) || 0); + start = dateAtPerennialWeekIndex(startWeek); + end = start.add(w, "week").subtract(1, "day"); + } else { + const base = parsePlantedAtAnchor(plantedAt); + const startOff = Math.floor(Number(phase?.startOffsetWeeks) || 0); + const endOff = Math.floor(Number(phase?.endOffsetWeeks) || 0); + start = base.add(startOff, "week"); + end = base.add(endOff, "week").subtract(1, "day"); + } + + if (!start.isValid() || !end.isValid() || end.isBefore(start)) return null; + + const left = earlyLateMonthLabel(start); + const right = earlyLateMonthLabel(end); + if (left && right && left === right) return left; + if (left && right) return `${left} – ${right}`; + return null; +} + +/** + * @param {object} props + * @param {number} props.phaseIndex + * @param {object} props.phase + * @param {'biennial' | 'perennial'} props.variant + * @param {number} props.weeks + * @param {string} props.nameFieldId + * @param {string} props.weeksFieldId + * @param {boolean} [props.editing=true] + * @param {boolean} [props.disabled] + * @param {boolean} props.removeDisabled + * @param {number|null|undefined} [props.soilHumidity] + * @param {string} [props.plantedAt] — YYYY-MM-DD or ISO; biennial calendar labels only + * @param {() => void} props.onRemove + * @param {(name: string) => void} props.onNameChange + * @param {(raw: string) => void} props.onWeeksChange + * @param {(n: number) => void} props.onGrowingPositionChange + * @param {(n: number) => void} props.onWitheringChange + * @param {(n: number) => void} props.onLeavesChange + * @param {(n: number) => void} props.onFlowersChange + * @param {(n: number) => void} props.onFruitingChange + */ +export function LifecyclePhase({ + phaseIndex, + phase, + variant, + weeks, + nameFieldId, + weeksFieldId, + editing = true, + disabled, + removeDisabled, + soilHumidity, + plantedAt, + produceIcon, + onRemove, + onNameChange, + onWeeksChange, + onGrowingPositionChange, + onWitheringChange, + onLeavesChange, + onFlowersChange, + onFruitingChange, +}) { + const sliderIds = useId(); + const growthLabelId = `${sliderIds}-growth`; + const witheringLabelId = `${sliderIds}-withering`; + const leavesLabelId = `${sliderIds}-leaves`; + const flowersLabelId = `${sliderIds}-flowers`; + const fruitingLabelId = `${sliderIds}-fruiting`; + const flowerCount = phase.flowers ?? 0; + + const timescaleLabel = phaseCalendarRangeLabel( + variant, + phase, + weeks, + plantedAt, + ); + + return ( + + {editing ? ( + + + + ) : null} + + + +

{phase.name}

+ {timescaleLabel ? ( +

+ {timescaleLabel} +

+ ) : null} +
+ {editing ? ( + <> + + + + + + + + + + + + + + + + + + + {flowerCount > 0 ? ( + + + + + ) : null} + + ) : null} +
+
+ +
+
+ ); +} diff --git a/packages/client/src/components/LifecyclePhases.css b/packages/client/src/components/LifecyclePhases.css new file mode 100644 index 0000000..a210b13 --- /dev/null +++ b/packages/client/src/components/LifecyclePhases.css @@ -0,0 +1,11 @@ +.lifecycle-phases-edit { + width: 100%; + display: flex; + flex-direction: column; + gap: 20px; +} + +.lifecycle-phases--readonly { + gap: 8px; + margin-left: -22px; +} diff --git a/packages/client/src/components/LifecyclePhases.jsx b/packages/client/src/components/LifecyclePhases.jsx new file mode 100644 index 0000000..bee9138 --- /dev/null +++ b/packages/client/src/components/LifecyclePhases.jsx @@ -0,0 +1,206 @@ +import { useId } from "react"; +import { Button } from "./Button.jsx"; +import { Flex } from "./Flex.jsx"; +import { LifecyclePhase } from "./LifecyclePhase.jsx"; +import "./LifecyclePhases.css"; + +const MAX_CAL_WEEK = 52; + +function biennialWeeksFromPhase(p) { + const s = p.startOffsetWeeks ?? 0; + const e = p.endOffsetWeeks ?? 0; + return Math.max(0, e - s); +} + +/** Span for display; when start > end, phase crosses the year in 0..52 space. */ +function perennialWeeksFromPhase(p) { + const s = p.startWeek ?? 0; + const e = p.endWeek ?? 0; + if (e >= s) return Math.max(0, e - s); + return Math.max(0, MAX_CAL_WEEK - s + e); +} + +function rebuildBiennialPhases(phases, weeksPerPhase) { + let cursor = 0; + return phases.map((p, i) => { + const w = Math.max(0, Math.floor(Number(weeksPerPhase[i]) || 0)); + const startOffsetWeeks = cursor; + const endOffsetWeeks = startOffsetWeeks + w; + cursor = endOffsetWeeks; + return { ...p, startOffsetWeeks, endOffsetWeeks }; + }); +} + +/** Sequential segments from week 0; each phase is [start, end) clamped to 0..52. */ +function rebuildPerennialPhases(phases, weeksPerPhase) { + let cursor = 0; + return phases.map((p, i) => { + const w = Math.max(0, Math.floor(Number(weeksPerPhase[i]) || 0)); + const startWeek = Math.min(MAX_CAL_WEEK, cursor); + const endWeek = Math.min(MAX_CAL_WEEK, startWeek + w); + cursor = endWeek; + return { ...p, startWeek, endWeek }; + }); +} + +/** + * @typedef {object} BiennialPhase + * @property {string} name + * @property {number} startOffsetWeeks + * @property {number} endOffsetWeeks + * @property {number} [growingPosition] — 0–100, Lottie growth stage + * @property {number} [withering] — 0–100, plant colour withering + * @property {number} [leaves] — 0–6, visible leaves on plant Lottie + * @property {number} [flowers] — 0–3, visible flowers on plant Lottie + * @property {number} [fruiting] — 0–100, fruit development when flowers > 0 + */ + +/** + * @typedef {object} PerennialPhase + * @property {string} name + * @property {number} startWeek + * @property {number} endWeek + * @property {number} [growingPosition] — 0–100 + * @property {number} [withering] — 0–100 + * @property {number} [leaves] — 0–6 + * @property {number} [flowers] — 0–3 + * @property {number} [fruiting] — 0–100 + */ + +/** + * @param {object} props + * @param {'biennial' | 'perennial'} props.variant + * @param {(BiennialPhase[] | PerennialPhase[])} props.phases + * @param {(next: BiennialPhase[] | PerennialPhase[]) => void} props.onChange + * @param {boolean} [props.editing=true] + * @param {boolean} [props.disabled] + * @param {string} [props.plantedAt] — YYYY-MM-DD or ISO; anchors biennial week offsets for calendar labels + */ +export function LifecyclePhases({ + variant, + phases, + onChange, + editing = true, + disabled, + soilHumidity, + plantedAt, + produceIcon, +}) { + const idPrefix = useId(); + const list = Array.isArray(phases) ? phases : []; + + const weeksRowForPhase = (p) => + variant === "biennial" + ? biennialWeeksFromPhase(p) + : perennialWeeksFromPhase(p); + + const addPhase = () => { + const weeks = list.map(weeksRowForPhase); + weeks.push(1); + const blank = + variant === "biennial" + ? { + name: "", + startOffsetWeeks: 0, + endOffsetWeeks: 1, + growingPosition: 0, + withering: 0, + leaves: 0, + flowers: 0, + fruiting: 0, + } + : { + name: "", + startWeek: 0, + endWeek: 1, + growingPosition: 0, + withering: 0, + leaves: 0, + flowers: 0, + fruiting: 0, + }; + const extended = [...list, blank]; + onChange( + variant === "biennial" + ? rebuildBiennialPhases(extended, weeks) + : rebuildPerennialPhases(extended, weeks), + ); + }; + + const removeAt = (index) => { + const weeks = list.map(weeksRowForPhase); + weeks.splice(index, 1); + const rest = list.filter((_, i) => i !== index); + onChange( + variant === "biennial" + ? rebuildBiennialPhases(rest, weeks) + : rebuildPerennialPhases(rest, weeks), + ); + }; + + const patchAt = (index, patch) => { + onChange(list.map((p, i) => (i === index ? { ...p, ...patch } : p))); + }; + + const setPhaseWeeks = (index, raw) => { + const n = parseInt(String(raw), 10); + const w = Number.isFinite(n) ? Math.max(0, n) : 0; + const weeks = list.map((p, i) => (i === index ? w : weeksRowForPhase(p))); + onChange( + variant === "biennial" + ? rebuildBiennialPhases(list, weeks) + : rebuildPerennialPhases(list, weeks), + ); + }; + + return ( + +
+ {list.map((phase, index) => ( + removeAt(index)} + onNameChange={(name) => patchAt(index, { name })} + onWeeksChange={(raw) => setPhaseWeeks(index, raw)} + onGrowingPositionChange={(n) => + patchAt(index, { growingPosition: n }) + } + onWitheringChange={(n) => patchAt(index, { withering: n })} + onLeavesChange={(n) => patchAt(index, { leaves: n })} + onFlowersChange={(n) => + patchAt( + index, + n === 0 ? { flowers: n, fruiting: 0 } : { flowers: n }, + ) + } + onFruitingChange={(n) => patchAt(index, { fruiting: n })} + /> + ))} +
+ {editing ? ( + + ) : null} +
+ ); +} diff --git a/packages/client/src/components/LoadingIcon.css b/packages/client/src/components/LoadingIcon.css new file mode 100644 index 0000000..8727d42 --- /dev/null +++ b/packages/client/src/components/LoadingIcon.css @@ -0,0 +1,19 @@ +.loading-icon { + display: inline-block; + width: 14px; + height: 14px; + animation: loading-spin 1s linear infinite; +} + +.loading-icon path { + fill: var(--loading-icon-fill, var(--text)); +} + +@keyframes loading-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/packages/client/src/components/LoadingIcon.jsx b/packages/client/src/components/LoadingIcon.jsx new file mode 100644 index 0000000..989b886 --- /dev/null +++ b/packages/client/src/components/LoadingIcon.jsx @@ -0,0 +1,21 @@ +import LoadingSvg from "../../assets/svg/Loading.svg?react"; +import "./LoadingIcon.css"; + +export function LoadingIcon({ className, size, color, style, ...props }) { + const mergedStyle = { + ...(size ? { width: size, height: size } : {}), + ...(color ? { "--loading-icon-fill": color } : {}), + ...style, + }; + function joinClassNames(...values) { + return values.filter(Boolean).join(" "); + } + + return ( + + ); +} diff --git a/packages/client/src/components/Metric.jsx b/packages/client/src/components/Metric.jsx new file mode 100644 index 0000000..af5e5f3 --- /dev/null +++ b/packages/client/src/components/Metric.jsx @@ -0,0 +1,10 @@ +import React from "react"; + +export function Metric({ title, children, className = "" }) { + return ( +
+ {title} + {children} +
+ ); +} diff --git a/packages/client/src/components/Metrics.css b/packages/client/src/components/Metrics.css new file mode 100644 index 0000000..54d219f --- /dev/null +++ b/packages/client/src/components/Metrics.css @@ -0,0 +1,5 @@ +.metrics.metrics--vertical > * { + flex: 0 0 auto; + width: 100%; + min-width: 0; +} diff --git a/packages/client/src/components/Metrics.jsx b/packages/client/src/components/Metrics.jsx new file mode 100644 index 0000000..3153506 --- /dev/null +++ b/packages/client/src/components/Metrics.jsx @@ -0,0 +1,36 @@ +import React from "react"; +import { Flex } from "./Flex.jsx"; +import "./Metrics.css"; + +/** Container for {@link Metric} children. `layout` controls row vs column flex direction. */ +export function Metrics({ + layout = "horizontal", + gap = "1rem", + wrap, + children, + className = "", + style, + ...rest +}) { + const vertical = layout === "vertical"; + const mergedClass = [ + "metrics", + vertical ? "metrics--vertical" : "metrics--horizontal", + className, + ] + .filter(Boolean) + .join(" "); + + return ( + + {children} + + ); +} diff --git a/packages/client/src/components/PageScroll.css b/packages/client/src/components/PageScroll.css new file mode 100644 index 0000000..8f50427 --- /dev/null +++ b/packages/client/src/components/PageScroll.css @@ -0,0 +1,175 @@ +.page-scroll { + flex: 1; + min-height: 0; + position: relative; + width: 100%; +} + +.page-scroll-sticky { + position: absolute; + top: 0; + z-index: 4; + flex-shrink: 0; + width: 100%; + box-sizing: border-box; + padding: var(--app-main-padding-top) var(--app-main-padding-right) 0 + calc(var(--sidebar-width) + var(--app-main-padding-left)); +} + +.page-scroll-sticky .page-title { + text-shadow: 0 0 20px var(--bg); + font-size: 38px; + font-family: "Libre Baskerville", serif; +} + +.page-scroll-wrapper { + position: absolute; + flex: 1; + min-height: 0; + + display: flex; + flex-direction: column; + top: var(--app-main-padding-top); + left: 0; + right: 0; + bottom: 0; +} + +.page-scroll-top-gradient { + position: absolute; + inset: 0; + top: -50px; + left: 0; + right: 0; + z-index: 2; + opacity: 1; + pointer-events: none; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255) 50%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + rgb(255 255 255) 0%, + rgb(255 255 255) 50%, + rgb(255 255 255 / 0%) 100% + ); +} + +.page-scroll-bottom-gradient { + position: absolute; + top: unset; + bottom: 0; + left: 0; + right: 0; + z-index: 2; + opacity: 1; + pointer-events: none; + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + mask-image: linear-gradient( + to top, + rgb(255 255 255) 0%, + rgb(255 255 255) 25%, + rgb(255 255 255 / 0%) 100% + ); + -webkit-mask-image: linear-gradient( + to top, + rgb(255 255 255) 0%, + rgb(255 255 255) 25%, + rgb(255 255 255 / 0%) 100% + ); +} + +.page-scroll-vscroll { + flex: 1; + min-height: 0; + width: 100%; + max-height: none; + height: auto; + margin: 0; + padding: 0; + mask: linear-gradient( + 180deg, + transparent 0%, + black var(--page-scroll-top-gradient-height, 50px), + black var(--page-scroll-bottom-gradient-height, 50px), + transparent 100% + ); + -webkit-mask: linear-gradient( + 180deg, + transparent 0%, + black var(--page-scroll-top-gradient-height, 50px), + black var(--page-scroll-bottom-gradient-height, 50px), + transparent 100% + ); +} + +.page-scroll-vscroll .simplebar-vertical { + margin-left: 0.35rem; + width: var(--border-ui-width); + border-radius: 18px; + overflow: hidden; + opacity: 0; + transition: opacity 0.3s ease; + margin-top: var(--simplebar-track-margin-top, 0); + margin-bottom: var(--app-main-padding-bottom); + margin-right: calc(var(--app-main-padding-right) / 2); +} + +.page-scroll-vscroll::before { + content: ""; + position: absolute; + right: 0; + top: 0; + bottom: 0; + z-index: 1; + opacity: 0; + transition: opacity 0.3s ease; + width: var(--border-ui-width); + border-radius: 18px; +} + +.page-scroll-vscroll.simplebar-scrolling::before { + opacity: 1; +} + +.page-scroll-vscroll.simplebar-scrolling .simplebar-vertical { + opacity: 1; +} + +.page-scroll-content { + display: flex; + flex-direction: column; + gap: 1.25rem; + box-sizing: border-box; + padding: var(--simplebar-track-margin-top, 50px) var(--app-main-padding-right) + 2rem calc(var(--sidebar-width) + var(--app-main-padding-left)); + min-height: 100%; + margin: 0; + margin-bottom: var(--app-main-padding-bottom); +} + +.page-scroll-start { + scroll-snap-align: start; + scroll-snap-stop: normal; + display: block; +} + +.page-scroll-vscroll .simplebar-scrollbar::before { + top: 0; + bottom: 0; + left: 0; + right: 0; + background: var(--border-ui-color); + border-radius: 18px; +} + +.page-scroll-vscroll .simplebar-scrollbar.simplebar-visible, +.page-scroll-vscroll .simplebar-scrollbar.simplebar-visible::before { + opacity: 1; +} diff --git a/packages/client/src/components/PageScroll.jsx b/packages/client/src/components/PageScroll.jsx new file mode 100644 index 0000000..e368ff4 --- /dev/null +++ b/packages/client/src/components/PageScroll.jsx @@ -0,0 +1,88 @@ +import { useEffect, useRef, useState } from "react"; +import SimpleBar from "simplebar-react"; +import "simplebar-react/dist/simplebar.min.css"; +import "./PageScroll.css"; +import AnimatedText from "./AnimatedText.jsx"; + +const GRADIENT_HEIGHT = 80; + +export function PageScroll({ + title, + children, + className = "", + scrollable = true, +}) { + const simpleBarRef = useRef(null); + const [isScrollAtTop, setIsScrollAtTop] = useState(true); + + useEffect(() => { + const instance = simpleBarRef.current; + if (!instance) return; + + const handleScroll = () => { + const scrollElement = instance.getScrollElement(); + if (scrollElement) { + setIsScrollAtTop(scrollElement.scrollTop <= 0); + } + }; + + const scrollElement = instance.getScrollElement(); + if (!scrollElement) return; + + scrollElement.addEventListener("scroll", handleScroll); + handleScroll(); + + const resizeObserver = new ResizeObserver(() => { + handleScroll(); + }); + resizeObserver.observe(scrollElement); + + return () => { + scrollElement.removeEventListener("scroll", handleScroll); + resizeObserver.disconnect(); + }; + }, []); + + const wrapperStyle = { + marginTop: `${30}px`, + "--simplebar-track-margin-top": `${GRADIENT_HEIGHT}px`, + "--page-scroll-top-gradient-height": `${GRADIENT_HEIGHT}px`, + "--page-scroll-bottom-gradient-height": `calc(100% - ${GRADIENT_HEIGHT}px)`, + }; + + return ( +
+
+
+ +
+
+
+ {scrollable && ( + <> +
+
+ + )} + {scrollable ? ( + + +
{children}
+
+ ) : ( +
{children}
+ )} +
+
+ ); +} diff --git a/packages/client/src/components/PlantGrid.css b/packages/client/src/components/PlantGrid.css new file mode 100644 index 0000000..634dc4e --- /dev/null +++ b/packages/client/src/components/PlantGrid.css @@ -0,0 +1,118 @@ +.plant-grid { + display: flex; + flex-direction: column; + gap: 8px; + align-items: stretch; + width: 100%; + min-width: 0; +} + +.plant-grid__controls { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; + gap: 10px; + min-width: 0; +} + +.plant-grid__col-controls, +.plant-grid__row-controls { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 3px; + min-width: 0; +} + +.plant-grid__col-controls .icon-btn > svg, +.plant-grid__row-controls .icon-btn > svg { + margin-right: 0; +} + +.plant-grid__stepper-value { + font-variant-numeric: tabular-nums; + font-weight: 600; + font-size: 0.95rem; + min-width: 14px; + text-align: center; + color: var(--text); +} + +.plant-grid__matrix-wrap { + min-height: 68px; + min-width: 0; + border: none; + padding: 16px 10px 0 10px; + overflow: visible; + display: flex; + align-items: center; +} + +.plant-grid__matrix-wrap.single-row { + margin-top: 0; +} + +.plant-grid__matrix-wrap.single-column { + margin-left: 0; +} + +.plant-grid__matrix-host { + position: relative; + width: 100%; + min-height: 50px; + background: color-mix(in srgb, var(--surface) 40%, var(--bg)); +} + +.plant-grid__matrix-wrap.single-row .plant-grid__matrix-host { + min-height: 0; + height: 2px; +} + +.plant-grid__matrix-wrap.single-column .plant-grid__matrix-host { + min-width: 0; + width: 2px; +} + +.plant-grid__matrix { + width: 100%; + min-height: 50px; + position: relative; + z-index: 0; + border-top: var(--border-ui-width) solid var(--border-ui-color); + border-left: var(--border-ui-width) solid var(--border-ui-color); +} + +.plant-grid__matrix-wrap.single-row .plant-grid__matrix { + border-left: none; +} + +.plant-grid__matrix-wrap.single-column .plant-grid__matrix { + border-top: none; +} + +.plant-grid__intersections { + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + margin: 1px; +} + +.plant-grid__intersection-icon { + position: absolute; + color: var(--accent); + width: 20px; + height: 20px; + flex-shrink: 0; + transform: translate(-50%, -100%); + margin-top: 2px; + /* horizontal center on intersection; bottom of icon sits on the intersection */ +} + +.plant-grid__cell { + min-width: 0; + min-height: 0; +} diff --git a/packages/client/src/components/PlantGrid.jsx b/packages/client/src/components/PlantGrid.jsx new file mode 100644 index 0000000..08d63e7 --- /dev/null +++ b/packages/client/src/components/PlantGrid.jsx @@ -0,0 +1,154 @@ +import { MdAdd, MdRemove } from "react-icons/md"; +import { PiPlantFill } from "react-icons/pi"; +import { Label } from "./Label.jsx"; +import { IconButton } from "./IconButton.jsx"; +import "./PlantGrid.css"; + +function clamp(n, min, max) { + return Math.min(max, Math.max(min, n)); +} + +/** + * Visual rows×columns grid with button-style lines, plant icons at line intersections, and steppers. + * + * @param {object} props + * @param {number} props.rows + * @param {number} props.columns + * @param {(n: number) => void} props.onRowsChange + * @param {(n: number) => void} props.onColumnsChange + * @param {number} [props.min] + * @param {number} [props.max] + * @param {boolean} [props.disabled] + */ +export function PlantGrid({ + rows, + columns, + onRowsChange, + onColumnsChange, + min = 1, + max = 24, + disabled = false, +}) { + const r = clamp(Math.round(Number(rows)) || min, min, max); + const c = clamp(Math.round(Number(columns)) || min, min, max); + + const singleRow = r === 1; + const singleColumn = c === 1; + + const edge = "var(--border-ui-width) solid var(--border-ui-color)"; + const cellRows = Math.max(0, r - 1); + const cellCols = Math.max(0, c - 1); + const cells = []; + for (let row = 0; row < cellRows; row++) { + for (let col = 0; col < cellCols; col++) { + cells.push( +
, + ); + } + } + + const intersectionIcons = []; + for (let j = 0; j <= r - 1; j++) { + for (let i = 0; i <= c - 1; i++) { + // Align to grid-line crossings: c columns ⇒ c lines at 0 … 100%, not c equal bands. + const leftPct = c <= 1 ? 50 : (i / (c - 1)) * 100; + const topPct = r <= 1 ? 50 : (j / (r - 1)) * 100; + intersectionIcons.push( + , + ); + } + } + + return ( +
+
+
+
{intersectionIcons}
+
+ {cells} +
+
+
+
+
+
+
+
+
+
+ ); +} diff --git a/packages/client/src/components/Popover.css b/packages/client/src/components/Popover.css new file mode 100644 index 0000000..4df23b2 --- /dev/null +++ b/packages/client/src/components/Popover.css @@ -0,0 +1,200 @@ +.popover-wrapper { + position: relative; + display: inline-block; +} + +.popover-root { + position: absolute; + z-index: 1050; + border-radius: 25px; + box-shadow: + 0 6px 35px 0 rgba(0, 0, 0, 0.3), + 0 3px 6px -4px rgba(0, 0, 0, 0.6); + display: flex; + flex-direction: column; + opacity: 0; + visibility: hidden; + transition: + opacity 0.2s ease, + transform 0.2s ease, + visibility 0.2s; + min-width: 177px; + max-width: min(360px, calc(100vw - 24px)); + box-sizing: border-box; +} + +.popover-root::before { + content: ""; + position: absolute; + inset: 0; + z-index: -1; + background: color-mix(in srgb, var(--surface) 72%, transparent); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); + border-radius: 25px; +} + +.drawer-root .popover-root::before { + background: var(--surface); + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + +.popover-root.popover-open { + opacity: 1; + visibility: visible; +} + +.popover-inner { + margin: 5px; + border-radius: 9px; + padding: 4px 4px; +} + +.popover-title { + margin-bottom: 8px; + padding-bottom: 8px; + border-bottom: 1px solid var(--border-ui-color); + color: var(--text); + font-size: 14px; + font-weight: 500; + line-height: 1.5; +} + +.popover-inner-content { + color: color-mix(in srgb, var(--text) 85%, transparent); + font-size: 14px; + line-height: 1.5; +} + +.popover-top { + bottom: 100%; + left: 50%; + transform: translateX(-50%) translateY(8px); + margin-bottom: 10px; +} + +.popover-top.popover-open { + transform: translateX(-50%) translateY(0); +} + +.popover-topLeft { + bottom: 100%; + left: 0; + transform: translateY(8px); + margin-bottom: 10px; +} + +.popover-topLeft.popover-open { + transform: translateY(0); +} + +.popover-topRight { + bottom: 100%; + right: 0; + transform: translateY(8px); + margin-bottom: 10px; +} + +.popover-topRight.popover-open { + transform: translateY(0); +} + +.popover-bottom { + top: 100%; + left: 50%; + transform: translateX(-50%) translateY(-8px); + margin-top: 10px; +} + +.popover-bottom.popover-open { + transform: translateX(-50%) translateY(0); +} + +.popover-bottomLeft { + top: 100%; + left: 0; + transform: translateY(-8px); + margin-top: 10px; +} + +.popover-bottomLeft.popover-open { + transform: translateY(0); +} + +.popover-bottomRight { + top: 100%; + right: 0; + transform: translateY(-8px); + margin-top: 10px; +} + +.popover-bottomRight.popover-open { + transform: translateY(0); +} + +.popover-left { + right: 100%; + top: 50%; + transform: translateY(-50%) translateX(8px); + margin-right: 10px; +} + +.popover-left.popover-open { + transform: translateY(-50%) translateX(0); +} + +.popover-leftTop { + right: 100%; + top: 0; + transform: translateX(8px); + margin-right: 10px; +} + +.popover-leftTop.popover-open { + transform: translateX(0); +} + +.popover-leftBottom { + right: 100%; + bottom: 0; + transform: translateX(8px); + margin-right: 10px; +} + +.popover-leftBottom.popover-open { + transform: translateX(0); +} + +.popover-right { + left: 100%; + top: 50%; + transform: translateY(-50%) translateX(-8px); + margin-left: 10px; +} + +.popover-right.popover-open { + transform: translateY(-50%) translateX(0); +} + +.popover-rightTop { + left: 100%; + top: 0; + transform: translateX(-8px); + margin-left: 10px; +} + +.popover-rightTop.popover-open { + transform: translateX(0); +} + +.popover-rightBottom { + left: 100%; + bottom: 0; + transform: translateX(-8px); + margin-left: 10px; +} + +.popover-rightBottom.popover-open { + transform: translateX(0); +} diff --git a/packages/client/src/components/Popover.jsx b/packages/client/src/components/Popover.jsx new file mode 100644 index 0000000..2337ab8 --- /dev/null +++ b/packages/client/src/components/Popover.jsx @@ -0,0 +1,207 @@ +import { + useState, + useRef, + useEffect, + useCallback, + cloneElement, +} from "react"; +import "./Popover.css"; + +/** + * @param {object} props + * @param {import('react').ReactElement} props.children — single element; receives trigger handlers and ref + * @param {import('react').ReactNode} props.content + * @param {import('react').ReactNode} [props.title] + * @param {string | string[]} [props.trigger] + * @param {string} [props.placement] + * @param {boolean} [props.disabled] + * @param {boolean} [props.open] — controlled (Ant-style); falls back to `visible` + * @param {boolean} [props.visible] — controlled (alias) + * @param {(open: boolean) => void} [props.onOpenChange] + * @param {(visible: boolean) => void} [props.onVisibleChange] + * @param {string} [props.className] + * @param {string} [props.overlayClassName] + * @param {boolean} [props.defaultOpen] + */ +export function Popover({ + children, + content, + title, + trigger = ["hover"], + placement = "top", + disabled = false, + open: openProp, + visible: visibleProp, + onOpenChange, + onVisibleChange, + className = "", + overlayClassName = "", + defaultOpen = false, + ...props +}) { + const controlledValue = + openProp !== undefined ? openProp : visibleProp; + const isControlled = controlledValue !== undefined; + const [internalVisible, setInternalVisible] = useState(defaultOpen); + const visible = isControlled ? controlledValue : internalVisible; + + const setVisible = useCallback( + (next) => { + if (!isControlled) setInternalVisible(next); + onOpenChange?.(next); + onVisibleChange?.(next); + }, + [isControlled, onOpenChange, onVisibleChange], + ); + + const triggers = Array.isArray(trigger) ? trigger : [trigger]; + const wrapperRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if ( + wrapperRef.current && + !wrapperRef.current.contains(event.target) + ) { + setVisible(false); + } + }; + + if (visible && triggers.includes("click")) { + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [visible, triggers, setVisible]); + + const handleMouseEnter = useCallback(() => { + if (!disabled && triggers.includes("hover")) { + setVisible(true); + } + }, [disabled, triggers, setVisible]); + + const handleMouseLeave = useCallback(() => { + if (triggers.includes("hover")) { + setVisible(false); + } + }, [triggers, setVisible]); + + const handleClick = useCallback( + (event) => { + if (disabled) return; + + if (triggers.includes("click")) { + event.preventDefault(); + event.stopPropagation(); + setVisible(!visible); + } + }, + [disabled, triggers, visible, setVisible], + ); + + const handleFocus = useCallback(() => { + if (!disabled && triggers.includes("focus")) { + setVisible(true); + } + }, [disabled, triggers, setVisible]); + + const handleBlur = useCallback(() => { + if (triggers.includes("focus")) { + setVisible(false); + } + }, [triggers, setVisible]); + + const handleContextMenu = useCallback( + (event) => { + if (disabled) return; + + if (triggers.includes("contextMenu")) { + event.preventDefault(); + setVisible(true); + } + }, + [disabled, triggers, setVisible], + ); + + const handleKeyDown = useCallback( + (event) => { + if (disabled) return; + + if (event.key === "Escape") { + setVisible(false); + } + }, + [disabled, setVisible], + ); + + const triggerElement = cloneElement(children, { + ref: (node) => { + const r = children.ref; + if (typeof r === "function") r(node); + else if (r) r.current = node; + }, + onClick: (e) => { + handleClick(e); + children.props?.onClick?.(e); + }, + onMouseEnter: (e) => { + handleMouseEnter(); + children.props?.onMouseEnter?.(e); + }, + onMouseLeave: (e) => { + handleMouseLeave(); + children.props?.onMouseLeave?.(e); + }, + onFocus: (e) => { + handleFocus(); + children.props?.onFocus?.(e); + }, + onBlur: (e) => { + handleBlur(); + children.props?.onBlur?.(e); + }, + onContextMenu: (e) => { + handleContextMenu(e); + children.props?.onContextMenu?.(e); + }, + onKeyDown: (e) => { + handleKeyDown(e); + children.props?.onKeyDown?.(e); + }, + "aria-haspopup": "true", + "aria-expanded": visible, + }); + + const placementClass = `popover-${placement}`; + + return ( +
+ {triggerElement} +
+
+ {title ?
{title}
: null} +
{content}
+
+
+
+ ); +} + +Popover.displayName = "Popover"; diff --git a/packages/client/src/components/ProduceIcon.jsx b/packages/client/src/components/ProduceIcon.jsx new file mode 100644 index 0000000..70da8f1 --- /dev/null +++ b/packages/client/src/components/ProduceIcon.jsx @@ -0,0 +1,66 @@ +import AppleSvg from "../../assets/svg/produce/apple.svg?react"; +import BeetSvg from "../../assets/svg/produce/beet.svg?react"; +import CabbageSvg from "../../assets/svg/produce/cabbage.svg?react"; +import CarrotSvg from "../../assets/svg/produce/carrot.svg?react"; +import CherrySvg from "../../assets/svg/produce/cherry.svg?react"; +import CornSvg from "../../assets/svg/produce/corn.svg?react"; +import CucumberSvg from "../../assets/svg/produce/cucumber.svg?react"; +import KiwiSvg from "../../assets/svg/produce/kiwi.svg?react"; +import LeekSvg from "../../assets/svg/produce/leek.svg?react"; +import LettuceSvg from "../../assets/svg/produce/lettuce.svg?react"; +import PeasSvg from "../../assets/svg/produce/peas.svg?react"; +import PlumSvg from "../../assets/svg/produce/plum.svg?react"; +import PotatoSvg from "../../assets/svg/produce/potato.svg?react"; +import RadishSvg from "../../assets/svg/produce/radish.svg?react"; +import RaspberrySvg from "../../assets/svg/produce/raspberry.svg?react"; +import StrawberrySvg from "../../assets/svg/produce/strawberry.svg?react"; +import TomatoSvg from "../../assets/svg/produce/tomato.svg?react"; +import { DEFAULT_PRODUCE_ICON, PRODUCE_ICON_IDS } from "./produceIconIds.js"; + +const PRODUCE_SVGS = { + apple: AppleSvg, + beet: BeetSvg, + cabbage: CabbageSvg, + carrot: CarrotSvg, + cherry: CherrySvg, + corn: CornSvg, + cucumber: CucumberSvg, + kiwi: KiwiSvg, + leek: LeekSvg, + lettuce: LettuceSvg, + peas: PeasSvg, + plum: PlumSvg, + potato: PotatoSvg, + radish: RadishSvg, + raspberry: RaspberrySvg, + strawberry: StrawberrySvg, + tomato: TomatoSvg, +}; + +/** + * @param {object} props + * @param {string} [props.icon] — id matching `produceIconIds` (e.g. `tomato`) + * @param {string} [props.className] + * @param {import('react').CSSProperties} [props.style] + * @param {string} [props.title] + * @param {string} [props.role] + */ +export function ProduceIcon({ icon, className, style, title, role, ...rest }) { + const id = + typeof icon === "string" && PRODUCE_ICON_IDS.includes(icon.trim()) + ? icon.trim() + : DEFAULT_PRODUCE_ICON; + const Svg = PRODUCE_SVGS[id] ?? PRODUCE_SVGS[DEFAULT_PRODUCE_ICON]; + return ( + + + + ); +} diff --git a/packages/client/src/components/ProduceIconSelect.css b/packages/client/src/components/ProduceIconSelect.css new file mode 100644 index 0000000..b9ad1a5 --- /dev/null +++ b/packages/client/src/components/ProduceIconSelect.css @@ -0,0 +1,86 @@ +.produce-icon-select { + display: flex; + align-items: flex-start; +} + +.produce-icon-select__anchor { + display: inline-flex; + line-height: 0; +} + +/* 64×64 icon button: themed like .btn, same border-radius as .btn (18px) */ +.produce-icon-select__trigger.btn { + width: 95px; + height: 95px; + min-height: 64px; + min-width: 64px; + padding: 0; + border-radius: 18px; + background-color: var(--bg); +} + +.produce-icon-select__trigger.btn:hover { + background-color: var(--bg); + border-color: color-mix(in srgb, var(--accent) 45%, var(--border-ui-color)); +} + +.produce-icon-select__trigger .produce-icon__svg { + width: 58px; + height: 58px; + display: block; +} + +.produce-icon-select__grid { + display: grid; + grid-template-columns: repeat(6, 44px); + gap: 8px; + padding: 2px; +} + +.produce-icon-select__option { + appearance: none; + -webkit-appearance: none; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + margin: 0; + padding: 0; + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 18px; + background: transparent; + color: var(--text); + cursor: pointer; + transition: + background-color 0.3s ease, + color 0.3s ease, + border-color 0.3s ease, + transform 0.2s ease; +} + +.produce-icon-select__option .produce-icon__svg { + width: 28px; + height: 28px; + display: block; +} + +.produce-icon-select__option:hover { + background-color: var(--border-ui-color); + color: var(--bg); + transform: scale(1.03); +} + +.produce-icon-select__option:active { + transform: scale(0.98); +} + +.produce-icon-select__option--selected { + border-color: var(--accent); + box-shadow: 0 0 0 1px var(--accent); +} + +.produce-icon-select__option--selected:hover { + border-color: var(--accent); +} diff --git a/packages/client/src/components/ProduceIconSelect.jsx b/packages/client/src/components/ProduceIconSelect.jsx new file mode 100644 index 0000000..6a7cc74 --- /dev/null +++ b/packages/client/src/components/ProduceIconSelect.jsx @@ -0,0 +1,80 @@ +import { useState } from "react"; +import { Button } from "./Button.jsx"; +import { Popover } from "./Popover.jsx"; +import { ProduceIcon } from "./ProduceIcon.jsx"; +import { DEFAULT_PRODUCE_ICON, PRODUCE_ICON_IDS } from "./produceIconIds.js"; +import "./ProduceIconSelect.css"; + +function optionLabel(id) { + return id.charAt(0).toUpperCase() + id.slice(1); +} + +/** + * @param {object} props + * @param {string} props.value + * @param {(next: string) => void} props.onChange + * @param {boolean} [props.disabled] + * @param {string} [props.id] + */ +export function ProduceIconSelect({ value, onChange, disabled, id }) { + const [open, setOpen] = useState(false); + const safe = + typeof value === "string" && PRODUCE_ICON_IDS.includes(value) + ? value + : DEFAULT_PRODUCE_ICON; + + const content = ( +
+ {PRODUCE_ICON_IDS.map((iconId) => ( + + ))} +
+ ); + + return ( +
+ + + + + +
+ ); +} diff --git a/packages/client/src/components/Select.css b/packages/client/src/components/Select.css new file mode 100644 index 0000000..77e507e --- /dev/null +++ b/packages/client/src/components/Select.css @@ -0,0 +1,219 @@ +/* Custom select — behaviour from HomePanel Select; visuals aligned with Input / theme tokens */ + +.select-wrap { + position: relative; + display: inline-block; + width: 100%; +} + +.select-trigger { + box-sizing: border-box; + margin: 0; + padding: 8px 12px 8px 14px; + color: var(--text); + font-family: inherit; + font-size: 0.9rem; + line-height: 1; + font-weight: 500; + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + width: 100%; + min-width: 0; + min-height: 30px; + background: var(--bg); + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 18px; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease; + cursor: pointer; + text-align: left; +} + +.select-trigger:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--accent) 45%, var(--border-ui-color)); +} + +.select-trigger:focus-visible { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); +} + +.select-trigger:disabled { + opacity: 0.55; + cursor: not-allowed; +} + +.select-trigger--open { + border-color: var(--accent); +} + +.select-value { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.select-search-input { + width: 100%; + background: transparent; + border: none; + color: var(--text); + font-family: inherit; + font-size: 0.9rem; + line-height: 1; + font-weight: 500; + padding: 0; + margin: 0; + outline: none; +} + +.select-search-input::placeholder { + color: var(--muted); + opacity: 1; +} + +.select-placeholder { + color: var(--muted); +} + +.select-chevron { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 18px; + height: 18px; + color: var(--muted); + transition: transform 0.2s ease; +} + +.select-trigger--open .select-chevron { + transform: rotate(180deg); +} + +.select-dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 1050; + margin-top: 6px; + border-radius: 18px; + background: var(--surface); + color: var(--text); + box-shadow: 0 8px 24px color-mix(in srgb, #000 22%, transparent); + max-height: 256px; + display: flex; + flex-direction: column; + overflow: hidden; + opacity: 0; + transform: translateY(-6px); + visibility: hidden; + transition: + opacity 0.2s ease, + transform 0.2s ease, + visibility 0.2s; +} + +.drawer-panel .select-dropdown { + z-index: 1500; +} + +.select-dropdown--open { + opacity: 1; + transform: translateY(0); + visibility: visible; +} + +.select-options { + flex: 1; + min-height: 0; + margin: 6px; + max-height: 220px; + border-radius: 12px; +} + +.select-options .simplebar-scrollbar::before { + background: color-mix(in srgb, var(--muted) 55%, var(--border-ui-color)); + border-radius: 4px; +} + +.select-options .simplebar-scrollbar.simplebar-visible::before { + opacity: 1; +} + +.select-options:hover .simplebar-scrollbar::before { + background: color-mix(in srgb, var(--muted) 75%, var(--text)); +} + +.select-options .simplebar-track.simplebar-vertical { + width: 8px; + right: 2px; +} + +.select-options .simplebar-content-wrapper { + border-radius: 10px; +} + +.select-option { + display: flex; + align-items: center; + padding: 8px 12px; + color: var(--text); + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: background 0.15s ease; + gap: 10px; + border-radius: 12px; + margin-bottom: 4px; +} + +.select-option:last-child { + margin-bottom: 0; +} + +.select-option:hover:not(.select-option--disabled) { + background: color-mix(in srgb, var(--text) 8%, transparent); +} + +.select-option--selected { + background: color-mix(in srgb, var(--accent) 18%, transparent); +} + +.select-option--disabled { + color: var(--muted); + opacity: 0.55; + cursor: not-allowed; +} + +.select-option--disabled:hover { + background: transparent; +} + +.select-option-label { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.select-selected-label { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.select-empty { + padding: 16px; + color: var(--muted); + text-align: center; + font-size: 0.9rem; +} diff --git a/packages/client/src/components/Select.jsx b/packages/client/src/components/Select.jsx new file mode 100644 index 0000000..005794e --- /dev/null +++ b/packages/client/src/components/Select.jsx @@ -0,0 +1,221 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import { IoChevronDown } from "react-icons/io5"; +import SimpleBar from "simplebar-react"; +import "simplebar-react/dist/simplebar.min.css"; +import "./Select.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * Custom select with optional search. onChange receives a synthetic event + * `{ target: { value, name } }` like a native select element. + * + * @param {object} props + * @param {string} props.value + * @param {(e: { target: { value: string, name?: string } }) => void} [props.onChange] + * @param {{ value: string, label: string, disabled?: boolean, search?: string }[]} [props.options] + * @param {string} [props.placeholder] + * @param {boolean} [props.disabled] + * @param {string} [props.id] + * @param {boolean} [props.searchable] + * @param {(option: object) => import('react').ReactNode} [props.renderOption] + * @param {(option: object) => import('react').ReactNode} [props.renderSelected] + * @param {string} [props.className] + * @param {string} [props.name] + */ +export function Select({ + value, + onChange, + options = [], + placeholder = "Select an option", + disabled = false, + id, + searchable = false, + renderOption, + renderSelected, + className = "", + name, +}) { + const [isOpen, setIsOpen] = useState(false); + const [searchTerm, setSearchTerm] = useState(""); + const wrapperRef = useRef(null); + const searchInputRef = useRef(null); + + const selectedOption = options.find((opt) => opt.value === value); + + const filteredOptions = + searchable && searchTerm + ? options.filter( + (opt) => + opt.label.toLowerCase().includes(searchTerm.toLowerCase()) || + opt?.search?.toLowerCase()?.includes(searchTerm.toLowerCase()), + ) + : options; + + useEffect(() => { + const handleClickOutside = (event) => { + if (wrapperRef.current && !wrapperRef.current.contains(event.target)) { + setIsOpen(false); + setSearchTerm(""); + } + }; + + if (isOpen) { + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [isOpen]); + + useEffect(() => { + if (isOpen && searchable && searchInputRef.current) { + searchInputRef.current.focus(); + } + }, [isOpen, searchable]); + + const handleKeyDown = useCallback( + (event) => { + if (disabled) return; + + switch (event.key) { + case "Enter": + case " ": + if (!isOpen) { + event.preventDefault(); + setIsOpen(true); + } + break; + case "Escape": + setIsOpen(false); + setSearchTerm(""); + break; + case "ArrowDown": + if (!isOpen) { + event.preventDefault(); + setIsOpen(true); + } + break; + default: + break; + } + }, + [disabled, isOpen], + ); + + const handleTriggerClick = () => { + if (!disabled) { + setIsOpen(!isOpen); + if (isOpen) { + setSearchTerm(""); + } + } + }; + + const handleOptionClick = (option) => { + if (option.disabled) return; + + onChange?.({ + target: { + value: option.value, + name, + }, + }); + setIsOpen(false); + setSearchTerm(""); + }; + + const handleSearchChange = (e) => { + setSearchTerm(e.target.value); + }; + + const renderSelectedContent = () => { + if (searchable && isOpen) { + return ( + e.stopPropagation()} + onFocus={(e) => e.stopPropagation()} + /> + ); + } + + if (!selectedOption) { + return {placeholder}; + } + + if (renderSelected) { + return renderSelected(selectedOption); + } + + return ( + {selectedOption.label} + ); + }; + + const renderOptionContent = (option) => { + if (renderOption) { + return renderOption(option); + } + + return {option.label}; + }; + + return ( +
+ + +
+ + {filteredOptions.length === 0 ? ( +
No options found
+ ) : ( + filteredOptions.map((option) => ( +
handleOptionClick(option)} + role="option" + aria-selected={option.value === value} + > + {renderOptionContent(option)} +
+ )) + )} +
+
+
+ ); +} diff --git a/packages/client/src/components/Sidebar.css b/packages/client/src/components/Sidebar.css new file mode 100644 index 0000000..aabc8a6 --- /dev/null +++ b/packages/client/src/components/Sidebar.css @@ -0,0 +1,265 @@ +.sidebar { + position: fixed; + left: 8vh; + top: 10vh; + bottom: 10vh; + z-index: 30; + display: flex; + flex-direction: column; + flex-shrink: 0; + box-sizing: border-box; +} + +.sidebar-container { + display: flex; + flex-direction: column; + padding: 20px 25px 25px 25px; + height: 100%; + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 35px; + background: color-mix(in srgb, var(--bg) 70%, transparent); + backdrop-filter: blur(10px); +} + +.sidebar-mobile-header { + right: 0; + margin-right: 10vw; + top: calc(10vh - 20px); + position: absolute; + z-index: 1000; + opacity: 0; + transition: + opacity 0.25s ease, + scale 0.35s cubic-bezier(0.33, 1, 0.68, 1); +} + +.sidebar-mobile-header--visible { + opacity: 1; +} + +.sidebar-brand { + margin-bottom: 10px; +} + +.sidebar-title { + margin: 0; + font-size: 28px; + text-transform: uppercase; + font-weight: 800; +} + +.sidebar-nav { + position: relative; + display: flex; + flex-direction: column; + gap: 5px; + margin: 0 -10px; +} + +.sidebar-nav-indicator { + position: absolute; + z-index: 0; + box-sizing: border-box; + border-radius: 15px; + background: color-mix(in srgb, var(--accent) 14%, transparent); + pointer-events: none; + transition: + top 0.32s cubic-bezier(0.4, 0, 0.2, 1), + left 0.32s cubic-bezier(0.4, 0, 0.2, 1), + width 0.32s cubic-bezier(0.4, 0, 0.2, 1), + height 0.32s cubic-bezier(0.4, 0, 0.2, 1), + opacity 0.2s ease; +} + +@media (prefers-reduced-motion: reduce) { + .sidebar-nav-indicator { + transition-duration: 0.01ms; + } +} + +.sidebar-link { + position: relative; + z-index: 1; + display: flex; + align-items: center; + gap: 8px; + padding: 7px 11px; + border-radius: 15px; + color: var(--text); + text-decoration: none; + font-size: 0.95rem; + transition: + background 0.15s, + color 0.15s; +} + +.sidebar-link-icon-box { + box-sizing: border-box; + flex-shrink: 0; + width: 18px; + min-width: 18px; + display: inline-flex; + align-items: center; + justify-content: center; + align-self: center; +} + +.sidebar-link-icon { + flex-shrink: 0; + width: 18px; + height: 18px; + opacity: 0.88; +} + +.sidebar-link-text { + font-size: 14px; + font-weight: 400; +} + +.sidebar-link--active .sidebar-link-icon { + opacity: 1; +} + +.sidebar-link:hover:not(.sidebar-link--active) { + background: var(--link-hover); +} + +.sidebar-link--active, +.sidebar-link--active:hover { + color: var(--accent); +} + +.sidebar-divider { + height: 0; + margin: 1rem 0; + border: 0; + border-top: var(--border-ui-width) solid var(--border-ui-color); +} + +.sidebar-footer { + margin-top: auto; + padding-top: 1.5rem; + border-top: var(--border-ui-width) solid var(--border-ui-color); +} + +.sidebar-footer .auth { + align-items: flex-start; +} + +.sidebar.sidebar--mobile-bottom { + left: calc(var(--app-main-padding-left) / 2); + right: calc(var(--app-main-padding-right) / 2); + + margin-bottom: calc(var(--app-main-padding-right) / 2); + bottom: 0; + top: auto; + width: auto; + height: auto; +} + +.sidebar.sidebar--mobile-bottom .sidebar-container { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + grid-template-rows: auto auto; + align-items: center; + padding: 12px; + height: auto; + border-radius: 40px; +} + +.sidebar.sidebar--mobile-bottom .sidebar-brand { + grid-column: 1; + grid-row: 1; + margin-bottom: 0; + min-width: 0; +} + +.sidebar.sidebar--mobile-bottom .sidebar-title { + font-size: 0.8rem; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sidebar.sidebar--mobile-bottom .sidebar-brand .sub { + margin-top: 0.2rem; + font-size: 0.68rem; +} + +.sidebar.sidebar--mobile-bottom .sidebar-nav { + grid-column: 1 / -1; + grid-row: 2; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + gap: 4px; + margin: 0; +} + +.sidebar.sidebar--mobile-bottom .sidebar-nav .sidebar-link-icon-box { + width: 38px; + min-width: 38px; +} + +.sidebar.sidebar--mobile-bottom .sidebar-nav .sidebar-link-icon { + width: 38px; + height: 38px; +} + +.sidebar.sidebar--mobile-bottom .sidebar-nav-indicator { + border-radius: 25px; +} + +.sidebar.sidebar--mobile-bottom .sidebar-link { + flex: 1 1 0; + min-width: 0; + flex-direction: column; + justify-content: center; + gap: 4px; + padding: 8px 4px; + border-radius: 25px; + text-align: center; +} + +.sidebar.sidebar--mobile-bottom .sidebar-link-text { + font-size: 0.62rem; + font-weight: 500; + line-height: 1.15; + display: -webkit-box; + line-clamp: 2; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.sidebar.sidebar--mobile-bottom .sidebar-footer { + grid-column: 2; + grid-row: 1; + margin-top: 0; + padding-top: 0; + border-top: none; + justify-self: end; + align-self: center; +} + +.sidebar.sidebar--mobile-bottom .sidebar-footer .auth { + align-items: center; + flex-direction: row; + flex-wrap: nowrap; + gap: 8px; +} + +.sidebar.sidebar--mobile-bottom .sidebar-footer .user { + display: none; +} + +.sidebar.sidebar--mobile-bottom .sidebar-footer .btn { + padding: 6px 10px; + font-size: 0.75rem; + white-space: nowrap; +} + +.sidebar.sidebar--mobile-bottom.sidebar--drawer-open { + transform-origin: 50% 100%; +} diff --git a/packages/client/src/components/Sidebar.jsx b/packages/client/src/components/Sidebar.jsx new file mode 100644 index 0000000..2239f72 --- /dev/null +++ b/packages/client/src/components/Sidebar.jsx @@ -0,0 +1,226 @@ +import { useCallback, useLayoutEffect, useRef, useState } from "react"; +import { matchPath, NavLink, useLocation } from "react-router-dom"; +import { + MdElectricBolt, + MdGridView, + MdWaterDrop, + MdPerson, +} from "react-icons/md"; +import { HiClock } from "react-icons/hi2"; +import { BiSolidBolt, BiWater } from "react-icons/bi"; +import { FaHandHoldingWater } from "react-icons/fa"; +import { PiPlantFill } from "react-icons/pi"; +import { FaGlassWaterDroplet } from "react-icons/fa6"; +import { Button } from "./Button.jsx"; +import { Flex } from "./Flex.jsx"; +import { useAuth } from "../contexts/AuthContext.jsx"; +import { useApi } from "../contexts/ApiContext.jsx"; +import { useTheme } from "../contexts/ThemeContext.jsx"; +import "./Sidebar.css"; + +// Each link: optional iconSize / mobileIconSize (px). Desktop: 18px-wide box, default 18×18 icon. Mobile bottom nav: 38px box, default 38×38. Smaller glyphs center in the box. +const MAIN_LINKS = [ + { path: "/patches", label: "Patches", Icon: PiPlantFill, mobileIconSize: 42 }, + { + path: "/water-tank", + label: "Water tank", + Icon: FaGlassWaterDroplet, + iconSize: 17, + mobileIconSize: 34, + }, + { + path: "/power", + label: "Power", + Icon: BiSolidBolt, + iconSize: 22, + mobileIconSize: 42, + }, + { + path: "/watering-sessions", + label: "Watering sessions", + Icon: MdWaterDrop, + mobileIconSize: 40, + }, + { + path: "/water-schedules", + label: "Watering schedules", + Icon: HiClock, + mobileIconSize: 40, + }, +]; + +function getSidebarLinkIconStyle(link, isMobile) { + const px = isMobile ? link.mobileIconSize : link.iconSize; + if (px == null) return undefined; + return { width: px, height: px }; +} + +export function Sidebar() { + const { user } = useAuth(); + const { isConnected } = useApi(); + const { isMobile } = useTheme(); + const location = useLocation(); + const pathname = + location.pathname.length > 1 && location.pathname.endsWith("/") + ? location.pathname.slice(0, -1) + : location.pathname; + const isPatchesPage = pathname === "/patches"; + + const activeNavIndex = MAIN_LINKS.findIndex( + ({ path }) => matchPath({ path, end: false }, pathname) != null, + ); + + const navRef = useRef(null); + const linkRefs = useRef([]); + const [navIndicator, setNavIndicator] = useState({ + top: 0, + left: 0, + width: 0, + height: 0, + visible: false, + }); + + const updateNavIndicator = useCallback(() => { + const nav = navRef.current; + if (!nav) return; + if (activeNavIndex < 0) { + setNavIndicator((s) => ({ ...s, visible: false })); + return; + } + const link = linkRefs.current[activeNavIndex]; + if (!link) return; + const nr = nav.getBoundingClientRect(); + const lr = link.getBoundingClientRect(); + setNavIndicator({ + top: lr.top - nr.top + nav.scrollTop, + left: lr.left - nr.left + nav.scrollLeft, + width: lr.width, + height: lr.height, + visible: true, + }); + }, [activeNavIndex]); + + useLayoutEffect(() => { + updateNavIndicator(); + }, [updateNavIndicator, pathname, isMobile]); + + useLayoutEffect(() => { + const nav = navRef.current; + if (!nav || typeof ResizeObserver === "undefined") return; + const ro = new ResizeObserver(() => updateNavIndicator()); + ro.observe(nav); + for (const el of linkRefs.current) { + if (el) ro.observe(el); + } + window.addEventListener("resize", updateNavIndicator); + return () => { + ro.disconnect(); + window.removeEventListener("resize", updateNavIndicator); + }; + }, [updateNavIndicator]); + + const footerContent = ( + + {user === undefined ? null : user ? ( + <> + + + + + {!isMobile && {user.name || user.sub}} + + + + ) : ( + + )} + + ); + + return ( + <> + {isMobile && ( +
+ {footerContent} +
+ )} + + + ); +} diff --git a/packages/client/src/components/Slider.css b/packages/client/src/components/Slider.css new file mode 100644 index 0000000..8b0ba8b --- /dev/null +++ b/packages/client/src/components/Slider.css @@ -0,0 +1,93 @@ +.slider-wrap { + position: relative; + width: 100%; + height: 100%; + padding: 2px 7px; +} + +.slider { + box-sizing: border-box; + position: relative; + width: 100%; + height: 12px; + touch-action: none; + cursor: default; +} + +.slider--disabled { + opacity: 0.45; + cursor: not-allowed; + pointer-events: none; +} + +.slider__rail { + position: absolute; + left: 0; + right: 0; + top: 50%; + transform: translateY(-50%); + height: 4px; + border-radius: 2px; + background-color: color-mix(in srgb, var(--text) 12%, transparent); +} + +.slider__track { + position: absolute; + top: 50%; + transform: translateY(-50%); + height: 4px; + border-radius: 2px; + background-color: var(--accent); +} + +.slider__rail-hit { + position: absolute; + left: 0; + right: 0; + top: 50%; + transform: translateY(-50%); + height: 16px; + margin-top: -8px; + border-radius: 4px; + cursor: pointer; +} + +.slider--disabled .slider__rail-hit { + cursor: not-allowed; +} + +.slider__handle { + position: absolute; + top: 50%; + width: 14px; + height: 14px; + margin-top: -7px; + margin-left: -7px; + border: 2px solid var(--accent); + border-radius: 50%; + background-color: var(--bg); + box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 12%, transparent); + cursor: grab; + z-index: 1; + transition: + border-color 0.15s ease, + box-shadow 0.15s ease; +} + +.slider:not(.slider--disabled) .slider__handle:hover { + border-color: color-mix(in srgb, var(--accent) 85%, var(--text)); +} + +.slider__handle:focus { + outline: none; +} + +.slider__handle:focus-visible { + box-shadow: + 0 0 0 2px var(--bg), + 0 0 0 4px color-mix(in srgb, var(--accent) 35%, transparent); +} + +.slider:not(.slider--disabled) .slider__handle:active { + cursor: grabbing; +} diff --git a/packages/client/src/components/Slider.jsx b/packages/client/src/components/Slider.jsx new file mode 100644 index 0000000..a1657a1 --- /dev/null +++ b/packages/client/src/components/Slider.jsx @@ -0,0 +1,230 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import "./Slider.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +function clamp(n, min, max) { + return Math.min(max, Math.max(min, n)); +} + +/** + * @param {number} clientX + * @param {DOMRect} rect + * @param {number} min + * @param {number} max + * @param {number} step + */ +function valueFromPointer(clientX, rect, min, max, step) { + if (rect.width <= 0) return min; + const t = (clientX - rect.left) / rect.width; + const raw = min + t * (max - min); + if (step > 0) { + const steps = Math.round((raw - min) / step); + return clamp(min + steps * step, min, max); + } + return clamp(raw, min, max); +} + +/** + * Ant Design–like single-value horizontal slider (no antd/rc-slider). + * + * @param {object} props + * @param {number} [props.min=0] + * @param {number} [props.max=100] + * @param {number} props.value + * @param {(n: number) => void} props.onChange + * @param {number} [props.step=1] + * @param {boolean} [props.disabled] + * @param {string} [props.className] + * @param {string} [props.id] — forwarded to the handle for label association + * @param {string} [props['aria-labelledby']] + * @param {string} [props['aria-label']] + */ +export function Slider({ + min = 0, + max = 100, + value, + onChange, + step = 1, + disabled = false, + className, + id, + "aria-labelledby": ariaLabelledBy, + "aria-label": ariaLabel, +}) { + const wrapRef = useRef(null); + const draggingRef = useRef(false); + const [focused, setFocused] = useState(false); + + const lo = Math.min(min, max); + const hi = Math.max(min, max); + const safeStep = step > 0 ? step : 1; + + const clamped = useMemo(() => { + const n = Number(value); + if (!Number.isFinite(n)) return lo; + if (safeStep > 0) { + const steps = Math.round((n - lo) / safeStep); + return clamp(lo + steps * safeStep, lo, hi); + } + return clamp(n, lo, hi); + }, [value, lo, hi, safeStep]); + + const percent = hi === lo ? 0 : ((clamped - lo) / (hi - lo)) * 100; + + const emitFromClientX = useCallback( + (clientX) => { + const el = wrapRef.current; + if (!el || disabled) return; + const rect = el.getBoundingClientRect(); + const next = valueFromPointer(clientX, rect, lo, hi, safeStep); + if (next !== clamped) onChange(next); + }, + [clamped, disabled, hi, lo, onChange, safeStep], + ); + + const onRailPointerDown = useCallback( + (e) => { + if (disabled || e.button !== 0) return; + e.preventDefault(); + e.currentTarget.setPointerCapture(e.pointerId); + draggingRef.current = true; + emitFromClientX(e.clientX); + }, + [disabled, emitFromClientX], + ); + + const onRailPointerMove = useCallback( + (e) => { + if (!draggingRef.current || disabled) return; + emitFromClientX(e.clientX); + }, + [disabled, emitFromClientX], + ); + + const onRailPointerUp = useCallback((e) => { + if (draggingRef.current) { + try { + e.currentTarget.releasePointerCapture(e.pointerId); + } catch { + /* ignore */ + } + } + draggingRef.current = false; + }, []); + + const onHandlePointerDown = useCallback( + (e) => { + e.stopPropagation(); + if (disabled || e.button !== 0) return; + e.preventDefault(); + const rail = wrapRef.current?.querySelector(".slider__rail-hit"); + if (rail) { + rail.setPointerCapture(e.pointerId); + draggingRef.current = true; + } + emitFromClientX(e.clientX); + }, + [disabled, emitFromClientX], + ); + + const onKeyDown = useCallback( + (e) => { + if (disabled) return; + let delta = 0; + const page = hi - lo; + const big = Math.max(safeStep, page / 10); + switch (e.key) { + case "ArrowRight": + case "ArrowUp": + delta = safeStep; + break; + case "ArrowLeft": + case "ArrowDown": + delta = -safeStep; + break; + case "Home": + e.preventDefault(); + onChange(lo); + return; + case "End": + e.preventDefault(); + onChange(hi); + return; + case "PageUp": + delta = big; + break; + case "PageDown": + delta = -big; + break; + default: + return; + } + e.preventDefault(); + const next = clamp(clamped + delta, lo, hi); + if (safeStep > 0) { + const steps = Math.round((next - lo) / safeStep); + onChange(clamp(lo + steps * safeStep, lo, hi)); + } else { + onChange(next); + } + }, + [clamped, disabled, hi, lo, onChange, safeStep], + ); + + useEffect(() => { + if (!focused) return; + const onDocPointerUp = () => { + draggingRef.current = false; + }; + document.addEventListener("pointerup", onDocPointerUp); + document.addEventListener("pointercancel", onDocPointerUp); + return () => { + document.removeEventListener("pointerup", onDocPointerUp); + document.removeEventListener("pointercancel", onDocPointerUp); + }; + }, [focused]); + + return ( +
+
+
+
+
+
setFocused(true)} + onBlur={() => setFocused(false)} + /> +
+
+ ); +} diff --git a/packages/client/src/components/Switch.css b/packages/client/src/components/Switch.css new file mode 100644 index 0000000..e030e8e --- /dev/null +++ b/packages/client/src/components/Switch.css @@ -0,0 +1,167 @@ +/* Ant Design–like switch; uses app :root tokens (App.css) */ + +.switch { + appearance: none; + -webkit-appearance: none; + box-sizing: border-box; + margin: 0; + padding: 0; + border: none; + background: transparent; + cursor: pointer; + vertical-align: middle; + flex-shrink: 0; + line-height: 1; + font: inherit; + color: inherit; +} + +.switch:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.switch__track { + position: relative; + display: block; + box-sizing: border-box; + min-width: 44px; + width: 44px; + height: 22px; + border-radius: 100px; + background: color-mix(in srgb, var(--text) 22%, transparent); + transition: + background-color 0.2s ease, + min-width 0.2s ease, + width 0.2s ease; +} + +.switch--checked .switch__track { + background: var(--accent); +} + +.switch--with-inner .switch__track { + min-width: 52px; + width: auto; + padding-inline: 2px; +} + +.switch--small.switch--with-inner .switch__track { + min-width: 40px; +} + +.switch--disabled { + cursor: not-allowed; + opacity: 0.45; +} + +.switch--disabled .switch__track { + cursor: not-allowed; +} + +.switch--loading { + cursor: default; +} + +.switch--small .switch__track { + min-width: 28px; + width: 28px; + height: 16px; +} + +.switch__handle { + position: absolute; + top: 2px; + left: 2px; + width: 18px; + height: 18px; + border-radius: 50%; + background: var(--bg); + box-shadow: 0 1px 3px color-mix(in srgb, #000 35%, transparent); + transition: left 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + z-index: 2; +} + +.switch--small .switch__handle { + width: 12px; + height: 12px; + top: 2px; + left: 2px; +} + +.switch--checked .switch__handle { + left: calc(100% - 20px); +} + +.switch--small.switch--checked .switch__handle { + left: calc(100% - 14px); +} + +.switch__loading-icon { + flex-shrink: 0; +} + +.switch--checked .switch__loading-icon path { + fill: var(--accent); +} + +.switch:not(.switch--checked) .switch__loading-icon path { + fill: var(--text); +} + +.switch__inner { + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + overflow: hidden; + border-radius: inherit; +} + +.switch__inner-text { + position: absolute; + inset: 0; + display: flex; + align-items: center; + font-size: 12px; + font-weight: 500; + line-height: 1; + white-space: nowrap; + opacity: 0; + transition: opacity 0.2s ease; + color: var(--on-accent); +} + +.switch--small .switch__inner-text { + font-size: 11px; +} + +.switch__inner-text--checked { + padding-left: 8px; + padding-right: 22px; + justify-content: flex-start; +} + +.switch__inner-text--unchecked { + padding-left: 22px; + padding-right: 8px; + justify-content: flex-end; + color: color-mix(in srgb, var(--text) 88%, transparent); +} + +.switch__inner-text--visible { + opacity: 1; +} + +.switch--small .switch__inner-text--checked { + padding-left: 5px; + padding-right: 16px; +} + +.switch--small .switch__inner-text--unchecked { + padding-left: 16px; + padding-right: 5px; +} diff --git a/packages/client/src/components/Switch.jsx b/packages/client/src/components/Switch.jsx new file mode 100644 index 0000000..fd34855 --- /dev/null +++ b/packages/client/src/components/Switch.jsx @@ -0,0 +1,133 @@ +import { useCallback, useState } from "react"; +import { LoadingIcon } from "./LoadingIcon"; +import "./Switch.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * Ant Design–like toggle switch (no antd). Controlled or uncontrolled. + * + * @param {object} props + * @param {boolean} [props.checked] — controlled + * @param {boolean} [props.defaultChecked=false] — uncontrolled initial + * @param {(checked: boolean, e: import('react').MouseEvent) => void} [props.onChange] + * @param {(e: import('react').MouseEvent) => void} [props.onClick] + * @param {boolean} [props.disabled] + * @param {boolean} [props.loading] + * @param {'default' | 'small'} [props.size='default'] + * @param {import('react').ReactNode} [props.checkedChildren] + * @param {import('react').ReactNode} [props.unCheckedChildren] + * @param {string} [props.className] + * @param {string} [props.id] + */ +export function Switch({ + checked, + defaultChecked = false, + onChange, + onClick, + disabled = false, + loading = false, + size = "default", + checkedChildren, + unCheckedChildren, + className, + id, + ...rest +}) { + const controlled = checked !== undefined; + const [innerChecked, setInnerChecked] = useState(defaultChecked); + const mergedChecked = controlled ? Boolean(checked) : innerChecked; + + const mergedDisabled = disabled || loading; + + const toggle = useCallback( + (e) => { + if (mergedDisabled) return; + const next = !mergedChecked; + if (!controlled) setInnerChecked(next); + onChange?.(next, e); + }, + [controlled, mergedChecked, mergedDisabled, onChange], + ); + + const handleClick = useCallback( + (e) => { + onClick?.(e); + if (e.defaultPrevented) return; + toggle(e); + }, + [onClick, toggle], + ); + + const hasInner = checkedChildren != null || unCheckedChildren != null; + + return ( + + ); +} diff --git a/packages/client/src/components/Table.css b/packages/client/src/components/Table.css new file mode 100644 index 0000000..278a8ed --- /dev/null +++ b/packages/client/src/components/Table.css @@ -0,0 +1,34 @@ +.ta-table-wrap { + width: 100%; + overflow-x: auto; +} + +.ta-table { + width: 100%; + border-collapse: collapse; + font-size: 0.9rem; +} + +.ta-table th, +.ta-table td { + padding: 0.65rem 1rem; + text-align: left; + border-bottom: var(--border-ui-width) solid var(--border-ui-color); +} + +.ta-table th { + font-size: 0.75rem; + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.05em; + background: rgba(0, 0, 0, 0.2); +} + +.ta-table tbody tr:last-child td { + border-bottom: none; +} + +.ta-table tbody tr:hover td { + background: rgba(255, 255, 255, 0.03); +} diff --git a/packages/client/src/components/Table.jsx b/packages/client/src/components/Table.jsx new file mode 100644 index 0000000..d2a66c4 --- /dev/null +++ b/packages/client/src/components/Table.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import "./Table.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +/** + * @param {object} props + * @param {import('react').ReactNode} [props.children] + * @param {string} [props.className] + */ +export function Table({ className, children, ...rest }) { + return ( +
+ + {children} +
+
+ ); +} diff --git a/packages/client/src/components/TemperatureHumidityDisplay.css b/packages/client/src/components/TemperatureHumidityDisplay.css new file mode 100644 index 0000000..dedd813 --- /dev/null +++ b/packages/client/src/components/TemperatureHumidityDisplay.css @@ -0,0 +1,13 @@ +.temperature-humidity-display { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; +} + +.temperature-humidity-stat { + display: flex; + flex-direction: row; + align-items: center; + gap: 3px; +} diff --git a/packages/client/src/components/TemperatureHumidityDisplay.jsx b/packages/client/src/components/TemperatureHumidityDisplay.jsx new file mode 100644 index 0000000..877daa7 --- /dev/null +++ b/packages/client/src/components/TemperatureHumidityDisplay.jsx @@ -0,0 +1,31 @@ +import React from "react"; +import { MdThermostat, MdWaterDrop } from "react-icons/md"; +import "./TemperatureHumidityDisplay.css"; + +export function TemperatureHumidityDisplay({ + soilTemperature, + soilHumidity, + coloredIcons = true, +}) { + const thermostatStyle = coloredIcons + ? { color: "#FF9230" } + : { color: "currentColor" }; + const waterStyle = coloredIcons + ? { color: "#3CD3FE", marginRight: "2px" } + : { color: "currentColor", marginRight: "2px" }; + + return ( +
+
+ + {soilTemperature != null + ? `${soilTemperature.toFixed(1)}°C` + : "—"} +
+
+ + {soilHumidity != null ? `${Math.round(soilHumidity)}%` : "—"} +
+
+ ); +} diff --git a/packages/client/src/components/TextArea.css b/packages/client/src/components/TextArea.css new file mode 100644 index 0000000..3c65548 --- /dev/null +++ b/packages/client/src/components/TextArea.css @@ -0,0 +1,246 @@ +@import "./Input.css"; + +/* Ant Design–style multiline field; shares Input border, radius, focus ring */ + +.textarea-affix-wrapper { + display: inline-flex; + align-items: flex-start; + width: 100%; + min-width: 0; + padding-block: 0; + gap: 8px; + box-sizing: border-box; + font-family: inherit; + font-size: 0.9rem; + line-height: 1.5715; + font-weight: 500; + color: var(--text); + background-color: var(--bg); + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 18px; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease; +} + +.textarea-affix-wrapper:hover:not(.textarea-affix-wrapper--disabled) { + border-color: color-mix(in srgb, var(--accent) 45%, var(--border-ui-color)); +} + +.textarea-affix-wrapper:focus-within:not(.textarea-affix-wrapper--disabled) { + border-color: var(--accent); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); +} + +.textarea-affix-wrapper--sm { + font-size: 0.8rem; + line-height: 1.5715; +} + +.textarea-affix-wrapper--sm .textarea-affix-inner { + padding: 6px 10px; + min-height: 52px; +} + +.textarea-affix-wrapper--md .textarea-affix-inner { + padding: 8px 14px; + min-height: 64px; +} + +.textarea-affix-wrapper--lg { + font-size: 1rem; +} + +.textarea-affix-wrapper--lg .textarea-affix-inner { + padding: 10px 16px; + min-height: 76px; +} + +.textarea-affix-wrapper--borderless { + border-color: transparent; + background-color: color-mix(in srgb, var(--text) 4%, transparent); +} + +.textarea-affix-wrapper--borderless:hover:not(.textarea-affix-wrapper--disabled) { + background-color: color-mix(in srgb, var(--text) 7%, transparent); +} + +.textarea-affix-wrapper--borderless:focus-within:not(.textarea-affix-wrapper--disabled) { + background-color: var(--bg); +} + +.textarea-affix-wrapper--error { + border-color: color-mix(in srgb, #ff4d4f 70%, var(--border-ui-color)); +} + +.textarea-affix-wrapper--error:focus-within { + border-color: #ff4d4f; + box-shadow: 0 0 0 2px color-mix(in srgb, #ff4d4f 22%, transparent); +} + +.textarea-affix-wrapper--warning { + border-color: color-mix(in srgb, #faad14 65%, var(--border-ui-color)); +} + +.textarea-affix-wrapper--warning:focus-within { + border-color: #faad14; + box-shadow: 0 0 0 2px color-mix(in srgb, #faad14 22%, transparent); +} + +.textarea-affix-wrapper--disabled { + opacity: 0.55; + cursor: not-allowed; + background-color: color-mix(in srgb, var(--text) 5%, var(--bg)); +} + +.textarea-affix-inner { + flex: 1 1 auto; + min-width: 0; + width: 100%; + border: none; + outline: none; + background: transparent; + color: inherit; + font: inherit; + line-height: inherit; + resize: vertical; + margin: 0; + appearance: none; + -webkit-appearance: none; + box-sizing: border-box; + display: block; +} + +.textarea-affix-inner::placeholder { + color: var(--muted); + opacity: 1; +} + +.textarea-affix-wrapper--disabled .textarea-affix-inner { + cursor: not-allowed; + color: var(--muted); +} + +.textarea-affix-wrapper .input-suffix { + align-self: flex-start; + margin-top: 6px; +} + +.textarea-affix-wrapper--sm .input-suffix { + margin-top: 4px; +} + +.textarea-affix-wrapper--lg .input-suffix { + margin-top: 8px; +} + +/* Standalone textarea (no affix) — same look as .input */ +.textarea { + box-sizing: border-box; + font-family: inherit; + font-size: 0.9rem; + line-height: 1.5715; + font-weight: 500; + color: var(--text); + background-color: var(--bg); + border: var(--border-ui-width) solid var(--border-ui-color); + border-radius: 18px; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease; + display: block; + width: 100%; + min-width: 0; + margin: 0; + vertical-align: top; + outline: none; + appearance: none; + -webkit-appearance: none; + resize: vertical; +} + +.textarea::placeholder { + color: var(--muted); + opacity: 1; +} + +.textarea:hover:not(:disabled):not(:read-only) { + border-color: color-mix(in srgb, var(--accent) 45%, var(--border-ui-color)); +} + +.textarea:focus-visible { + border-color: var(--accent); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); +} + +.textarea--borderless { + border-color: transparent; + background-color: color-mix(in srgb, var(--text) 4%, transparent); +} + +.textarea--borderless:hover:not(:disabled):not(:read-only) { + background-color: color-mix(in srgb, var(--text) 7%, transparent); +} + +.textarea--borderless:focus-visible { + background-color: var(--bg); +} + +.textarea--sm { + font-size: 0.8rem; + padding: 6px 10px; + min-height: 52px; +} + +.textarea--md { + font-size: 0.9rem; + padding: 8px 14px; + min-height: 64px; +} + +.textarea--lg { + font-size: 1rem; + padding: 10px 16px; + min-height: 76px; +} + +.textarea--error { + border-color: color-mix(in srgb, #ff4d4f 70%, var(--border-ui-color)); +} + +.textarea--error:focus-visible { + border-color: #ff4d4f; + box-shadow: 0 0 0 2px color-mix(in srgb, #ff4d4f 22%, transparent); +} + +.textarea--warning { + border-color: color-mix(in srgb, #faad14 65%, var(--border-ui-color)); +} + +.textarea--warning:focus-visible { + border-color: #faad14; + box-shadow: 0 0 0 2px color-mix(in srgb, #faad14 22%, transparent); +} + +.textarea:disabled { + opacity: 0.55; + cursor: not-allowed; + background-color: color-mix(in srgb, var(--text) 5%, var(--bg)); +} + +.textarea:read-only:not(:disabled) { + cursor: default; +} + +.textarea-count { + display: block; + text-align: right; + font-size: 0.75rem; + font-weight: 500; + color: var(--muted); + margin-top: 4px; +} + +.textarea-count--error { + color: #ff4d4f; +} diff --git a/packages/client/src/components/TextArea.jsx b/packages/client/src/components/TextArea.jsx new file mode 100644 index 0000000..96985cd --- /dev/null +++ b/packages/client/src/components/TextArea.jsx @@ -0,0 +1,269 @@ +import { + forwardRef, + useCallback, + useEffect, + useLayoutEffect, + useRef, + useState, +} from "react"; +import { IoCloseCircle } from "react-icons/io5"; +import "./TextArea.css"; + +function cx(...parts) { + return parts.filter(Boolean).join(" "); +} + +const sizeClass = { + small: "sm", + middle: "md", + large: "lg", +}; + +/** + * Ant Design–like controlled/uncontrolled textarea (Input.TextArea style). + * + * @param {object} props + * @param {string} [props.value] + * @param {string} [props.defaultValue] + * @param {(e: import('react').ChangeEvent) => void} [props.onChange] + * @param {(e: import('react').KeyboardEvent) => void} [props.onPressEnter] + * @param {string} [props.placeholder] + * @param {boolean} [props.disabled] + * @param {boolean} [props.readOnly] + * @param {boolean} [props.allowClear] + * @param {boolean} [props.bordered=true] + * @param {'large' | 'middle' | 'small'} [props.size='middle'] + * @param {'' | 'error' | 'warning'} [props.status] + * @param {number} [props.rows=4] + * @param {boolean | { minRows?: number, maxRows?: number }} [props.autoSize] + * @param {boolean} [props.showCount] + * @param {number} [props.maxLength] + * @param {import('react').ReactNode} [props.suffix] + * @param {string} [props.className] + */ +export const TextArea = forwardRef(function TextArea( + { + value, + defaultValue, + onChange, + onPressEnter, + placeholder, + disabled = false, + readOnly = false, + allowClear = false, + bordered = true, + size = "middle", + status, + rows = 4, + autoSize = false, + showCount = false, + maxLength, + suffix, + className, + name, + id, + style, + onKeyDown: onKeyDownProp, + ...rest + }, + ref, +) { + const sz = sizeClass[size] ?? "md"; + const innerRef = useRef(null); + const setRefs = useCallback( + (node) => { + innerRef.current = node; + if (typeof ref === "function") ref(node); + else if (ref) ref.current = node; + }, + [ref], + ); + + const isControlled = value !== undefined; + const [innerValue, setInnerValue] = useState(() => defaultValue ?? ""); + + useEffect(() => { + if (!isControlled && defaultValue !== undefined) { + setInnerValue(defaultValue); + } + }, [defaultValue, isControlled]); + + const displayValue = isControlled ? value ?? "" : innerValue; + + const emitChange = useCallback( + (next, event) => { + if (!isControlled) setInnerValue(next); + if (onChange && event) { + const target = Object.assign({}, event.target, { value: next }); + const synthetic = Object.assign({}, event, { + target, + currentTarget: target, + }); + onChange(synthetic); + } + }, + [isControlled, onChange], + ); + + const handleChange = (e) => { + emitChange(e.target.value, e); + }; + + const handleClear = (e) => { + e.preventDefault(); + const el = innerRef.current; + if (el && !disabled && !readOnly) { + const synthetic = { + type: "change", + target: { value: "" }, + currentTarget: { value: "" }, + }; + emitChange("", synthetic); + el.focus(); + } + }; + + const handleKeyDown = (e) => { + onKeyDownProp?.(e); + if ( + onPressEnter && + e.key === "Enter" && + !e.nativeEvent.isComposing && + !e.shiftKey + ) { + e.preventDefault(); + onPressEnter(e); + } + }; + + const minRows = + autoSize && typeof autoSize === "object" ? autoSize.minRows : undefined; + const maxRows = + autoSize && typeof autoSize === "object" ? autoSize.maxRows : undefined; + + useLayoutEffect(() => { + if (!autoSize || !innerRef.current) return; + const el = innerRef.current; + const cs = getComputedStyle(el); + const lineHeight = parseFloat(cs.lineHeight) || 22; + const padY = + parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom) || 16; + const minH = + minRows != null + ? minRows * lineHeight + padY + : parseFloat(cs.minHeight) || 64; + const maxH = + maxRows != null ? maxRows * lineHeight + padY : Number.POSITIVE_INFINITY; + el.style.height = "auto"; + const next = Math.min(maxH, Math.max(minH, el.scrollHeight)); + el.style.height = `${next}px`; + el.style.overflowY = el.scrollHeight > maxH ? "auto" : "hidden"; + }, [autoSize, displayValue, minRows, maxRows]); + + const statusMod = + status === "error" + ? "error" + : status === "warning" + ? "warning" + : null; + + const showAffix = Boolean(suffix || allowClear); + const showClear = + allowClear && + !disabled && + !readOnly && + String(displayValue).length > 0; + + const shared = { + ref: setRefs, + id, + name, + disabled, + readOnly, + placeholder, + maxLength: maxLength != null ? maxLength : undefined, + value: displayValue, + onChange: handleChange, + onKeyDown: handleKeyDown, + rows: autoSize ? 1 : rows, + "aria-invalid": status === "error" || undefined, + ...rest, + }; + + const countStr = + maxLength != null + ? `${String(displayValue).length} / ${maxLength}` + : `${String(displayValue).length}`; + + const field = showAffix ? ( + +