git commit -m "feat(docs): add dual Docusaurus sites with custom branding and Giscus integration
- Split documentation into separate User and Developer sites - Migrated existing docs to proper Docusaurus structure - Added custom Tibber-themed header logos (light + dark mode variants) - Implemented custom color scheme matching integration branding - Hero gradient: Cyan → Dark Cyan → Gold - Removed standard Docusaurus purple/green theme - Integrated Giscus comments system for community collaboration - User docs: Comments enabled on guides, examples, FAQ - User docs: Comments disabled on reference pages (glossary, sensors, troubleshooting) - Developer docs: No comments (GitHub Issues/PRs preferred) - Added categorized sidebars with emoji navigation - Created 8 new placeholder documentation pages - Fixed image paths for baseUrl compatibility (local + GitHub Pages) - Escaped MDX special characters in performance metrics - Added GitHub Actions workflow for automated deployment - Created helper scripts: dev-user, dev-developer, build-all Breaking changes: - Moved /docs/user/*.md to /docs/user/docs/*.md - Moved /docs/development/*.md to /docs/developer/docs/*.md
|
|
@ -7,12 +7,22 @@
|
|||
"PYTHONASYNCIODEBUG": "1"
|
||||
},
|
||||
"forwardPorts": [
|
||||
8123
|
||||
8123,
|
||||
3000,
|
||||
3001
|
||||
],
|
||||
"portsAttributes": {
|
||||
"8123": {
|
||||
"label": "Home Assistant",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"3000": {
|
||||
"label": "Docusaurus User Docs",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"3001": {
|
||||
"label": "Docusaurus Developer Docs",
|
||||
"onAutoForward": "notify"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
|
|
|
|||
133
.github/workflows/docusaurus.yml
vendored
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
name: Deploy Docusaurus Documentation (Dual Sites)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/docusaurus.yml'
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build and Deploy Documentation Sites
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Needed for version timestamps
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
# USER DOCS BUILD
|
||||
- name: Install user docs dependencies
|
||||
working-directory: docs/user
|
||||
run: npm ci
|
||||
|
||||
- name: Create user docs version snapshot on tag
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
working-directory: docs/user
|
||||
run: |
|
||||
TAG_VERSION=${GITHUB_REF#refs/tags/}
|
||||
echo "Creating user documentation version: $TAG_VERSION"
|
||||
|
||||
npm run docusaurus docs:version $TAG_VERSION || echo "Version already exists"
|
||||
|
||||
# Update GitHub links in versioned docs
|
||||
if [ -d "versioned_docs/version-$TAG_VERSION" ]; then
|
||||
find versioned_docs/version-$TAG_VERSION -name "*.md" -type f -exec sed -i "s|github.com/jpawlowski/hass.tibber_prices/blob/main/|github.com/jpawlowski/hass.tibber_prices/blob/$TAG_VERSION/|g" {} \; || true
|
||||
fi
|
||||
|
||||
- name: Cleanup old user docs versions
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
working-directory: docs/user
|
||||
run: |
|
||||
chmod +x ../cleanup-old-versions.sh
|
||||
# Adapt script for single-instance mode (versioned_docs/ instead of user_versioned_docs/)
|
||||
sed 's/user_versioned_docs/versioned_docs/g; s/user_versions.json/versions.json/g; s/developer_versioned_docs/versioned_docs/g; s/developer_versions.json/versions.json/g' ../cleanup-old-versions.sh > cleanup-single.sh
|
||||
chmod +x cleanup-single.sh
|
||||
./cleanup-single.sh
|
||||
|
||||
- name: Build user docs website
|
||||
working-directory: docs/user
|
||||
run: npm run build
|
||||
|
||||
# DEVELOPER DOCS BUILD
|
||||
- name: Install developer docs dependencies
|
||||
working-directory: docs/developer
|
||||
run: npm ci
|
||||
|
||||
- name: Create developer docs version snapshot on tag
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
working-directory: docs/developer
|
||||
run: |
|
||||
TAG_VERSION=${GITHUB_REF#refs/tags/}
|
||||
echo "Creating developer documentation version: $TAG_VERSION"
|
||||
|
||||
npm run docusaurus docs:version $TAG_VERSION || echo "Version already exists"
|
||||
|
||||
# Update GitHub links in versioned docs
|
||||
if [ -d "versioned_docs/version-$TAG_VERSION" ]; then
|
||||
find versioned_docs/version-$TAG_VERSION -name "*.md" -type f -exec sed -i "s|github.com/jpawlowski/hass.tibber_prices/blob/main/|github.com/jpawlowski/hass.tibber_prices/blob/$TAG_VERSION/|g" {} \; || true
|
||||
fi
|
||||
|
||||
- name: Cleanup old developer docs versions
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
working-directory: docs/developer
|
||||
run: |
|
||||
chmod +x ../cleanup-old-versions.sh
|
||||
# Adapt script for single-instance mode
|
||||
sed 's/user_versioned_docs/versioned_docs/g; s/user_versions.json/versions.json/g; s/developer_versioned_docs/versioned_docs/g; s/developer_versions.json/versions.json/g' ../cleanup-old-versions.sh > cleanup-single.sh
|
||||
chmod +x cleanup-single.sh
|
||||
./cleanup-single.sh
|
||||
|
||||
- name: Build developer docs website
|
||||
working-directory: docs/developer
|
||||
run: npm run build
|
||||
|
||||
# MERGE BUILDS
|
||||
- name: Merge both documentation sites
|
||||
run: |
|
||||
mkdir -p deploy-root
|
||||
cp docs/index.html deploy-root/
|
||||
cp -r docs/user/build/* deploy-root/user/
|
||||
mkdir -p deploy-root/developer
|
||||
cp -r docs/developer/build/* deploy-root/developer/
|
||||
|
||||
# COMMIT VERSION SNAPSHOTS
|
||||
- name: Commit version snapshots back to repository
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
TAG_VERSION=${GITHUB_REF#refs/tags/}
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Add version files from both docs
|
||||
git add docs/user/versioned_docs/ docs/user/versions.json 2>/dev/null || true
|
||||
git add docs/developer/versioned_docs/ docs/developer/versions.json 2>/dev/null || true
|
||||
|
||||
# Commit if there are changes
|
||||
if git diff --staged --quiet; then
|
||||
echo "No version snapshot changes to commit"
|
||||
else
|
||||
git commit -m "docs: add version snapshot $TAG_VERSION and cleanup old versions [skip ci]"
|
||||
git push origin HEAD:main
|
||||
echo "Version snapshots committed and pushed to main"
|
||||
fi
|
||||
|
||||
# DEPLOY
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./deploy-root
|
||||
user_name: github-actions[bot]
|
||||
user_email: github-actions[bot]@users.noreply.github.com
|
||||
60
README.md
|
|
@ -1,4 +1,8 @@
|
|||
# Tibber Price Information & Ratings
|
||||
# Tibber Prices - Custom Home Assistant Integration
|
||||
|
||||
<p align="center">
|
||||
<img src="images/header.svg" alt="Tibber Prices Custom Integration for Tibber" width="600">
|
||||
</p>
|
||||
|
||||
[![GitHub Release][releases-shield]][releases]
|
||||
[![GitHub Activity][commits-shield]][commits]
|
||||
|
|
@ -8,16 +12,24 @@
|
|||
[![Project Maintenance][maintenance-shield]][user_profile]
|
||||
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
|
||||
|
||||
A Home Assistant integration that provides advanced price information and ratings from Tibber. This integration fetches **quarter-hourly** electricity prices, enriches them with statistical analysis, and provides smart indicators to help you optimize your energy consumption and save money.
|
||||
> **⚠️ Not affiliated with Tibber**
|
||||
> This is an independent, community-maintained custom integration for Home Assistant. It is **not** an official Tibber product and is **not** affiliated with or endorsed by Tibber AS.
|
||||
|
||||

|
||||
A custom Home Assistant integration that provides advanced electricity price information and ratings from Tibber. This integration fetches **quarter-hourly** electricity prices, enriches them with statistical analysis, and provides smart indicators to help you optimize your energy consumption and save money.
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
- **[User Guide](docs/user/)** - Installation, configuration, and usage guides
|
||||
- **[Period Calculation](docs/user/period-calculation.md)** - How Best/Peak Price periods are calculated
|
||||
- **[Developer Guide](docs/development/)** - Contributing, architecture, and release process
|
||||
- **[Changelog](https://github.com/jpawlowski/hass.tibber_prices/releases)** - Release history and notes
|
||||
**[📚 Complete Documentation](https://jpawlowski.github.io/hass.tibber_prices/)** - Two comprehensive documentation sites:
|
||||
|
||||
- **[👤 User Documentation](https://jpawlowski.github.io/hass.tibber_prices/user/)** - Installation, configuration, usage guides, and examples
|
||||
- **[🔧 Developer Documentation](https://jpawlowski.github.io/hass.tibber_prices/developer/)** - Architecture, contributing guidelines, and development setup
|
||||
|
||||
**Quick Links:**
|
||||
- [Installation Guide](https://jpawlowski.github.io/hass.tibber_prices/user/installation) - Step-by-step setup instructions
|
||||
- [Sensor Reference](https://jpawlowski.github.io/hass.tibber_prices/user/sensors) - Complete list of all sensors and attributes
|
||||
- [Chart Examples](https://jpawlowski.github.io/hass.tibber_prices/user/chart-examples) - ApexCharts visualizations
|
||||
- [Automation Examples](https://jpawlowski.github.io/hass.tibber_prices/user/automation-examples) - Real-world automation scenarios
|
||||
- [Changelog](https://github.com/jpawlowski/hass.tibber_prices/releases) - Release history and notes
|
||||
|
||||
## ✨ Features
|
||||
|
||||
|
|
@ -28,7 +40,7 @@ A Home Assistant integration that provides advanced price information and rating
|
|||
- **Statistical Sensors**: Track lowest, highest, and average prices for the day
|
||||
- **Price Ratings**: Quarter-hourly ratings comparing current prices to 24-hour trailing averages
|
||||
- **Smart Indicators**: Binary sensors to detect peak hours and best price hours for automations
|
||||
- **Beautiful ApexCharts**: Auto-generated chart configurations with dynamic Y-axis scaling ([see examples](docs/user/chart-examples.md))
|
||||
- **Beautiful ApexCharts**: Auto-generated chart configurations with dynamic Y-axis scaling ([see examples](https://jpawlowski.github.io/hass.tibber_prices/user/chart-examples))
|
||||
- **Chart Metadata Sensor**: Dynamic chart configuration for optimal visualization
|
||||
- **Intelligent Caching**: Minimizes API calls while ensuring data freshness across Home Assistant restarts
|
||||
- **Custom Actions** (backend services): API endpoints for advanced integrations (ApexCharts support included)
|
||||
|
|
@ -81,7 +93,7 @@ This will guide you through:
|
|||
- Configure additional sensors in **Settings** → **Devices & Services** → **Tibber Price Information & Ratings** → **Entities**
|
||||
- Use sensors in automations, dashboards, and scripts
|
||||
|
||||
📖 **[Full Installation Guide →](docs/user/installation.md)**
|
||||
📖 **[Full Installation Guide →](https://jpawlowski.github.io/hass.tibber_prices/user/installation)**
|
||||
|
||||
## 📊 Available Entities
|
||||
|
||||
|
|
@ -89,6 +101,8 @@ The integration provides **30+ sensors** across different categories. Key sensor
|
|||
|
||||
> **Rich Sensor Attributes**: All sensors include extensive attributes with timestamps, context data, and detailed explanations. Enable **Extended Descriptions** in the integration options to add `long_description` and `usage_tips` attributes to every sensor, providing in-context documentation directly in Home Assistant's UI.
|
||||
|
||||
**[📋 Complete Sensor Reference](https://jpawlowski.github.io/hass.tibber_prices/user/sensors)** - Full list with descriptions and attributes
|
||||
|
||||
### Core Price Sensors (Enabled by Default)
|
||||
|
||||
| Entity | Description |
|
||||
|
|
@ -131,8 +145,8 @@ The integration provides **30+ sensors** across different categories. Key sensor
|
|||
|
||||
| Entity | Description |
|
||||
| ------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Peak Price Period | ON when in a detected peak price period ([how it works](docs/user/period-calculation.md)) |
|
||||
| Best Price Period | ON when in a detected best price period ([how it works](docs/user/period-calculation.md)) |
|
||||
| Peak Price Period | ON when in a detected peak price period ([how it works](https://jpawlowski.github.io/hass.tibber_prices/user/period-calculation)) |
|
||||
| Best Price Period | ON when in a detected best price period ([how it works](https://jpawlowski.github.io/hass.tibber_prices/user/period-calculation)) |
|
||||
| Tibber API Connection | Connection status to Tibber API |
|
||||
| Tomorrow's Data Available | Whether tomorrow's price data is available |
|
||||
|
||||
|
|
@ -156,7 +170,7 @@ The following sensors are available but disabled by default. Enable them in `Set
|
|||
|
||||
## Automation Examples
|
||||
|
||||
> **Note:** See the [full automation examples guide](docs/user/automation-examples.md) for more advanced recipes.
|
||||
> **Note:** See the [full automation examples guide](https://jpawlowski.github.io/hass.tibber_prices/user/automation-examples) for more advanced recipes.
|
||||
|
||||
### Run Appliances During Cheap Hours
|
||||
|
||||
|
|
@ -179,7 +193,7 @@ automation:
|
|||
entity_id: switch.dishwasher
|
||||
```
|
||||
|
||||
> **Learn more:** The [period calculation guide](docs/user/period-calculation.md) explains how Best/Peak Price periods are identified and how you can configure filters (flexibility, minimum distance from average, price level filters with gap tolerance).
|
||||
> **Learn more:** The [period calculation guide](https://jpawlowski.github.io/hass.tibber_prices/user/period-calculation) explains how Best/Peak Price periods are identified and how you can configure filters (flexibility, minimum distance from average, price level filters with gap tolerance).
|
||||
|
||||
### Notify on Extremely High Prices
|
||||
|
||||
|
|
@ -308,17 +322,17 @@ template:
|
|||
Price at {{ timestamp }}: {{ price }} ct/kWh
|
||||
```
|
||||
|
||||
📖 **[View all sensors and attributes →](docs/user/sensors.md)**
|
||||
📖 **[View all sensors and attributes →](https://jpawlowski.github.io/hass.tibber_prices/user/sensors)**
|
||||
|
||||
### Dynamic Icons & Visual Indicators
|
||||
|
||||
All sensors feature dynamic icons that change based on price levels, providing instant visual feedback in your dashboards.
|
||||
|
||||
<img src="images/entities-overview.jpg" width="400" alt="Entity list showing dynamic icons for different price states">
|
||||
<img src="docs/user/static/img/entities-overview.jpg" width="400" alt="Entity list showing dynamic icons for different price states">
|
||||
|
||||
_Dynamic icons adapt to price levels, trends, and period states - showing CHEAP prices, FALLING trend, and active Best Price Period_
|
||||
|
||||
📖 **[Dynamic Icons Guide →](docs/user/dynamic-icons.md)** | **[Icon Colors Guide →](docs/user/icon-colors.md)**
|
||||
📖 **[Dynamic Icons Guide →](https://jpawlowski.github.io/hass.tibber_prices/user/dynamic-icons)** | **[Icon Colors Guide →](https://jpawlowski.github.io/hass.tibber_prices/user/icon-colors)**
|
||||
|
||||
### Custom Actions
|
||||
|
||||
|
|
@ -328,27 +342,27 @@ The integration provides custom actions (they still appear as services under the
|
|||
- `tibber_prices.get_apexcharts_yaml` - Generate complete ApexCharts configurations
|
||||
- `tibber_prices.refresh_user_data` - Manually refresh account information
|
||||
|
||||
📖 **[Action documentation and examples →](docs/user/actions.md)**
|
||||
📖 **[Action documentation and examples →](https://jpawlowski.github.io/hass.tibber_prices/user/actions)**
|
||||
|
||||
### Chart Visualizations (Optional)
|
||||
|
||||
The integration includes built-in support for creating price visualization cards with automatic Y-axis scaling and color-coded series.
|
||||
|
||||
<img src="images/charts/rolling-window.jpg" width="600" alt="Example: Dynamic 48h rolling window chart">
|
||||
<img src="docs/user/static/img/charts/rolling-window.jpg" width="600" alt="Example: Dynamic 48h rolling window chart">
|
||||
|
||||
_Optional: Dynamic 48h chart with automatic Y-axis scaling - generated via `get_apexcharts_yaml` action_
|
||||
|
||||
📖 **[Chart examples and setup guide →](docs/user/chart-examples.md)**
|
||||
📖 **[Chart examples and setup guide →](https://jpawlowski.github.io/hass.tibber_prices/user/chart-examples)**
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Contributions are welcome! Please read the [Contributing Guidelines](CONTRIBUTING.md) and [Developer Guide](docs/development/) before submitting pull requests.
|
||||
Contributions are welcome! Please read the [Contributing Guidelines](CONTRIBUTING.md) and [Developer Documentation](https://jpawlowski.github.io/hass.tibber_prices/developer/) before submitting pull requests.
|
||||
|
||||
### For Contributors
|
||||
|
||||
- **[Developer Setup](docs/development/setup.md)** - Get started with DevContainer
|
||||
- **[Architecture Guide](docs/development/architecture.md)** - Understand the codebase
|
||||
- **[Release Management](docs/development/release-management.md)** - Release process and versioning
|
||||
- **[Developer Setup](https://jpawlowski.github.io/hass.tibber_prices/developer/setup)** - Get started with DevContainer
|
||||
- **[Architecture Guide](https://jpawlowski.github.io/hass.tibber_prices/developer/architecture)** - Understand the codebase
|
||||
- **[Release Management](https://jpawlowski.github.io/hass.tibber_prices/developer/release-management)** - Release process and versioning
|
||||
|
||||
## 🤖 Development Note
|
||||
|
||||
|
|
|
|||
128
docs/cleanup-old-versions.sh
Executable file
|
|
@ -0,0 +1,128 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Cleanup old documentation versions based on versioning strategy:
|
||||
# - Pre-1.0 (0.x.y): Keep only last 5 versions
|
||||
# - Post-1.0 (≥1.0.0): Keep last 3 MINOR versions per MAJOR (only latest PATCH per MINOR)
|
||||
|
||||
KEEP_PRE_1_0=5
|
||||
KEEP_POST_1_0_MINORS=3
|
||||
|
||||
echo "🧹 Cleaning up old documentation versions..."
|
||||
|
||||
for doc_type in "user" "developer"; do
|
||||
VERSIONS_FILE="${doc_type}_versions.json"
|
||||
VERSIONED_DOCS_DIR="${doc_type}_versioned_docs"
|
||||
|
||||
if [ ! -f "$VERSIONS_FILE" ]; then
|
||||
echo "⚠️ No $VERSIONS_FILE found, skipping $doc_type docs"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Read current versions from JSON (remove brackets and quotes)
|
||||
CURRENT_VERSIONS=$(jq -r '.[]' "$VERSIONS_FILE" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$CURRENT_VERSIONS" ]; then
|
||||
echo "✓ No versions found in $VERSIONS_FILE"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📋 Current $doc_type versions:"
|
||||
echo "$CURRENT_VERSIONS"
|
||||
|
||||
# Separate pre-1.0 and post-1.0 versions
|
||||
PRE_1_0_VERSIONS=$(echo "$CURRENT_VERSIONS" | grep '^v0\.' || true)
|
||||
POST_1_0_VERSIONS=$(echo "$CURRENT_VERSIONS" | grep -v '^v0\.' || true)
|
||||
|
||||
VERSIONS_TO_KEEP=()
|
||||
|
||||
# Handle pre-1.0 versions: keep last N
|
||||
if [ -n "$PRE_1_0_VERSIONS" ]; then
|
||||
echo ""
|
||||
echo "🔍 Processing pre-1.0 versions (keep last $KEEP_PRE_1_0):"
|
||||
PRE_1_0_SORTED=$(echo "$PRE_1_0_VERSIONS" | sort -V -r)
|
||||
PRE_1_0_KEEP=$(echo "$PRE_1_0_SORTED" | head -n "$KEEP_PRE_1_0")
|
||||
|
||||
while IFS= read -r version; do
|
||||
[ -n "$version" ] && VERSIONS_TO_KEEP+=("$version")
|
||||
done <<< "$PRE_1_0_KEEP"
|
||||
|
||||
echo "$PRE_1_0_KEEP"
|
||||
fi
|
||||
|
||||
# Handle post-1.0 versions: keep last N MINOR per MAJOR (latest PATCH only)
|
||||
if [ -n "$POST_1_0_VERSIONS" ]; then
|
||||
echo ""
|
||||
echo "🔍 Processing post-1.0 versions (keep last $KEEP_POST_1_0_MINORS MINOR per MAJOR):"
|
||||
|
||||
# Get unique MAJOR versions
|
||||
MAJORS=$(echo "$POST_1_0_VERSIONS" | sed 's/^v\([0-9]*\)\..*/\1/' | sort -u -n)
|
||||
|
||||
for major in $MAJORS; do
|
||||
# Get all versions for this MAJOR
|
||||
MAJOR_VERSIONS=$(echo "$POST_1_0_VERSIONS" | grep "^v${major}\.")
|
||||
|
||||
# Group by MINOR version and keep only latest PATCH
|
||||
MINORS=$(echo "$MAJOR_VERSIONS" | sed 's/^v[0-9]*\.\([0-9]*\)\..*/\1/' | sort -u -n -r)
|
||||
|
||||
MINOR_COUNT=0
|
||||
for minor in $MINORS; do
|
||||
if [ $MINOR_COUNT -ge $KEEP_POST_1_0_MINORS ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
# Get latest PATCH for this MINOR
|
||||
LATEST_PATCH=$(echo "$MAJOR_VERSIONS" | grep "^v${major}\.${minor}\." | sort -V -r | head -n 1)
|
||||
|
||||
if [ -n "$LATEST_PATCH" ]; then
|
||||
VERSIONS_TO_KEEP+=("$LATEST_PATCH")
|
||||
echo " v${major}.${minor}.x → $LATEST_PATCH"
|
||||
MINOR_COUNT=$((MINOR_COUNT + 1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
# Convert array to newline-separated list for comparison
|
||||
KEEP_LIST=$(printf "%s\n" "${VERSIONS_TO_KEEP[@]}" | sort -V)
|
||||
|
||||
echo ""
|
||||
echo "✅ Versions to keep for $doc_type:"
|
||||
echo "$KEEP_LIST"
|
||||
|
||||
# Find versions to delete
|
||||
VERSIONS_TO_DELETE=()
|
||||
while IFS= read -r version; do
|
||||
if ! echo "$KEEP_LIST" | grep -q "^${version}$"; then
|
||||
VERSIONS_TO_DELETE+=("$version")
|
||||
fi
|
||||
done <<< "$CURRENT_VERSIONS"
|
||||
|
||||
if [ ${#VERSIONS_TO_DELETE[@]} -eq 0 ]; then
|
||||
echo ""
|
||||
echo "✓ No old versions to delete for $doc_type"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🗑️ Deleting old $doc_type versions:"
|
||||
for version in "${VERSIONS_TO_DELETE[@]}"; do
|
||||
echo " - $version"
|
||||
|
||||
# Remove versioned docs directory
|
||||
VERSION_DIR="${VERSIONED_DOCS_DIR}/version-${version}"
|
||||
if [ -d "$VERSION_DIR" ]; then
|
||||
rm -rf "$VERSION_DIR"
|
||||
echo " Removed: $VERSION_DIR"
|
||||
fi
|
||||
done
|
||||
|
||||
# Update versions.json with only kept versions
|
||||
echo "$KEEP_LIST" | jq -R -s 'split("\n") | map(select(length > 0))' > "$VERSIONS_FILE"
|
||||
echo ""
|
||||
echo "✓ Updated $VERSIONS_FILE"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✨ Cleanup complete!"
|
||||
20
docs/developer/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
41
docs/developer/README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Website
|
||||
|
||||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
## Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```bash
|
||||
USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```bash
|
||||
GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
186
docs/developer/docs/api-reference.md
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
Documentation of the Tibber GraphQL API used by this integration.
|
||||
|
||||
## GraphQL Endpoint
|
||||
|
||||
```
|
||||
https://api.tibber.com/v1-beta/gql
|
||||
```
|
||||
|
||||
**Authentication:** Bearer token in `Authorization` header
|
||||
|
||||
## Queries Used
|
||||
|
||||
### User Data Query
|
||||
|
||||
Fetches home information and metadata:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
viewer {
|
||||
homes {
|
||||
id
|
||||
appNickname
|
||||
address {
|
||||
address1
|
||||
postalCode
|
||||
city
|
||||
country
|
||||
}
|
||||
timeZone
|
||||
currentSubscription {
|
||||
priceInfo {
|
||||
current {
|
||||
currency
|
||||
}
|
||||
}
|
||||
}
|
||||
meteringPointData {
|
||||
consumptionEan
|
||||
gridAreaCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Cached for:** 24 hours
|
||||
|
||||
### Price Data Query
|
||||
|
||||
Fetches quarter-hourly prices:
|
||||
|
||||
```graphql
|
||||
query($homeId: ID!) {
|
||||
viewer {
|
||||
home(id: $homeId) {
|
||||
currentSubscription {
|
||||
priceInfo {
|
||||
range(resolution: QUARTER_HOURLY, first: 384) {
|
||||
nodes {
|
||||
total
|
||||
startsAt
|
||||
level
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `homeId`: Tibber home identifier
|
||||
- `resolution`: Always `QUARTER_HOURLY`
|
||||
- `first`: 384 intervals (4 days of data)
|
||||
|
||||
**Cached until:** Midnight local time
|
||||
|
||||
## Rate Limits
|
||||
|
||||
Tibber API rate limits (as of 2024):
|
||||
- **5000 requests per hour** per token
|
||||
- **Burst limit:** 100 requests per minute
|
||||
|
||||
Integration stays well below these limits:
|
||||
- Polls every 15 minutes = 96 requests/day
|
||||
- User data cached for 24h = 1 request/day
|
||||
- **Total:** ~100 requests/day per home
|
||||
|
||||
## Response Format
|
||||
|
||||
### Price Node Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 0.2456,
|
||||
"startsAt": "2024-12-06T14:00:00.000+01:00",
|
||||
"level": "NORMAL"
|
||||
}
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
- `total`: Price including VAT and fees (currency's major unit, e.g., EUR)
|
||||
- `startsAt`: ISO 8601 timestamp with timezone
|
||||
- `level`: Tibber's own classification (VERY_CHEAP, CHEAP, NORMAL, EXPENSIVE, VERY_EXPENSIVE)
|
||||
|
||||
### Currency Information
|
||||
|
||||
```json
|
||||
{
|
||||
"currency": "EUR"
|
||||
}
|
||||
```
|
||||
|
||||
Supported currencies:
|
||||
- `EUR` (Euro) - displayed as ct/kWh
|
||||
- `NOK` (Norwegian Krone) - displayed as øre/kWh
|
||||
- `SEK` (Swedish Krona) - displayed as öre/kWh
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Error Responses
|
||||
|
||||
**Invalid Token:**
|
||||
```json
|
||||
{
|
||||
"errors": [{
|
||||
"message": "Unauthorized",
|
||||
"extensions": {
|
||||
"code": "UNAUTHENTICATED"
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
**Rate Limit Exceeded:**
|
||||
```json
|
||||
{
|
||||
"errors": [{
|
||||
"message": "Too Many Requests",
|
||||
"extensions": {
|
||||
"code": "RATE_LIMIT_EXCEEDED"
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
**Home Not Found:**
|
||||
```json
|
||||
{
|
||||
"errors": [{
|
||||
"message": "Home not found",
|
||||
"extensions": {
|
||||
"code": "NOT_FOUND"
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
Integration handles these with:
|
||||
- Exponential backoff retry (3 attempts)
|
||||
- ConfigEntryAuthFailed for auth errors
|
||||
- ConfigEntryNotReady for temporary failures
|
||||
|
||||
## Data Transformation
|
||||
|
||||
Raw API data is enriched with:
|
||||
- **Trailing 24h average** - Calculated from previous intervals
|
||||
- **Leading 24h average** - Calculated from future intervals
|
||||
- **Price difference %** - Deviation from average
|
||||
- **Custom rating** - Based on user thresholds (different from Tibber's `level`)
|
||||
|
||||
See `utils/price.py` for enrichment logic.
|
||||
|
||||
---
|
||||
|
||||
💡 **External Resources:**
|
||||
- [Tibber API Documentation](https://developer.tibber.com/docs/overview)
|
||||
- [GraphQL Explorer](https://developer.tibber.com/explorer)
|
||||
- [Get API Token](https://developer.tibber.com/settings/access-token)
|
||||
|
|
@ -1,8 +1,12 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Architecture
|
||||
|
||||
This document provides a visual overview of the integration's architecture, focusing on end-to-end data flow and caching layers.
|
||||
|
||||
For detailed implementation patterns, see [`AGENTS.md`](../../AGENTS.md).
|
||||
For detailed implementation patterns, see [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -351,4 +355,4 @@ Sensors organized by **calculation method** (refactored Nov 2025):
|
|||
- **[Setup Guide](./setup.md)** - Development environment setup
|
||||
- **[Testing Guide](./testing.md)** - How to test changes
|
||||
- **[Release Management](./release-management.md)** - Release workflow and versioning
|
||||
- **[AGENTS.md](../../AGENTS.md)** - Complete reference for AI development
|
||||
- **[AGENTS.md](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md)** - Complete reference for AI development
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Caching Strategy
|
||||
|
||||
This document explains all caching mechanisms in the Tibber Prices integration, their purpose, invalidation logic, and lifetime.
|
||||
|
|
@ -194,7 +198,7 @@ hash_data = (
|
|||
|
||||
**Performance impact:**
|
||||
- **Period calculation:** ~100-500ms (depends on interval count, relaxation attempts)
|
||||
- **Cache hit:** <1ms (hash comparison + dict lookup)
|
||||
- **Cache hit:** `<`1ms (hash comparison + dict lookup)
|
||||
- **Savings:** ~70% of calculation time (most updates hit cache)
|
||||
|
||||
**Why this cache matters:** Period calculation is CPU-intensive (filtering, gap tolerance, relaxation). Caching avoids recalculating unchanged periods 3-4 times per hour.
|
||||
|
|
@ -363,7 +367,7 @@ Total: ~755ms (expected once per day)
|
|||
### After Config Change
|
||||
```
|
||||
Options Update
|
||||
├─> Cache invalidation: <1ms
|
||||
├─> Cache invalidation: `<`1ms
|
||||
├─> Coordinator refresh: ~600ms
|
||||
│ ├─> API fetch: SKIP (data unchanged)
|
||||
│ ├─> Config rebuild: ~50μs
|
||||
|
|
@ -381,7 +385,7 @@ Options Update
|
|||
|------------|----------|------|--------------|---------|
|
||||
| **API Data** | Hours to 1 day | ~50KB | Midnight, validation | Reduce API calls |
|
||||
| **Translations** | Forever (until HA restart) | ~5KB | Never | Avoid file I/O |
|
||||
| **Config Dicts** | Until options change | <1KB | Explicit (options update) | Avoid dict lookups |
|
||||
| **Config Dicts** | Until options change | `<`1KB | Explicit (options update) | Avoid dict lookups |
|
||||
| **Period Calculation** | Until data/config change | ~10KB | Auto (hash mismatch) | Avoid CPU-intensive calculation |
|
||||
| **Transformation** | Until midnight/config change | ~50KB | Auto (midnight/config) | Avoid re-enrichment |
|
||||
|
||||
|
|
@ -440,4 +444,4 @@ Options Update
|
|||
|
||||
- **[Timer Architecture](./timer-architecture.md)** - Timer system, scheduling, midnight coordination
|
||||
- **[Architecture](./architecture.md)** - Overall system design, data flow
|
||||
- **[AGENTS.md](../../AGENTS.md)** - Complete reference for AI development
|
||||
- **[AGENTS.md](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md)** - Complete reference for AI development
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Coding Guidelines
|
||||
|
||||
> **Note:** For complete coding standards, see [`AGENTS.md`](../../AGENTS.md).
|
||||
> **Note:** For complete coding standards, see [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md).
|
||||
|
||||
## Code Style
|
||||
|
||||
|
|
@ -71,7 +75,7 @@ Many existing classes lack the `TibberPrices` prefix. Before refactoring:
|
|||
2. Use `multi_replace_string_in_file` for bulk renames
|
||||
3. Test thoroughly after each module
|
||||
|
||||
See [`AGENTS.md`](../../AGENTS.md) for complete list of classes needing rename.
|
||||
See [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) for complete list of classes needing rename.
|
||||
|
||||
## Import Order
|
||||
|
||||
|
|
@ -114,4 +118,4 @@ enriched = enrich_price_info_with_differences(
|
|||
)
|
||||
```
|
||||
|
||||
See [`AGENTS.md`](../../AGENTS.md) for complete guidelines.
|
||||
See [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) for complete guidelines.
|
||||
216
docs/developer/docs/contributing.md
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
# Contributing Guide
|
||||
|
||||
Welcome! This guide helps you contribute to the Tibber Prices integration.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Git
|
||||
- VS Code with Remote Containers extension
|
||||
- Docker Desktop
|
||||
|
||||
### Fork and Clone
|
||||
|
||||
1. Fork the repository on GitHub
|
||||
2. Clone your fork:
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/hass.tibber_prices.git
|
||||
cd hass.tibber_prices
|
||||
```
|
||||
3. Open in VS Code
|
||||
4. Click "Reopen in Container" when prompted
|
||||
|
||||
The DevContainer will set up everything automatically.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### 1. Create a Branch
|
||||
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
# or
|
||||
git checkout -b fix/issue-123-description
|
||||
```
|
||||
|
||||
**Branch naming:**
|
||||
- `feature/` - New features
|
||||
- `fix/` - Bug fixes
|
||||
- `docs/` - Documentation only
|
||||
- `refactor/` - Code restructuring
|
||||
- `test/` - Test improvements
|
||||
|
||||
### 2. Make Changes
|
||||
|
||||
Edit code, following [Coding Guidelines](coding-guidelines.md).
|
||||
|
||||
**Run checks frequently:**
|
||||
```bash
|
||||
./scripts/type-check # Pyright type checking
|
||||
./scripts/lint # Ruff linting (auto-fix)
|
||||
./scripts/test # Run tests
|
||||
```
|
||||
|
||||
### 3. Test Locally
|
||||
|
||||
```bash
|
||||
./scripts/develop # Start HA with integration loaded
|
||||
```
|
||||
|
||||
Access at http://localhost:8123
|
||||
|
||||
### 4. Write Tests
|
||||
|
||||
Add tests in `/tests/` for new features:
|
||||
|
||||
```python
|
||||
@pytest.mark.unit
|
||||
async def test_your_feature(hass, coordinator):
|
||||
"""Test your new feature."""
|
||||
# Arrange
|
||||
coordinator.data = {...}
|
||||
|
||||
# Act
|
||||
result = your_function(coordinator.data)
|
||||
|
||||
# Assert
|
||||
assert result == expected_value
|
||||
```
|
||||
|
||||
Run your test:
|
||||
```bash
|
||||
./scripts/test tests/test_your_feature.py -v
|
||||
```
|
||||
|
||||
### 5. Commit Changes
|
||||
|
||||
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat(sensors): add volatility trend sensor
|
||||
|
||||
Add new sensor showing 3-hour volatility trend direction.
|
||||
Includes attributes with historical volatility data.
|
||||
|
||||
Impact: Users can predict when prices will stabilize or continue fluctuating."
|
||||
```
|
||||
|
||||
**Commit types:**
|
||||
- `feat:` - New feature
|
||||
- `fix:` - Bug fix
|
||||
- `docs:` - Documentation
|
||||
- `refactor:` - Code restructuring
|
||||
- `test:` - Test changes
|
||||
- `chore:` - Maintenance
|
||||
|
||||
**Add scope when relevant:**
|
||||
- `feat(sensors):` - Sensor platform
|
||||
- `fix(coordinator):` - Data coordinator
|
||||
- `docs(user):` - User documentation
|
||||
|
||||
### 6. Push and Create PR
|
||||
|
||||
```bash
|
||||
git push origin your-branch-name
|
||||
```
|
||||
|
||||
Then open Pull Request on GitHub.
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
### PR Template
|
||||
|
||||
Title: Short, descriptive (50 chars max)
|
||||
|
||||
Description should include:
|
||||
```markdown
|
||||
## What
|
||||
Brief description of changes
|
||||
|
||||
## Why
|
||||
Problem being solved or feature rationale
|
||||
|
||||
## How
|
||||
Implementation approach
|
||||
|
||||
## Testing
|
||||
- [ ] Manual testing in Home Assistant
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Type checking passes
|
||||
- [ ] Linting passes
|
||||
|
||||
## Breaking Changes
|
||||
(If any - describe migration path)
|
||||
|
||||
## Related Issues
|
||||
Closes #123
|
||||
```
|
||||
|
||||
### PR Checklist
|
||||
|
||||
Before submitting:
|
||||
- [ ] Code follows [Coding Guidelines](coding-guidelines.md)
|
||||
- [ ] All tests pass (`./scripts/test`)
|
||||
- [ ] Type checking passes (`./scripts/type-check`)
|
||||
- [ ] Linting passes (`./scripts/lint-check`)
|
||||
- [ ] Documentation updated (if needed)
|
||||
- [ ] AGENTS.md updated (if patterns changed)
|
||||
- [ ] Commit messages follow Conventional Commits
|
||||
|
||||
### Review Process
|
||||
|
||||
1. **Automated checks** run (CI/CD)
|
||||
2. **Maintainer review** (usually within 3 days)
|
||||
3. **Address feedback** if requested
|
||||
4. **Approval** → Maintainer merges
|
||||
|
||||
## Code Review Tips
|
||||
|
||||
### What Reviewers Look For
|
||||
|
||||
✅ **Good:**
|
||||
- Clear, self-explanatory code
|
||||
- Appropriate comments for complex logic
|
||||
- Tests covering edge cases
|
||||
- Type hints on all functions
|
||||
- Follows existing patterns
|
||||
|
||||
❌ **Avoid:**
|
||||
- Large PRs (>500 lines) - split into smaller ones
|
||||
- Mixing unrelated changes
|
||||
- Missing tests for new features
|
||||
- Breaking changes without migration path
|
||||
- Copy-pasted code (refactor into shared functions)
|
||||
|
||||
### Responding to Feedback
|
||||
|
||||
- Don't take it personally - we're improving code together
|
||||
- Ask questions if feedback unclear
|
||||
- Push additional commits to address comments
|
||||
- Mark conversations as resolved when fixed
|
||||
|
||||
## Finding Issues to Work On
|
||||
|
||||
Good first issues are labeled:
|
||||
- `good first issue` - Beginner-friendly
|
||||
- `help wanted` - Maintainers welcome contributions
|
||||
- `documentation` - Docs improvements
|
||||
|
||||
Comment on issue before starting work to avoid duplicates.
|
||||
|
||||
## Communication
|
||||
|
||||
- **GitHub Issues** - Bug reports, feature requests
|
||||
- **Pull Requests** - Code discussion
|
||||
- **Discussions** - General questions, ideas
|
||||
|
||||
Be respectful, constructive, and patient. We're all volunteers! 🙏
|
||||
|
||||
---
|
||||
|
||||
💡 **Related:**
|
||||
- [Setup Guide](setup.md) - DevContainer setup
|
||||
- [Coding Guidelines](coding-guidelines.md) - Style guide
|
||||
- [Testing](testing.md) - Writing tests
|
||||
- [Release Management](release-management.md) - How releases work
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Critical Behavior Patterns - Testing Guide
|
||||
|
||||
**Purpose:** This documentation lists essential behavior patterns that must be tested to ensure production-quality code and prevent resource leaks.
|
||||
230
docs/developer/docs/debugging.md
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
# Debugging Guide
|
||||
|
||||
Tips and techniques for debugging the Tibber Prices integration during development.
|
||||
|
||||
## Logging
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
Add to `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
logger:
|
||||
default: info
|
||||
logs:
|
||||
custom_components.tibber_prices: debug
|
||||
```
|
||||
|
||||
Restart Home Assistant to apply.
|
||||
|
||||
### Key Log Messages
|
||||
|
||||
**Coordinator Updates:**
|
||||
```
|
||||
[custom_components.tibber_prices.coordinator] Successfully fetched price data
|
||||
[custom_components.tibber_prices.coordinator] Cache valid, using cached data
|
||||
[custom_components.tibber_prices.coordinator] Midnight turnover detected, clearing cache
|
||||
```
|
||||
|
||||
**Period Calculation:**
|
||||
```
|
||||
[custom_components.tibber_prices.coordinator.periods] Calculating BEST PRICE periods: flex=15.0%
|
||||
[custom_components.tibber_prices.coordinator.periods] Day 2024-12-06: Found 2 periods
|
||||
[custom_components.tibber_prices.coordinator.periods] Period 1: 02:00-05:00 (12 intervals)
|
||||
```
|
||||
|
||||
**API Errors:**
|
||||
```
|
||||
[custom_components.tibber_prices.api] API request failed: Unauthorized
|
||||
[custom_components.tibber_prices.api] Retrying (attempt 2/3) after 2.0s
|
||||
```
|
||||
|
||||
## VS Code Debugging
|
||||
|
||||
### Launch Configuration
|
||||
|
||||
`.vscode/launch.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Home Assistant",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"module": "homeassistant",
|
||||
"args": ["-c", "config", "--debug"],
|
||||
"justMyCode": false,
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceFolder}/.venv/lib/python3.13/site-packages"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Set Breakpoints
|
||||
|
||||
**Coordinator update:**
|
||||
```python
|
||||
# coordinator/core.py
|
||||
async def _async_update_data(self) -> dict:
|
||||
"""Fetch data from API."""
|
||||
breakpoint() # Or set VS Code breakpoint
|
||||
```
|
||||
|
||||
**Period calculation:**
|
||||
```python
|
||||
# coordinator/period_handlers/core.py
|
||||
def calculate_periods(...) -> list[dict]:
|
||||
"""Calculate best/peak price periods."""
|
||||
breakpoint()
|
||||
```
|
||||
|
||||
## pytest Debugging
|
||||
|
||||
### Run Single Test with Output
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m pytest tests/test_period_calculation.py::test_midnight_crossing -v -s
|
||||
```
|
||||
|
||||
**Flags:**
|
||||
- `-v` - Verbose output
|
||||
- `-s` - Show print statements
|
||||
- `-k pattern` - Run tests matching pattern
|
||||
|
||||
### Debug Test in VS Code
|
||||
|
||||
Set breakpoint in test file, use "Debug Test" CodeLens.
|
||||
|
||||
### Useful Test Patterns
|
||||
|
||||
**Print coordinator data:**
|
||||
```python
|
||||
def test_something(coordinator):
|
||||
print(f"Coordinator data: {coordinator.data}")
|
||||
print(f"Price info count: {len(coordinator.data['priceInfo'])}")
|
||||
```
|
||||
|
||||
**Inspect period attributes:**
|
||||
```python
|
||||
def test_periods(hass, coordinator):
|
||||
periods = coordinator.data.get('best_price_periods', [])
|
||||
for period in periods:
|
||||
print(f"Period: {period['start']} to {period['end']}")
|
||||
print(f" Intervals: {len(period['intervals'])}")
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Integration Not Loading
|
||||
|
||||
**Check:**
|
||||
```bash
|
||||
grep "tibber_prices" config/home-assistant.log
|
||||
```
|
||||
|
||||
**Common causes:**
|
||||
- Syntax error in Python code → Check logs for traceback
|
||||
- Missing dependency → Run `uv sync`
|
||||
- Wrong file permissions → `chmod +x scripts/*`
|
||||
|
||||
### Sensors Not Updating
|
||||
|
||||
**Check coordinator state:**
|
||||
```python
|
||||
# In Developer Tools > Template
|
||||
{{ states.sensor.tibber_home_current_interval_price.last_updated }}
|
||||
```
|
||||
|
||||
**Debug in code:**
|
||||
```python
|
||||
# Add logging in sensor/core.py
|
||||
_LOGGER.debug("Updating sensor %s: old=%s new=%s",
|
||||
self.entity_id, self._attr_native_value, new_value)
|
||||
```
|
||||
|
||||
### Period Calculation Wrong
|
||||
|
||||
**Enable detailed period logs:**
|
||||
```python
|
||||
# coordinator/period_handlers/period_building.py
|
||||
_LOGGER.debug("Candidate intervals: %s",
|
||||
[(i['startsAt'], i['total']) for i in candidates])
|
||||
```
|
||||
|
||||
**Check filter statistics:**
|
||||
```
|
||||
[period_building] Flex filter blocked: 45 intervals
|
||||
[period_building] Min distance blocked: 12 intervals
|
||||
[period_building] Level filter blocked: 8 intervals
|
||||
```
|
||||
|
||||
## Performance Profiling
|
||||
|
||||
### Time Execution
|
||||
|
||||
```python
|
||||
import time
|
||||
|
||||
start = time.perf_counter()
|
||||
result = expensive_function()
|
||||
duration = time.perf_counter() - start
|
||||
_LOGGER.debug("Function took %.3fs", duration)
|
||||
```
|
||||
|
||||
### Memory Usage
|
||||
|
||||
```python
|
||||
import tracemalloc
|
||||
|
||||
tracemalloc.start()
|
||||
# ... your code ...
|
||||
current, peak = tracemalloc.get_traced_memory()
|
||||
_LOGGER.debug("Memory: current=%d peak=%d", current, peak)
|
||||
tracemalloc.stop()
|
||||
```
|
||||
|
||||
### Profile with cProfile
|
||||
|
||||
```bash
|
||||
python -m cProfile -o profile.stats -m homeassistant -c config
|
||||
python -m pstats profile.stats
|
||||
# Then: sort cumtime, stats 20
|
||||
```
|
||||
|
||||
## Live Debugging in Running HA
|
||||
|
||||
### Remote Debugging with debugpy
|
||||
|
||||
Add to coordinator code:
|
||||
```python
|
||||
import debugpy
|
||||
debugpy.listen(5678)
|
||||
_LOGGER.info("Waiting for debugger attach on port 5678")
|
||||
debugpy.wait_for_client()
|
||||
```
|
||||
|
||||
Connect from VS Code with remote attach configuration.
|
||||
|
||||
### IPython REPL
|
||||
|
||||
Install in container:
|
||||
```bash
|
||||
uv pip install ipython
|
||||
```
|
||||
|
||||
Add breakpoint:
|
||||
```python
|
||||
from IPython import embed
|
||||
embed() # Drops into interactive shell
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
💡 **Related:**
|
||||
- [Testing Guide](testing.md) - Writing and running tests
|
||||
- [Setup Guide](setup.md) - Development environment
|
||||
- [Architecture](architecture.md) - Code structure
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
# Developer Documentation
|
||||
|
||||
This section contains documentation for contributors and maintainers of the Tibber Prices integration.
|
||||
This section contains documentation for contributors and maintainers of the **Tibber Prices custom integration**.
|
||||
|
||||
:::info Community Project
|
||||
This is an independent, community-maintained custom integration for Home Assistant. It is **not** an official Tibber product and is **not** affiliated with Tibber AS.
|
||||
:::
|
||||
|
||||
## 📚 Developer Guides
|
||||
|
||||
|
|
@ -16,7 +20,7 @@ This section contains documentation for contributors and maintainers of the Tibb
|
|||
|
||||
## 🤖 AI Documentation
|
||||
|
||||
The main AI/Copilot documentation is in [`AGENTS.md`](../../AGENTS.md). This file serves as long-term memory for AI assistants and contains:
|
||||
The main AI/Copilot documentation is in [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md). This file serves as long-term memory for AI assistants and contains:
|
||||
|
||||
- Detailed architectural patterns
|
||||
- Code quality rules and conventions
|
||||
|
|
@ -24,7 +28,7 @@ The main AI/Copilot documentation is in [`AGENTS.md`](../../AGENTS.md). This fil
|
|||
- Common pitfalls and anti-patterns
|
||||
- Project-specific patterns and utilities
|
||||
|
||||
**Important:** When proposing changes to patterns or conventions, always update [`AGENTS.md`](../../AGENTS.md) to keep AI guidance consistent.
|
||||
**Important:** When proposing changes to patterns or conventions, always update [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) to keep AI guidance consistent.
|
||||
|
||||
### AI-Assisted Development
|
||||
|
||||
|
|
@ -57,7 +61,7 @@ This integration is developed with extensive AI assistance (GitHub Copilot, Clau
|
|||
- Translation quality depends on AI's understanding of target language
|
||||
- User feedback is crucial for discovering real-world issues
|
||||
|
||||
If you're working with AI tools on this project, the [`AGENTS.md`](../../AGENTS.md) file provides the context and patterns that ensure consistency.
|
||||
If you're working with AI tools on this project, the [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) file provides the context and patterns that ensure consistency.
|
||||
|
||||
## 🚀 Quick Start for Contributors
|
||||
|
||||
|
|
@ -161,12 +165,12 @@ pytest --cov=custom_components.tibber_prices tests/
|
|||
|
||||
## 🤝 Contributing
|
||||
|
||||
See [CONTRIBUTING.md](../../CONTRIBUTING.md) for detailed contribution guidelines, code of conduct, and pull request process.
|
||||
See [CONTRIBUTING.md](https://github.com/jpawlowski/hass.tibber_prices/blob/main/CONTRIBUTING.md) for detailed contribution guidelines, code of conduct, and pull request process.
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under [LICENSE](../../LICENSE).
|
||||
This project is licensed under the [Apache License 2.0](https://github.com/jpawlowski/hass.tibber_prices/blob/main/LICENSE).
|
||||
|
||||
---
|
||||
|
||||
**Note:** This documentation is for developers. End users should refer to the [User Documentation](../user/).
|
||||
**Note:** This documentation is for developers. End users should refer to the [User Documentation](https://jpawlowski.github.io/hass.tibber_prices/user/).
|
||||
322
docs/developer/docs/performance.md
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
# Performance Optimization
|
||||
|
||||
Guidelines for maintaining and improving integration performance.
|
||||
|
||||
## Performance Goals
|
||||
|
||||
Target metrics:
|
||||
- **Coordinator update**: <500ms (typical: 200-300ms)
|
||||
- **Sensor update**: <10ms per sensor
|
||||
- **Period calculation**: <100ms (typical: 20-50ms)
|
||||
- **Memory footprint**: <10MB per home
|
||||
- **API calls**: <100 per day per home
|
||||
|
||||
## Profiling
|
||||
|
||||
### Timing Decorator
|
||||
|
||||
Use for performance-critical functions:
|
||||
|
||||
```python
|
||||
import time
|
||||
import functools
|
||||
|
||||
def timing(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
start = time.perf_counter()
|
||||
result = func(*args, **kwargs)
|
||||
duration = time.perf_counter() - start
|
||||
_LOGGER.debug("%s took %.3fms", func.__name__, duration * 1000)
|
||||
return result
|
||||
return wrapper
|
||||
|
||||
@timing
|
||||
def expensive_calculation():
|
||||
# Your code here
|
||||
```
|
||||
|
||||
### Memory Profiling
|
||||
|
||||
```python
|
||||
import tracemalloc
|
||||
|
||||
tracemalloc.start()
|
||||
# Run your code
|
||||
current, peak = tracemalloc.get_traced_memory()
|
||||
_LOGGER.info("Memory: current=%.2fMB peak=%.2fMB",
|
||||
current / 1024**2, peak / 1024**2)
|
||||
tracemalloc.stop()
|
||||
```
|
||||
|
||||
### Async Profiling
|
||||
|
||||
```bash
|
||||
# Install aioprof
|
||||
uv pip install aioprof
|
||||
|
||||
# Run with profiling
|
||||
python -m aioprof homeassistant -c config
|
||||
```
|
||||
|
||||
## Optimization Patterns
|
||||
|
||||
### Caching
|
||||
|
||||
**1. Persistent Cache** (API data):
|
||||
```python
|
||||
# Already implemented in coordinator/cache.py
|
||||
store = Store(hass, STORAGE_VERSION, STORAGE_KEY)
|
||||
data = await store.async_load()
|
||||
```
|
||||
|
||||
**2. Translation Cache** (in-memory):
|
||||
```python
|
||||
# Already implemented in const.py
|
||||
_TRANSLATION_CACHE: dict[str, dict] = {}
|
||||
|
||||
def get_translation(path: str, language: str) -> dict:
|
||||
cache_key = f"{path}_{language}"
|
||||
if cache_key not in _TRANSLATION_CACHE:
|
||||
_TRANSLATION_CACHE[cache_key] = load_translation(path, language)
|
||||
return _TRANSLATION_CACHE[cache_key]
|
||||
```
|
||||
|
||||
**3. Config Cache** (invalidated on options change):
|
||||
```python
|
||||
class DataTransformer:
|
||||
def __init__(self):
|
||||
self._config_cache: dict | None = None
|
||||
|
||||
def get_config(self) -> dict:
|
||||
if self._config_cache is None:
|
||||
self._config_cache = self._build_config()
|
||||
return self._config_cache
|
||||
|
||||
def invalidate_config_cache(self):
|
||||
self._config_cache = None
|
||||
```
|
||||
|
||||
### Lazy Loading
|
||||
|
||||
**Load data only when needed:**
|
||||
```python
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict | None:
|
||||
"""Return attributes."""
|
||||
# Calculate only when accessed
|
||||
if self.entity_description.key == "complex_sensor":
|
||||
return self._calculate_complex_attributes()
|
||||
return None
|
||||
```
|
||||
|
||||
### Bulk Operations
|
||||
|
||||
**Process multiple items at once:**
|
||||
```python
|
||||
# ❌ Slow - loop with individual operations
|
||||
for interval in intervals:
|
||||
enriched = enrich_single_interval(interval)
|
||||
results.append(enriched)
|
||||
|
||||
# ✅ Fast - bulk processing
|
||||
results = enrich_intervals_bulk(intervals)
|
||||
```
|
||||
|
||||
### Async Best Practices
|
||||
|
||||
**1. Concurrent API calls:**
|
||||
```python
|
||||
# ❌ Sequential (slow)
|
||||
user_data = await fetch_user_data()
|
||||
price_data = await fetch_price_data()
|
||||
|
||||
# ✅ Concurrent (fast)
|
||||
user_data, price_data = await asyncio.gather(
|
||||
fetch_user_data(),
|
||||
fetch_price_data()
|
||||
)
|
||||
```
|
||||
|
||||
**2. Don't block event loop:**
|
||||
```python
|
||||
# ❌ Blocking
|
||||
result = heavy_computation() # Blocks for seconds
|
||||
|
||||
# ✅ Non-blocking
|
||||
result = await hass.async_add_executor_job(heavy_computation)
|
||||
```
|
||||
|
||||
## Memory Management
|
||||
|
||||
### Avoid Memory Leaks
|
||||
|
||||
**1. Clear references:**
|
||||
```python
|
||||
class Coordinator:
|
||||
async def async_shutdown(self):
|
||||
"""Clean up resources."""
|
||||
self._listeners.clear()
|
||||
self._data = None
|
||||
self._cache = None
|
||||
```
|
||||
|
||||
**2. Use weak references for callbacks:**
|
||||
```python
|
||||
import weakref
|
||||
|
||||
class Manager:
|
||||
def __init__(self):
|
||||
self._callbacks: list[weakref.ref] = []
|
||||
|
||||
def register(self, callback):
|
||||
self._callbacks.append(weakref.ref(callback))
|
||||
```
|
||||
|
||||
### Efficient Data Structures
|
||||
|
||||
**Use appropriate types:**
|
||||
```python
|
||||
# ❌ List for lookups (O(n))
|
||||
if timestamp in timestamp_list:
|
||||
...
|
||||
|
||||
# ✅ Set for lookups (O(1))
|
||||
if timestamp in timestamp_set:
|
||||
...
|
||||
|
||||
# ❌ List comprehension with filter
|
||||
results = [x for x in items if condition(x)]
|
||||
|
||||
# ✅ Generator for large datasets
|
||||
results = (x for x in items if condition(x))
|
||||
```
|
||||
|
||||
## Coordinator Optimization
|
||||
|
||||
### Minimize API Calls
|
||||
|
||||
**Already implemented:**
|
||||
- Cache valid until midnight
|
||||
- User data cached for 24h
|
||||
- Only poll when tomorrow data expected
|
||||
|
||||
**Monitor API usage:**
|
||||
```python
|
||||
_LOGGER.debug("API call: %s (cache_age=%s)",
|
||||
endpoint, cache_age)
|
||||
```
|
||||
|
||||
### Smart Updates
|
||||
|
||||
**Only update when needed:**
|
||||
```python
|
||||
async def _async_update_data(self) -> dict:
|
||||
"""Fetch data from API."""
|
||||
if self._is_cache_valid():
|
||||
_LOGGER.debug("Using cached data")
|
||||
return self.data
|
||||
|
||||
# Fetch new data
|
||||
return await self._fetch_data()
|
||||
```
|
||||
|
||||
## Database Impact
|
||||
|
||||
### State Class Selection
|
||||
|
||||
**Affects long-term statistics storage:**
|
||||
```python
|
||||
# ❌ MEASUREMENT for prices (stores every change)
|
||||
state_class=SensorStateClass.MEASUREMENT # ~35K records/year
|
||||
|
||||
# ✅ None for prices (no long-term stats)
|
||||
state_class=None # Only current state
|
||||
|
||||
# ✅ TOTAL for counters only
|
||||
state_class=SensorStateClass.TOTAL # For cumulative values
|
||||
```
|
||||
|
||||
### Attribute Size
|
||||
|
||||
**Keep attributes minimal:**
|
||||
```python
|
||||
# ❌ Large nested structures (KB per update)
|
||||
attributes = {
|
||||
"all_intervals": [...], # 384 intervals
|
||||
"full_history": [...], # Days of data
|
||||
}
|
||||
|
||||
# ✅ Essential data only (bytes per update)
|
||||
attributes = {
|
||||
"timestamp": "...",
|
||||
"rating_level": "...",
|
||||
"next_interval": "...",
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Performance
|
||||
|
||||
### Benchmark Tests
|
||||
|
||||
```python
|
||||
import pytest
|
||||
import time
|
||||
|
||||
@pytest.mark.benchmark
|
||||
def test_period_calculation_performance(coordinator):
|
||||
"""Period calculation should complete in <100ms."""
|
||||
start = time.perf_counter()
|
||||
|
||||
periods = calculate_periods(coordinator.data)
|
||||
|
||||
duration = time.perf_counter() - start
|
||||
assert duration < 0.1, f"Too slow: {duration:.3f}s"
|
||||
```
|
||||
|
||||
### Load Testing
|
||||
|
||||
```python
|
||||
@pytest.mark.integration
|
||||
async def test_multiple_homes_performance(hass):
|
||||
"""Test with 10 homes."""
|
||||
coordinators = []
|
||||
for i in range(10):
|
||||
coordinator = create_coordinator(hass, home_id=f"home_{i}")
|
||||
await coordinator.async_refresh()
|
||||
coordinators.append(coordinator)
|
||||
|
||||
# Verify memory usage
|
||||
# Verify update times
|
||||
```
|
||||
|
||||
## Monitoring in Production
|
||||
|
||||
### Log Performance Metrics
|
||||
|
||||
```python
|
||||
@timing
|
||||
async def _async_update_data(self) -> dict:
|
||||
"""Fetch data with timing."""
|
||||
result = await self._fetch_data()
|
||||
_LOGGER.info("Update completed in %.2fs", timing_duration)
|
||||
return result
|
||||
```
|
||||
|
||||
### Memory Tracking
|
||||
|
||||
```python
|
||||
import psutil
|
||||
import os
|
||||
|
||||
process = psutil.Process(os.getpid())
|
||||
memory_mb = process.memory_info().rss / 1024**2
|
||||
_LOGGER.debug("Current memory usage: %.2f MB", memory_mb)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
💡 **Related:**
|
||||
- [Caching Strategy](caching-strategy.md) - Cache layers
|
||||
- [Architecture](architecture.md) - System design
|
||||
- [Debugging](debugging.md) - Profiling tools
|
||||
|
|
@ -582,7 +582,7 @@ MIN_CONTEXT_SIZE = 3 # Minimum intervals for regression
|
|||
- Single pass through price data
|
||||
- O(n) complexity with small context window
|
||||
- No iterative refinement needed
|
||||
- Typical processing time: <1ms for 96 intervals
|
||||
- Typical processing time: `<`1ms for 96 intervals
|
||||
|
||||
**Example Debug Output:**
|
||||
```
|
||||
|
|
@ -808,7 +808,7 @@ When debugging period calculation issues:
|
|||
|
||||
4. **Check Min_Distance Scaling**
|
||||
- Debug messages show "High flex X% detected: Reducing min_distance Y% → Z%"
|
||||
- If scale factor <0.8 (20% reduction): High flex is active
|
||||
- If scale factor `<`0.8 (20% reduction): High flex is active
|
||||
- If periods still not found: Filters conflict even with scaling
|
||||
|
||||
5. **Check Outlier Filtering**
|
||||
|
|
@ -944,7 +944,7 @@ else: # Normal day
|
|||
- This gives: 5% → 6% (20%), 15% → 18% (20%), 40% → 43% (7.5%)
|
||||
|
||||
**Why Not Implemented:**
|
||||
- Very low base flex (<10%) unusual
|
||||
- Very low base flex (`<`10%) unusual
|
||||
- Users with strict requirements likely disable relaxation
|
||||
- Simplicity preferred over edge case optimization
|
||||
|
||||
|
|
@ -1103,10 +1103,10 @@ Low volatility (< 15%) means classification changes are less economically signif
|
|||
|
||||
## References
|
||||
|
||||
- [User Documentation: Period Calculation](../user/period-calculation.md)
|
||||
- [User Documentation: Period Calculation](https://jpawlowski.github.io/hass.tibber_prices/user/period-calculation)
|
||||
- [Architecture Overview](./architecture.md)
|
||||
- [Caching Strategy](./caching-strategy.md)
|
||||
- [AGENTS.md](../../AGENTS.md) - AI assistant memory (implementation patterns)
|
||||
- [AGENTS.md](https://github.com/jpawlowski/hass.tibber_prices/blob/main/AGENTS.md) - AI assistant memory (implementation patterns)
|
||||
|
||||
## Changelog
|
||||
|
||||
|
|
@ -20,8 +20,8 @@ Not every code change needs a detailed plan. Create a refactoring plan when:
|
|||
|
||||
🟢 **Small changes - no planning needed:**
|
||||
|
||||
- Bug fixes (straightforward, <100 lines)
|
||||
- Small features (<3 files, clear approach)
|
||||
- Bug fixes (straightforward, `<`100 lines)
|
||||
- Small features (`<`3 files, clear approach)
|
||||
- Documentation updates
|
||||
- Cosmetic changes (formatting, renaming)
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ The **sensor/ package refactoring** (Nov 2025) is a successful example:
|
|||
**After:**
|
||||
|
||||
- `sensor/` package with 5 focused modules
|
||||
- Each module <800 lines
|
||||
- Each module `<`800 lines
|
||||
- Clear separation of concerns
|
||||
|
||||
**Process:**
|
||||
|
|
@ -158,7 +158,7 @@ The **sensor/ package refactoring** (Nov 2025) is a successful example:
|
|||
- Clear file lifecycle (CREATE/MODIFY/DELETE/RENAME)
|
||||
- Phase-by-phase approach enables safe rollback
|
||||
|
||||
See the complete plan: [module-splitting-plan.md](module-splitting-plan.md)
|
||||
**Note:** The complete module splitting plan was documented during implementation but has been superseded by the actual code structure.
|
||||
|
||||
## Phase-by-Phase Implementation
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ This project uses AI heavily (GitHub Copilot, Claude). The planning process supp
|
|||
- `docs/development/`: Practical, focused, human-optimized
|
||||
- Both stay in sync but serve different audiences
|
||||
|
||||
See [AGENTS.md](../../AGENTS.md) section "Planning Major Refactorings" for AI-specific guidance.
|
||||
See [AGENTS.md](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) section "Planning Major Refactorings" for AI-specific guidance.
|
||||
|
||||
## Tools and Resources
|
||||
|
||||
|
|
@ -373,7 +373,7 @@ Document WHY the plan changed (helps future refactorings).
|
|||
|
||||
**A:** No! Use judgment:
|
||||
|
||||
- **Small changes (<100 lines, clear approach)**: Just do it, no plan needed
|
||||
- **Small changes (`<`100 lines, clear approach)**: Just do it, no plan needed
|
||||
- **Medium changes (unclear scope)**: Write rough outline, refine if needed
|
||||
- **Large changes (>500 lines, >5 files)**: Full planning process
|
||||
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Release Notes Generation
|
||||
|
||||
This project supports **three ways** to generate release notes from conventional commits, plus **automatic version management**.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Development Setup
|
||||
|
||||
> **Note:** This guide is under construction. For now, please refer to [`AGENTS.md`](../../AGENTS.md) for detailed setup information.
|
||||
> **Note:** This guide is under construction. For now, please refer to [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) for detailed setup information.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -54,4 +54,4 @@ Visit http://localhost:8123
|
|||
./scripts/release/hassfest
|
||||
```
|
||||
|
||||
See [`AGENTS.md`](../../AGENTS.md) for detailed patterns and conventions.
|
||||
See [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md) for detailed patterns and conventions.
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Timer Architecture
|
||||
|
||||
This document explains the timer/scheduler system in the Tibber Prices integration - what runs when, why, and how they coordinate.
|
||||
|
|
@ -406,7 +410,7 @@ _LOGGER.setLevel(logging.DEBUG)
|
|||
|
||||
- **[Architecture](./architecture.md)** - Overall system design, data flow
|
||||
- **[Caching Strategy](./caching-strategy.md)** - Cache lifetimes, invalidation, midnight turnover
|
||||
- **[AGENTS.md](../../AGENTS.md)** - Complete reference for AI development
|
||||
- **[AGENTS.md](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md)** - Complete reference for AI development
|
||||
|
||||
---
|
||||
|
||||
220
docs/developer/docusaurus.config.ts
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
import type {Config} from '@docusaurus/types';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
|
||||
const config: Config = {
|
||||
title: 'Tibber Prices - Developer Guide',
|
||||
tagline: 'Developer documentation for the Tibber Prices custom integration',
|
||||
favicon: 'img/logo.svg',
|
||||
|
||||
future: {
|
||||
v4: true,
|
||||
},
|
||||
|
||||
url: 'https://jpawlowski.github.io',
|
||||
baseUrl: '/hass.tibber_prices/developer/',
|
||||
|
||||
organizationName: 'jpawlowski',
|
||||
projectName: 'hass.tibber_prices',
|
||||
deploymentBranch: 'gh-pages',
|
||||
trailingSlash: false,
|
||||
|
||||
onBrokenLinks: 'warn',
|
||||
|
||||
markdown: {
|
||||
mermaid: true,
|
||||
hooks: {
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
themes: ['@docusaurus/theme-mermaid'],
|
||||
|
||||
plugins: [
|
||||
'docusaurus-lunr-search',
|
||||
],
|
||||
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
headTags: [
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'preconnect',
|
||||
href: 'https://fonts.googleapis.com',
|
||||
},
|
||||
},
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'preconnect',
|
||||
href: 'https://fonts.gstatic.com',
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
},
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'stylesheet',
|
||||
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
{
|
||||
docs: {
|
||||
routeBasePath: '/',
|
||||
sidebarPath: './sidebars.ts',
|
||||
editUrl: ({versionDocsDirPath, docPath}) => {
|
||||
if (versionDocsDirPath.includes('_versioned_')) {
|
||||
const version = versionDocsDirPath.match(/version-([^/]+)/)?.[1] || 'main';
|
||||
return `https://github.com/jpawlowski/hass.tibber_prices/tree/${version}/docs/developer/docs/${docPath}`;
|
||||
}
|
||||
return `https://github.com/jpawlowski/hass.tibber_prices/tree/main/docs/developer/docs/${docPath}`;
|
||||
},
|
||||
showLastUpdateTime: true,
|
||||
versions: {
|
||||
current: {
|
||||
label: 'Next 🚧',
|
||||
banner: 'unreleased',
|
||||
badge: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
mermaid: {
|
||||
theme: {light: 'base', dark: 'dark'},
|
||||
options: {
|
||||
themeVariables: {
|
||||
// Light mode colors
|
||||
primaryColor: '#e6f7ff',
|
||||
primaryTextColor: '#1a1a1a',
|
||||
primaryBorderColor: '#00b9e7',
|
||||
lineColor: '#00b9e7',
|
||||
secondaryColor: '#e6fff5',
|
||||
secondaryTextColor: '#1a1a1a',
|
||||
secondaryBorderColor: '#00ffa3',
|
||||
tertiaryColor: '#fff9e6',
|
||||
tertiaryTextColor: '#1a1a1a',
|
||||
tertiaryBorderColor: '#ffb800',
|
||||
noteBkgColor: '#e6f7ff',
|
||||
noteTextColor: '#1a1a1a',
|
||||
noteBorderColor: '#00b9e7',
|
||||
// Node styling
|
||||
mainBkg: '#ffffff',
|
||||
nodeBorder: '#00b9e7',
|
||||
clusterBkg: '#f0f9ff',
|
||||
clusterBorder: '#00b9e7',
|
||||
// Font styling
|
||||
fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
|
||||
fontSize: '14px',
|
||||
},
|
||||
},
|
||||
},
|
||||
image: 'img/social-card.png',
|
||||
colorMode: {
|
||||
respectPrefersColorScheme: true,
|
||||
},
|
||||
docs: {
|
||||
sidebar: {
|
||||
hideable: true,
|
||||
autoCollapseCategories: true,
|
||||
},
|
||||
},
|
||||
navbar: {
|
||||
title: 'Tibber Prices HA',
|
||||
logo: {
|
||||
alt: 'Tibber Prices Integration Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: '/intro',
|
||||
label: 'Developer Guide',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
href: 'https://jpawlowski.github.io/hass.tibber_prices/user/',
|
||||
label: 'User Docs',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'docsVersionDropdown',
|
||||
position: 'right',
|
||||
dropdownActiveClassDisabled: true,
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Documentation',
|
||||
items: [
|
||||
{
|
||||
label: 'User Guide',
|
||||
href: 'https://jpawlowski.github.io/hass.tibber_prices/user/',
|
||||
},
|
||||
{
|
||||
label: 'Developer Guide',
|
||||
to: '/intro',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub Issues',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices/issues',
|
||||
},
|
||||
{
|
||||
label: 'Home Assistant Community',
|
||||
href: 'https://community.home-assistant.io/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices',
|
||||
},
|
||||
{
|
||||
label: 'Release Notes',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices/releases',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Not affiliated with Tibber AS. Community-maintained custom integration. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
additionalLanguages: ['bash', 'yaml', 'json', 'python'],
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
||||
export default config;
|
||||
20229
docs/developer/package-lock.json
generated
Normal file
49
docs/developer/package.json
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "docs-split-developer",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@docusaurus/theme-mermaid": "^3.9.2",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-lunr-search": "^3.6.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.9.2",
|
||||
"@docusaurus/tsconfig": "3.9.2",
|
||||
"@docusaurus/types": "3.9.2",
|
||||
"typescript": "~5.6.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 3 chrome version",
|
||||
"last 3 firefox version",
|
||||
"last 5 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0"
|
||||
}
|
||||
}
|
||||
56
docs/developer/sidebars.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
|
||||
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
const sidebars: SidebarsConfig = {
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
{
|
||||
type: 'category',
|
||||
label: '🏗️ Architecture',
|
||||
items: ['architecture', 'timer-architecture', 'caching-strategy', 'api-reference'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '💻 Development',
|
||||
items: ['setup', 'coding-guidelines', 'critical-patterns', 'debugging'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '📐 Advanced Topics',
|
||||
items: ['period-calculation-theory', 'refactoring-guide', 'performance'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '📝 Contributing',
|
||||
items: ['contributing'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '🚀 Release',
|
||||
items: ['release-management', 'testing'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default sidebars;
|
||||
214
docs/developer/src/css/custom.css
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* Modern font stack */
|
||||
:root {
|
||||
--ifm-font-family-base: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
--ifm-heading-font-family: 'Space Grotesk', var(--ifm-font-family-base);
|
||||
--ifm-font-family-monospace: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
/* Tibber-inspired electric color scheme */
|
||||
:root {
|
||||
/* Primary: Electric blue */
|
||||
--ifm-color-primary: #00b9e7;
|
||||
--ifm-color-primary-dark: #00a7d0;
|
||||
--ifm-color-primary-darker: #009ec4;
|
||||
--ifm-color-primary-darkest: #0082a2;
|
||||
--ifm-color-primary-light: #00cbfe;
|
||||
--ifm-color-primary-lighter: #19d1ff;
|
||||
--ifm-color-primary-lightest: #4dddff;
|
||||
|
||||
/* Accent: Energy green */
|
||||
--ifm-color-success: #00ffa3;
|
||||
|
||||
/* Warning: Price orange */
|
||||
--ifm-color-warning: #ffb800;
|
||||
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 185, 231, 0.1);
|
||||
|
||||
/* Modern border radius */
|
||||
--ifm-global-radius: 0.75rem;
|
||||
--ifm-button-border-radius: 0.75rem;
|
||||
--ifm-card-border-radius: 1rem;
|
||||
--ifm-code-border-radius: 0.5rem;
|
||||
|
||||
/* Subtle shadows for depth */
|
||||
--ifm-global-shadow-lw: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
--ifm-global-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
--ifm-global-shadow-tl: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
|
||||
/* Hero background gradient */
|
||||
--ifm-hero-background-color: linear-gradient(135deg, #00b9e7 0%, #00ffa3 100%);
|
||||
}
|
||||
|
||||
/* Dark mode with electric theme */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #00d4ff;
|
||||
--ifm-color-primary-dark: #00c0e6;
|
||||
--ifm-color-primary-darker: #00b5d9;
|
||||
--ifm-color-primary-darkest: #0095b3;
|
||||
--ifm-color-primary-light: #19ddff;
|
||||
--ifm-color-primary-lighter: #33e1ff;
|
||||
--ifm-color-primary-lightest: #66e9ff;
|
||||
|
||||
/* Accent: Brighter green in dark mode */
|
||||
--ifm-color-success: #00ffb3;
|
||||
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 212, 255, 0.15);
|
||||
|
||||
/* Darker background for better contrast */
|
||||
--ifm-background-color: #1a1a1a;
|
||||
--ifm-background-surface-color: #242424;
|
||||
|
||||
/* Darker shadows for dark mode */
|
||||
--ifm-global-shadow-lw: 0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2);
|
||||
--ifm-global-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
||||
--ifm-global-shadow-tl: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Hero section styling */
|
||||
.hero--primary {
|
||||
background: linear-gradient(135deg, #00b9e7 0%, #0099cc 50%, #ffb800 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero--primary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(0, 185, 231, 0.95) 0%, rgba(0, 153, 204, 0.95) 50%, rgba(255, 184, 0, 0.85) 100%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.hero--primary .container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .hero--primary {
|
||||
background: linear-gradient(135deg, #00506b 0%, #003d52 50%, #665000 100%);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .hero--primary::before {
|
||||
background: linear-gradient(135deg, rgba(0, 80, 107, 0.95) 0%, rgba(0, 61, 82, 0.95) 50%, rgba(102, 80, 0, 0.85) 100%);
|
||||
}
|
||||
|
||||
/* Unreleased version banner styling */
|
||||
[data-theme='light'] .theme-doc-version-banner {
|
||||
background-color: #fff4e6;
|
||||
border-color: #ffb800;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .theme-doc-version-banner {
|
||||
background-color: #2d2000;
|
||||
border-color: #ffb800;
|
||||
}
|
||||
|
||||
/* Make code blocks stand out */
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 185, 231, 0.2);
|
||||
display: block;
|
||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 212, 255, 0.2);
|
||||
}
|
||||
|
||||
/* Sidebar customization */
|
||||
.theme-doc-sidebar-container {
|
||||
border-right: 1px solid var(--ifm-toc-border-color);
|
||||
}
|
||||
|
||||
/* Table of contents highlighting */
|
||||
.table-of-contents__link--active {
|
||||
color: var(--ifm-color-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Admonition styling */
|
||||
.admonition {
|
||||
border-left-width: 4px;
|
||||
}
|
||||
|
||||
.admonition-note {
|
||||
border-left-color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.admonition-tip {
|
||||
border-left-color: var(--ifm-color-success);
|
||||
}
|
||||
|
||||
.admonition-warning {
|
||||
border-left-color: var(--ifm-color-warning);
|
||||
}
|
||||
|
||||
/* Features section on homepage */
|
||||
.features {
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.features h3 {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .features h3 {
|
||||
color: var(--ifm-color-primary-lighter);
|
||||
}
|
||||
|
||||
/* Card styling with modern shadows */
|
||||
.card {
|
||||
border-radius: var(--ifm-card-border-radius);
|
||||
box-shadow: var(--ifm-global-shadow-md);
|
||||
transition: box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: var(--ifm-global-shadow-tl);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Navbar with subtle shadow */
|
||||
.navbar {
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
}
|
||||
|
||||
/* Code blocks with modern styling */
|
||||
code {
|
||||
border-radius: var(--ifm-code-border-radius);
|
||||
}
|
||||
|
||||
/* Buttons with modern feel */
|
||||
.button {
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.025em;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--ifm-global-shadow-md);
|
||||
}
|
||||
|
||||
/* Headings with Space Grotesk */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--ifm-heading-font-family);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
/* Smooth transitions everywhere */
|
||||
* {
|
||||
transition-property: background-color, border-color, color, fill, stroke;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
23
docs/developer/src/pages/index.module.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 996px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
117
docs/developer/src/pages/index.tsx
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import type {ReactNode} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import {useColorMode} from '@docusaurus/theme-common';
|
||||
import Layout from '@theme/Layout';
|
||||
import Heading from '@theme/Heading';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
function HomepageHeader() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {colorMode} = useColorMode();
|
||||
const headerUrl = useBaseUrl(colorMode === 'dark' ? '/img/header-dark.svg' : '/img/header.svg');
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<div style={{ marginBottom: '2rem' }}>
|
||||
<img src={headerUrl} alt="Tibber Prices for Tibber" style={{ maxWidth: '600px', width: '100%', height: 'auto' }} />
|
||||
</div>
|
||||
<Heading as="h1" className="hero__title">
|
||||
{siteConfig.title}
|
||||
</Heading>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/intro">
|
||||
Get Started →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
function HomepageFeatures() {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🏗️ Clean Architecture</h3>
|
||||
<p>
|
||||
Modular design with separation of concerns. Calculator pattern for business logic,
|
||||
coordinator-based data flow, and comprehensive caching strategies.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🧪 Test Coverage</h3>
|
||||
<p>
|
||||
Comprehensive test suite with unit, integration, and E2E tests. Resource leak
|
||||
detection, lifecycle validation, and performance benchmarks.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>📚 Full Documentation</h3>
|
||||
<p>
|
||||
Complete API reference, architecture diagrams, coding guidelines, and
|
||||
debugging guides. Everything you need to contribute effectively.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row margin-top--lg">
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🔧 DevContainer Ready</h3>
|
||||
<p>
|
||||
Pre-configured development environment with all dependencies. VS Code
|
||||
integration, linting, type checking, and debugging tools included.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>⚡ Performance Focused</h3>
|
||||
<p>
|
||||
Multi-layer caching, optimized algorithms, and efficient data structures.
|
||||
Coordinator updates in <500ms, sensor updates in <10ms.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🤝 Community Driven</h3>
|
||||
<p>
|
||||
Open source project with active development. Conventional commits,
|
||||
semantic versioning, and automated release management.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): ReactNode {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title={siteConfig.title}
|
||||
description="Developer documentation for the Tibber Prices custom integration for Home Assistant">
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
7
docs/developer/src/pages/markdown-page.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Markdown page example
|
||||
---
|
||||
|
||||
# Markdown page example
|
||||
|
||||
You don't need React to write simple standalone pages.
|
||||
0
docs/developer/static/.nojekyll
Normal file
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
BIN
docs/developer/static/img/docusaurus-social-card.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/developer/static/img/docusaurus.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
74
docs/developer/static/img/header-dark.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name (light text for dark mode) -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#E8E8E8">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#B0B0B0">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider (lighter) -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#666666"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text (lighter) -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#888888">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text (light text for dark mode) -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#E8E8E8">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
74
docs/developer/static/img/header.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#333333">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#666666">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#CCCCCC"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#999999">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#333333">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
BIN
docs/developer/static/img/logo.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
29
docs/developer/static/img/logo.svg
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Tibber Prices Logo: Lightning bolt + Price tag + T -->
|
||||
<defs>
|
||||
<linearGradient id="boltGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Stylized lightning bolt (Tibber inspired) -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGradient)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGradient)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Currency symbol inside price tag -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
171
docs/developer/static/img/undraw_docusaurus_mountain.svg
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
|
||||
<title>Easy to Use</title>
|
||||
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
|
||||
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
|
||||
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
|
||||
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
|
||||
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
|
||||
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
|
||||
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
|
||||
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
|
||||
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
|
||||
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
|
||||
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
|
||||
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
|
||||
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
|
||||
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
|
||||
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 31 KiB |
170
docs/developer/static/img/undraw_docusaurus_react.svg
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
|
||||
<title>Powered by React</title>
|
||||
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
|
||||
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
|
||||
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
|
||||
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
|
||||
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
|
||||
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
|
||||
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
|
||||
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
|
||||
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
|
||||
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
|
||||
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
|
||||
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
|
||||
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
|
||||
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
|
||||
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
|
||||
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
|
||||
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="React-icon" transform="translate(906.3 541.56)">
|
||||
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
|
||||
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
|
||||
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
|
||||
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 35 KiB |
40
docs/developer/static/img/undraw_docusaurus_tree.svg
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
|
||||
<title>Focus on What Matters</title>
|
||||
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
|
||||
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
|
||||
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
|
||||
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
|
||||
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
|
||||
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
|
||||
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
|
||||
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
|
||||
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
|
||||
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
|
||||
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
8
docs/developer/tsconfig.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@docusaurus/tsconfig",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": [".docusaurus", "build"]
|
||||
}
|
||||
217
docs/index.html
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tibber Prices Documentation</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
padding: 60px 40px;
|
||||
max-width: 800px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 120px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.logo svg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
color: #1a202c;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 18px;
|
||||
color: #718096;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: #fff5f5;
|
||||
border: 2px solid #fc8181;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 40px;
|
||||
color: #742a2a;
|
||||
}
|
||||
|
||||
.warning strong {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.docs-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.doc-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 12px;
|
||||
padding: 32px 24px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.doc-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.doc-card.user {
|
||||
background: linear-gradient(135deg, #00D4FF 0%, #0099CC 100%);
|
||||
}
|
||||
|
||||
.doc-card.developer {
|
||||
background: linear-gradient(135deg, #00FFA3 0%, #00CC7A 100%);
|
||||
}
|
||||
|
||||
.doc-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.doc-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.doc-description {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.container {
|
||||
padding: 40px 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.docs-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Tibber lightning bolt inspired shape -->
|
||||
<defs>
|
||||
<linearGradient id="boltGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Stylized lightning bolt (Tibber inspired) -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z" fill="url(#boltGradient)"
|
||||
stroke="none" />
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGradient)" stroke="white" stroke-width="4" />
|
||||
|
||||
<!-- Currency symbols inside price tag -->
|
||||
<text x="145" y="58" font-family="Arial, sans-serif" font-size="32" font-weight="bold" fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
|
||||
<!-- Small "T" from Tibber style at bottom -->
|
||||
<text x="100" y="185" font-family="Arial, sans-serif" font-size="24" font-weight="bold" fill="#667eea"
|
||||
text-anchor="middle">T</text>
|
||||
</svg>
|
||||
</div>
|
||||
<h1>Tibber Prices Documentation</h1>
|
||||
<p class="tagline">Custom Home Assistant Integration</p>
|
||||
|
||||
<div class="warning">
|
||||
<strong>⚠️ Not affiliated with Tibber</strong>
|
||||
This is an independent, community-maintained custom integration. Not an official Tibber product.
|
||||
</div>
|
||||
|
||||
<div class="docs-grid">
|
||||
<a href="user/" class="doc-card user">
|
||||
<div class="doc-icon">👤</div>
|
||||
<div class="doc-title">User Documentation</div>
|
||||
<div class="doc-description">Installation guides, configuration, sensors, and automation examples</div>
|
||||
</a>
|
||||
|
||||
<a href="developer/" class="doc-card developer">
|
||||
<div class="doc-icon">🔧</div>
|
||||
<div class="doc-title">Developer Documentation</div>
|
||||
<div class="doc-description">Architecture, contributing guidelines, and development setup</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<a href="https://github.com/jpawlowski/hass.tibber_prices" class="link">📦 GitHub Repository</a>
|
||||
<a href="https://github.com/jpawlowski/hass.tibber_prices/releases" class="link">📋 Changelog</a>
|
||||
<a href="https://github.com/jpawlowski/hass.tibber_prices/issues" class="link">🐛 Report Issues</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
20
docs/user/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
|
@ -1,51 +1,41 @@
|
|||
# User Documentation
|
||||
# Website
|
||||
|
||||
Welcome to Tibber Prices! This integration provides enhanced electricity price data from Tibber with quarter-hourly precision, statistical analysis, and intelligent ratings.
|
||||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
## 📚 Documentation
|
||||
## Installation
|
||||
|
||||
- **[Installation](installation.md)** - How to install via HACS and configure the integration
|
||||
- **[Configuration](configuration.md)** - Setting up your Tibber API token and price thresholds
|
||||
- **[Period Calculation](period-calculation.md)** - How Best/Peak Price periods are calculated and configured
|
||||
- **[Sensors](sensors.md)** - Available sensors, their states, and attributes
|
||||
- **[Dynamic Icons](dynamic-icons.md)** - State-based automatic icon changes
|
||||
- **[Dynamic Icon Colors](icon-colors.md)** - Using icon_color attribute for color-coded dashboards
|
||||
- **[Actions](actions.md)** - Custom actions (service endpoints) and how to use them
|
||||
- **[Chart Examples](chart-examples.md)** - ✨ ApexCharts visualizations with screenshots
|
||||
- **[Automation Examples](automation-examples.md)** - Ready-to-use automation recipes
|
||||
- **[Troubleshooting](troubleshooting.md)** - Common issues and solutions
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
## Local Development
|
||||
|
||||
1. **Install via HACS** (add as custom repository)
|
||||
2. **Add Integration** in Home Assistant → Settings → Devices & Services
|
||||
3. **Enter Tibber API Token** (get yours at [developer.tibber.com](https://developer.tibber.com/))
|
||||
4. **Configure Price Thresholds** (optional, defaults work for most users)
|
||||
5. **Start Using Sensors** in automations, dashboards, and scripts!
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
## ✨ Key Features
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
- **Quarter-hourly precision** - 15-minute intervals for accurate price tracking
|
||||
- **Statistical analysis** - Trailing/leading 24h averages for context
|
||||
- **Price ratings** - LOW/NORMAL/HIGH classification based on your thresholds
|
||||
- **Best/Peak hour detection** - Automatic detection of cheapest/peak periods with configurable filters ([learn how](period-calculation.md))
|
||||
- **Beautiful ApexCharts** - Auto-generated chart configurations with dynamic Y-axis scaling ([see examples](chart-examples.md))
|
||||
- **Chart metadata sensor** - Dynamic chart configuration for optimal visualization
|
||||
- **Multi-currency support** - EUR, NOK, SEK with proper minor units (ct, øre, öre)
|
||||
## Build
|
||||
|
||||
## 🔗 Useful Links
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
- [GitHub Repository](https://github.com/jpawlowski/hass.tibber_prices)
|
||||
- [Issue Tracker](https://github.com/jpawlowski/hass.tibber_prices/issues)
|
||||
- [Release Notes](https://github.com/jpawlowski/hass.tibber_prices/releases)
|
||||
- [Home Assistant Community](https://community.home-assistant.io/)
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
## 🤝 Need Help?
|
||||
## Deployment
|
||||
|
||||
- Check the [Troubleshooting Guide](troubleshooting.md)
|
||||
- Search [existing issues](https://github.com/jpawlowski/hass.tibber_prices/issues)
|
||||
- Open a [new issue](https://github.com/jpawlowski/hass.tibber_prices/issues/new) if needed
|
||||
Using SSH:
|
||||
|
||||
---
|
||||
```bash
|
||||
USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
**Note:** These guides are for end users. If you want to contribute to development, see the [Developer Documentation](../development/).
|
||||
Not using SSH:
|
||||
|
||||
```bash
|
||||
GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ data:
|
|||
|
||||
**Screenshot:**
|
||||
|
||||
<img src="../../images/charts/today.jpg" width="800" alt="Today's Prices - Static 24h View">
|
||||

|
||||
|
||||
**Key Features:**
|
||||
- ✅ Color-coded price levels (LOW, NORMAL, HIGH)
|
||||
|
|
@ -70,7 +70,7 @@ data:
|
|||
|
||||
**Screenshot:**
|
||||
|
||||
<img src="../../images/charts/rolling-window.jpg" width="800" alt="Rolling 48h Window with Dynamic Y-Axis Scaling">
|
||||

|
||||
|
||||
**Key Features:**
|
||||
- ✅ **Dynamic Y-axis scaling** via `chart_metadata` sensor
|
||||
|
|
@ -104,7 +104,7 @@ data:
|
|||
|
||||
**Screenshot:**
|
||||
|
||||
<img src="../../images/charts/rolling-window-autozoom.jpg" width="800" alt="Rolling Window Auto-Zoom - Progressive Zoom Effect">
|
||||

|
||||
|
||||
**Key Features:**
|
||||
- ✅ **Progressive zoom:** Graph span decreases every 15 minutes
|
||||
|
|
@ -292,14 +292,14 @@ cards:
|
|||
|
||||
1. **Today View (Static)** - Representative of all fixed day views (yesterday/today/tomorrow)
|
||||
|
||||
<img src="../../images/charts/today.jpg" width="600" alt="Today View">
|
||||

|
||||
|
||||
2. **Rolling Window (Dynamic)** - Shows dynamic Y-axis scaling and 48h window
|
||||
|
||||
<img src="../../images/charts/rolling-window.jpg" width="600" alt="Rolling Window">
|
||||

|
||||
|
||||
3. **Rolling Window Auto-Zoom (Dynamic)** - Shows progressive zoom effect
|
||||
|
||||
<img src="../../images/charts/rolling-window-autozoom.jpg" width="600" alt="Rolling Window Auto-Zoom">
|
||||

|
||||
|
||||
**Note:** Tomorrow view is visually identical to Today view (same chart type, just different data).
|
||||
67
docs/user/docs/concepts.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Core Concepts
|
||||
|
||||
Understanding the fundamental concepts behind the Tibber Prices integration.
|
||||
|
||||
## Price Intervals
|
||||
|
||||
The integration works with **quarter-hourly intervals** (15 minutes):
|
||||
|
||||
- Each interval has a start time (e.g., 14:00, 14:15, 14:30, 14:45)
|
||||
- Prices are fixed for the entire interval
|
||||
- Synchronized with Tibber's smart meter readings
|
||||
|
||||
## Price Ratings
|
||||
|
||||
Prices are automatically classified into **rating levels**:
|
||||
|
||||
- **VERY_CHEAP** - Exceptionally low prices (great for energy-intensive tasks)
|
||||
- **CHEAP** - Below average prices (good for flexible loads)
|
||||
- **NORMAL** - Around average prices (regular consumption)
|
||||
- **EXPENSIVE** - Above average prices (reduce consumption if possible)
|
||||
- **VERY_EXPENSIVE** - Exceptionally high prices (avoid heavy loads)
|
||||
|
||||
Rating is based on **statistical analysis** comparing current price to:
|
||||
- Daily average
|
||||
- Trailing 24-hour average
|
||||
- User-configured thresholds
|
||||
|
||||
## Price Periods
|
||||
|
||||
**Best Price Periods** and **Peak Price Periods** are automatically detected time windows:
|
||||
|
||||
- **Best Price Period** - Consecutive intervals with favorable prices (for scheduling energy-heavy tasks)
|
||||
- **Peak Price Period** - Time windows with highest prices (to avoid or shift consumption)
|
||||
|
||||
Periods can:
|
||||
- Span multiple hours
|
||||
- Cross midnight boundaries
|
||||
- Adapt based on your configuration (flex, min_distance, rating levels)
|
||||
|
||||
See [Period Calculation](period-calculation.md) for detailed configuration.
|
||||
|
||||
## Statistical Analysis
|
||||
|
||||
The integration enriches every interval with context:
|
||||
|
||||
- **Trailing 24h Average** - Average price over the last 24 hours
|
||||
- **Leading 24h Average** - Average price over the next 24 hours
|
||||
- **Price Difference** - How much current price deviates from average (in %)
|
||||
- **Volatility** - Price stability indicator (LOW, MEDIUM, HIGH)
|
||||
|
||||
This helps you understand if current prices are exceptional or typical.
|
||||
|
||||
## Multi-Home Support
|
||||
|
||||
You can add multiple Tibber homes to track prices for:
|
||||
- Different locations
|
||||
- Different electricity contracts
|
||||
- Comparison between regions
|
||||
|
||||
Each home gets its own set of sensors with unique entity IDs.
|
||||
|
||||
---
|
||||
|
||||
💡 **Next Steps:**
|
||||
- [Glossary](glossary.md) - Detailed term definitions
|
||||
- [Sensors](sensors.md) - How to use sensor data
|
||||
- [Automation Examples](automation-examples.md) - Practical use cases
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Configuration
|
||||
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](../../README.md) for configuration instructions.
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/README.md) for configuration instructions.
|
||||
|
||||
## Initial Setup
|
||||
|
||||
186
docs/user/docs/dashboard-examples.md
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
# Dashboard Examples
|
||||
|
||||
Beautiful dashboard layouts using Tibber Prices sensors.
|
||||
|
||||
## Basic Price Display Card
|
||||
|
||||
Simple card showing current price with dynamic color:
|
||||
|
||||
```yaml
|
||||
type: entities
|
||||
title: Current Electricity Price
|
||||
entities:
|
||||
- entity: sensor.tibber_home_current_interval_price
|
||||
name: Current Price
|
||||
icon: mdi:flash
|
||||
- entity: sensor.tibber_home_current_interval_rating
|
||||
name: Price Rating
|
||||
- entity: sensor.tibber_home_next_interval_price
|
||||
name: Next Price
|
||||
```
|
||||
|
||||
## Period Status Cards
|
||||
|
||||
Show when best/peak price periods are active:
|
||||
|
||||
```yaml
|
||||
type: horizontal-stack
|
||||
cards:
|
||||
- type: entity
|
||||
entity: binary_sensor.tibber_home_best_price_period
|
||||
name: Best Price Active
|
||||
icon: mdi:currency-eur-off
|
||||
- type: entity
|
||||
entity: binary_sensor.tibber_home_peak_price_period
|
||||
name: Peak Price Active
|
||||
icon: mdi:alert
|
||||
```
|
||||
|
||||
## Custom Button Card Examples
|
||||
|
||||
### Price Level Card
|
||||
|
||||
```yaml
|
||||
type: custom:button-card
|
||||
entity: sensor.tibber_home_current_interval_level
|
||||
name: Price Level
|
||||
show_state: true
|
||||
styles:
|
||||
card:
|
||||
- background: |
|
||||
[[[
|
||||
if (entity.state === 'LOWEST') return 'linear-gradient(135deg, #00ffa3 0%, #00d4ff 100%)';
|
||||
if (entity.state === 'LOW') return 'linear-gradient(135deg, #4dddff 0%, #00ffa3 100%)';
|
||||
if (entity.state === 'NORMAL') return 'linear-gradient(135deg, #ffd700 0%, #ffb800 100%)';
|
||||
if (entity.state === 'HIGH') return 'linear-gradient(135deg, #ff8c00 0%, #ff6b00 100%)';
|
||||
if (entity.state === 'HIGHEST') return 'linear-gradient(135deg, #ff4500 0%, #dc143c 100%)';
|
||||
return 'var(--card-background-color)';
|
||||
]]]
|
||||
```
|
||||
|
||||
## Lovelace Layouts
|
||||
|
||||
### Compact Mobile View
|
||||
|
||||
Optimized for mobile devices:
|
||||
|
||||
```yaml
|
||||
type: vertical-stack
|
||||
cards:
|
||||
- type: custom:mini-graph-card
|
||||
entities:
|
||||
- entity: sensor.tibber_home_current_interval_price
|
||||
name: Today's Prices
|
||||
hours_to_show: 24
|
||||
points_per_hour: 4
|
||||
|
||||
- type: glance
|
||||
entities:
|
||||
- entity: sensor.tibber_home_best_price_start_time
|
||||
name: Best Period Starts
|
||||
- entity: binary_sensor.tibber_home_best_price_period
|
||||
name: Active Now
|
||||
```
|
||||
|
||||
### Desktop Dashboard
|
||||
|
||||
Full-width layout for desktop:
|
||||
|
||||
```yaml
|
||||
type: grid
|
||||
columns: 3
|
||||
square: false
|
||||
cards:
|
||||
- type: custom:apexcharts-card
|
||||
# See chart-examples.md for ApexCharts config
|
||||
|
||||
- type: vertical-stack
|
||||
cards:
|
||||
- type: entities
|
||||
title: Current Status
|
||||
entities:
|
||||
- sensor.tibber_home_current_interval_price
|
||||
- sensor.tibber_home_current_interval_rating
|
||||
|
||||
- type: vertical-stack
|
||||
cards:
|
||||
- type: entities
|
||||
title: Statistics
|
||||
entities:
|
||||
- sensor.tibber_home_daily_avg_today
|
||||
- sensor.tibber_home_daily_min_today
|
||||
- sensor.tibber_home_daily_max_today
|
||||
```
|
||||
|
||||
## Icon Color Integration
|
||||
|
||||
Using the `icon_color` attribute for dynamic colors:
|
||||
|
||||
```yaml
|
||||
type: custom:mushroom-chips-card
|
||||
chips:
|
||||
- type: entity
|
||||
entity: sensor.tibber_home_current_interval_price
|
||||
icon_color: "{{ state_attr('sensor.tibber_home_current_interval_price', 'icon_color') }}"
|
||||
|
||||
- type: entity
|
||||
entity: binary_sensor.tibber_home_best_price_period
|
||||
icon_color: green
|
||||
|
||||
- type: entity
|
||||
entity: binary_sensor.tibber_home_peak_price_period
|
||||
icon_color: red
|
||||
```
|
||||
|
||||
See [Icon Colors](icon-colors.md) for detailed color mapping.
|
||||
|
||||
## Picture Elements Dashboard
|
||||
|
||||
Advanced interactive dashboard:
|
||||
|
||||
```yaml
|
||||
type: picture-elements
|
||||
image: /local/electricity_dashboard_bg.png
|
||||
elements:
|
||||
- type: state-label
|
||||
entity: sensor.tibber_home_current_interval_price
|
||||
style:
|
||||
top: 20%
|
||||
left: 50%
|
||||
font-size: 32px
|
||||
font-weight: bold
|
||||
|
||||
- type: state-badge
|
||||
entity: binary_sensor.tibber_home_best_price_period
|
||||
style:
|
||||
top: 40%
|
||||
left: 30%
|
||||
|
||||
# Add more elements...
|
||||
```
|
||||
|
||||
## Auto-Entities Dynamic Lists
|
||||
|
||||
Automatically list all price sensors:
|
||||
|
||||
```yaml
|
||||
type: custom:auto-entities
|
||||
card:
|
||||
type: entities
|
||||
title: All Price Sensors
|
||||
filter:
|
||||
include:
|
||||
- entity_id: "sensor.tibber_*_price"
|
||||
exclude:
|
||||
- state: unavailable
|
||||
sort:
|
||||
method: state
|
||||
numeric: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
💡 **Related:**
|
||||
- [Chart Examples](chart-examples.md) - ApexCharts configurations
|
||||
- [Dynamic Icons](dynamic-icons.md) - Icon behavior
|
||||
- [Icon Colors](icon-colors.md) - Color attributes
|
||||
151
docs/user/docs/faq.md
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
# FAQ - Frequently Asked Questions
|
||||
|
||||
Common questions about the Tibber Prices integration.
|
||||
|
||||
## General Questions
|
||||
|
||||
### Why don't I see tomorrow's prices yet?
|
||||
|
||||
Tomorrow's prices are published by Tibber around **13:00 CET** (12:00 UTC in winter, 11:00 UTC in summer).
|
||||
|
||||
- **Before publication**: Sensors show `unavailable` or use today's data
|
||||
- **After publication**: Integration automatically fetches new data within 15 minutes
|
||||
- **No manual refresh needed** - polling happens automatically
|
||||
|
||||
### How often does the integration update data?
|
||||
|
||||
- **API Polling**: Every 15 minutes
|
||||
- **Sensor Updates**: On quarter-hour boundaries (00, 15, 30, 45 minutes)
|
||||
- **Cache**: Price data cached until midnight (reduces API load)
|
||||
|
||||
### Can I use multiple Tibber homes?
|
||||
|
||||
Yes! Use the **"Add another home"** option:
|
||||
|
||||
1. Settings → Devices & Services → Tibber Prices
|
||||
2. Click "Configure" → "Add another home"
|
||||
3. Select additional home from dropdown
|
||||
4. Each home gets separate sensors with unique entity IDs
|
||||
|
||||
### Does this work without a Tibber subscription?
|
||||
|
||||
No, you need:
|
||||
- Active Tibber electricity contract
|
||||
- API token from [developer.tibber.com](https://developer.tibber.com/)
|
||||
|
||||
The integration is free, but requires Tibber as your electricity provider.
|
||||
|
||||
## Configuration Questions
|
||||
|
||||
### What are good values for price thresholds?
|
||||
|
||||
**Default values work for most users:**
|
||||
- High Price Threshold: 30% above average
|
||||
- Low Price Threshold: 15% below average
|
||||
|
||||
**Adjust if:**
|
||||
- You're in a market with high volatility → increase thresholds
|
||||
- You want more sensitive ratings → decrease thresholds
|
||||
- Seasonal changes → review every few months
|
||||
|
||||
### How do I optimize Best Price Period detection?
|
||||
|
||||
**Key parameters:**
|
||||
- **Flex**: 15-20% is optimal (default 15%)
|
||||
- **Min Distance**: 5-10% recommended (default 5%)
|
||||
- **Rating Levels**: Start with "CHEAP + VERY_CHEAP" (default)
|
||||
- **Relaxation**: Keep enabled (helps find periods on expensive days)
|
||||
|
||||
See [Period Calculation](period-calculation.md) for detailed tuning guide.
|
||||
|
||||
### Why do I sometimes only get 1 period instead of 2?
|
||||
|
||||
This happens on **high-price days** when:
|
||||
- Few intervals meet your criteria
|
||||
- Relaxation is disabled
|
||||
- Flex is too low
|
||||
- Min Distance is too strict
|
||||
|
||||
**Solutions:**
|
||||
1. Enable relaxation (recommended)
|
||||
2. Increase flex to 20-25%
|
||||
3. Reduce min_distance to 3-5%
|
||||
4. Add more rating levels (include "NORMAL")
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Sensors show "unavailable"
|
||||
|
||||
**Common causes:**
|
||||
1. **API Token invalid** → Check token at developer.tibber.com
|
||||
2. **No internet connection** → Check HA network
|
||||
3. **Tibber API down** → Check [status.tibber.com](https://status.tibber.com)
|
||||
4. **Integration not loaded** → Restart Home Assistant
|
||||
|
||||
### Best Price Period is ON all day
|
||||
|
||||
This means **all intervals meet your criteria** (very cheap day!):
|
||||
- Not an error - enjoy the low prices!
|
||||
- Consider tightening filters (lower flex, higher min_distance)
|
||||
- Or add automation to only run during first detected period
|
||||
|
||||
### Prices are in wrong currency
|
||||
|
||||
Integration uses currency from your Tibber subscription:
|
||||
- EUR → displays in ct/kWh
|
||||
- NOK/SEK → displays in øre/kWh
|
||||
|
||||
Cannot be changed (tied to your electricity contract).
|
||||
|
||||
### Tomorrow data not appearing at all
|
||||
|
||||
**Check:**
|
||||
1. Your Tibber home has hourly price contract (not fixed price)
|
||||
2. API token has correct permissions
|
||||
3. Integration logs for API errors (`/config/home-assistant.log`)
|
||||
4. Tibber actually published data (check Tibber app)
|
||||
|
||||
## Automation Questions
|
||||
|
||||
### How do I run dishwasher during cheap period?
|
||||
|
||||
```yaml
|
||||
automation:
|
||||
- alias: "Dishwasher during Best Price"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: binary_sensor.tibber_home_best_price_period
|
||||
to: "on"
|
||||
condition:
|
||||
- condition: time
|
||||
after: "20:00:00" # Only start after 8 PM
|
||||
action:
|
||||
- service: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.dishwasher
|
||||
```
|
||||
|
||||
See [Automation Examples](automation-examples.md) for more recipes.
|
||||
|
||||
### Can I avoid peak prices automatically?
|
||||
|
||||
Yes! Use Peak Price Period binary sensor:
|
||||
|
||||
```yaml
|
||||
automation:
|
||||
- alias: "Disable charging during peak prices"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: binary_sensor.tibber_home_peak_price_period
|
||||
to: "on"
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.ev_charger
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
💡 **Still need help?**
|
||||
- [Troubleshooting Guide](troubleshooting.md)
|
||||
- [GitHub Issues](https://github.com/jpawlowski/hass.tibber_prices/issues)
|
||||
105
docs/user/docs/glossary.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Glossary
|
||||
|
||||
Quick reference for terms used throughout the documentation.
|
||||
|
||||
## A
|
||||
|
||||
**API Token**
|
||||
: Your personal access key from Tibber. Get it at [developer.tibber.com](https://developer.tibber.com/settings/access-token).
|
||||
|
||||
**Attributes**
|
||||
: Additional data attached to each sensor (timestamps, statistics, metadata). Access via `state_attr()` in templates.
|
||||
|
||||
## B
|
||||
|
||||
**Best Price Period**
|
||||
: Automatically detected time window with favorable electricity prices. Ideal for scheduling dishwashers, heat pumps, EV charging.
|
||||
|
||||
**Binary Sensor**
|
||||
: Sensor with ON/OFF state (e.g., "Best Price Period Active"). Used in automations as triggers.
|
||||
|
||||
## C
|
||||
|
||||
**Currency Units**
|
||||
: Minor currency units used for display (ct for EUR, øre for NOK/SEK). Integration handles conversion automatically.
|
||||
|
||||
**Coordinator**
|
||||
: Home Assistant component managing data fetching and updates. Polls Tibber API every 15 minutes.
|
||||
|
||||
## D
|
||||
|
||||
**Dynamic Icons**
|
||||
: Icons that change based on sensor state (e.g., battery icons showing price level). See [Dynamic Icons](dynamic-icons.md).
|
||||
|
||||
## F
|
||||
|
||||
**Flex (Flexibility)**
|
||||
: Configuration parameter controlling how strict period detection is. Higher flex = more periods found, but potentially at higher prices.
|
||||
|
||||
## I
|
||||
|
||||
**Interval**
|
||||
: 15-minute time slot with fixed electricity price (00:00-00:15, 00:15-00:30, etc.).
|
||||
|
||||
## L
|
||||
|
||||
**Level**
|
||||
: Price classification within a day (LOWEST, LOW, NORMAL, HIGH, HIGHEST). Based on daily min/max prices.
|
||||
|
||||
## M
|
||||
|
||||
**Min Distance**
|
||||
: Threshold requiring periods to be at least X% below daily average. Prevents detecting "cheap" periods during expensive days.
|
||||
|
||||
## P
|
||||
|
||||
**Peak Price Period**
|
||||
: Time window with highest electricity prices. Use to avoid heavy consumption.
|
||||
|
||||
**Price Info**
|
||||
: Complete dataset with all intervals (yesterday, today, tomorrow) including enriched statistics.
|
||||
|
||||
## Q
|
||||
|
||||
**Quarter-Hourly**
|
||||
: 15-minute precision (4 intervals per hour, 96 per day).
|
||||
|
||||
## R
|
||||
|
||||
**Rating**
|
||||
: Statistical price classification (VERY_CHEAP, CHEAP, NORMAL, EXPENSIVE, VERY_EXPENSIVE). Based on 24h averages and thresholds.
|
||||
|
||||
**Relaxation**
|
||||
: Automatic loosening of period detection filters when target period count isn't met. Ensures you always get usable periods.
|
||||
|
||||
## S
|
||||
|
||||
**State**
|
||||
: Current value of a sensor (e.g., price in ct/kWh, "ON"/"OFF" for binary sensors).
|
||||
|
||||
**State Class**
|
||||
: Home Assistant classification for long-term statistics (MEASUREMENT, TOTAL, or none).
|
||||
|
||||
## T
|
||||
|
||||
**Trailing Average**
|
||||
: Average price over the past 24 hours from current interval.
|
||||
|
||||
**Leading Average**
|
||||
: Average price over the next 24 hours from current interval.
|
||||
|
||||
## V
|
||||
|
||||
**Volatility**
|
||||
: Measure of price stability (LOW, MEDIUM, HIGH). High volatility = large price swings = good for timing optimization.
|
||||
|
||||
---
|
||||
|
||||
💡 **See Also:**
|
||||
- [Core Concepts](concepts.md) - In-depth explanations
|
||||
- [Sensors](sensors.md) - How sensors use these concepts
|
||||
- [Period Calculation](period-calculation.md) - Deep dive into period detection
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Dynamic Icon Colors
|
||||
|
||||
Many sensors in the Tibber Prices integration provide an `icon_color` attribute that allows you to dynamically color elements in your dashboard based on the sensor's state. This is particularly useful for visual dashboards where you want instant recognition of price levels or states.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Installation
|
||||
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](../../README.md) for installation instructions.
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/README.md) for installation instructions.
|
||||
|
||||
## HACS Installation (Recommended)
|
||||
|
||||
59
docs/user/docs/intro.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# User Documentation
|
||||
|
||||
Welcome to the **Tibber Prices custom integration for Home Assistant**! This community-developed integration enhances your Home Assistant installation with detailed electricity price data from Tibber, featuring quarter-hourly precision, statistical analysis, and intelligent ratings.
|
||||
|
||||
:::info Not affiliated with Tibber
|
||||
This is an independent, community-maintained custom integration. It is **not** an official Tibber product and is **not** affiliated with or endorsed by Tibber AS.
|
||||
:::
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- **[Installation](installation.md)** - How to install via HACS and configure the integration
|
||||
- **[Configuration](configuration.md)** - Setting up your Tibber API token and price thresholds
|
||||
- **[Period Calculation](period-calculation.md)** - How Best/Peak Price periods are calculated and configured
|
||||
- **[Sensors](sensors.md)** - Available sensors, their states, and attributes
|
||||
- **[Dynamic Icons](dynamic-icons.md)** - State-based automatic icon changes
|
||||
- **[Dynamic Icon Colors](icon-colors.md)** - Using icon_color attribute for color-coded dashboards
|
||||
- **[Actions](actions.md)** - Custom actions (service endpoints) and how to use them
|
||||
- **[Chart Examples](chart-examples.md)** - ✨ ApexCharts visualizations with screenshots
|
||||
- **[Automation Examples](automation-examples.md)** - Ready-to-use automation recipes
|
||||
- **[Troubleshooting](troubleshooting.md)** - Common issues and solutions
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
1. **Install via HACS** (add as custom repository)
|
||||
2. **Add Integration** in Home Assistant → Settings → Devices & Services
|
||||
3. **Enter Tibber API Token** (get yours at [developer.tibber.com](https://developer.tibber.com/))
|
||||
4. **Configure Price Thresholds** (optional, defaults work for most users)
|
||||
5. **Start Using Sensors** in automations, dashboards, and scripts!
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
- **Quarter-hourly precision** - 15-minute intervals for accurate price tracking
|
||||
- **Statistical analysis** - Trailing/leading 24h averages for context
|
||||
- **Price ratings** - LOW/NORMAL/HIGH classification based on your thresholds
|
||||
- **Best/Peak hour detection** - Automatic detection of cheapest/peak periods with configurable filters ([learn how](period-calculation.md))
|
||||
- **Beautiful ApexCharts** - Auto-generated chart configurations with dynamic Y-axis scaling ([see examples](chart-examples.md))
|
||||
- **Chart metadata sensor** - Dynamic chart configuration for optimal visualization
|
||||
- **Multi-currency support** - EUR, NOK, SEK with proper minor units (ct, øre, öre)
|
||||
|
||||
## 🔗 Useful Links
|
||||
|
||||
- [GitHub Repository](https://github.com/jpawlowski/hass.tibber_prices)
|
||||
- [Issue Tracker](https://github.com/jpawlowski/hass.tibber_prices/issues)
|
||||
- [Release Notes](https://github.com/jpawlowski/hass.tibber_prices/releases)
|
||||
- [Home Assistant Community](https://community.home-assistant.io/)
|
||||
|
||||
## 🤝 Need Help?
|
||||
|
||||
- Check the [Troubleshooting Guide](troubleshooting.md)
|
||||
- Search [existing issues](https://github.com/jpawlowski/hass.tibber_prices/issues)
|
||||
- Open a [new issue](https://github.com/jpawlowski/hass.tibber_prices/issues/new) if needed
|
||||
|
||||
---
|
||||
|
||||
**Note:** These guides are for end users. If you want to contribute to development, see the [Developer Documentation](../development/).
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Sensors
|
||||
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](../../README.md) for available sensors.
|
||||
> **Note:** This guide is under construction. For now, please refer to the [main README](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/README.md) for available sensors.
|
||||
|
||||
> **Tip:** Many sensors have dynamic icons and colors! See the **[Dynamic Icons Guide](dynamic-icons.md)** and **[Dynamic Icon Colors Guide](icon-colors.md)** to enhance your dashboards.
|
||||
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
comments: false
|
||||
---
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
> **Note:** This guide is under construction.
|
||||
220
docs/user/docusaurus.config.ts
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
import type {Config} from '@docusaurus/types';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
|
||||
const config: Config = {
|
||||
title: 'Tibber Prices Integration',
|
||||
tagline: 'Custom Home Assistant integration for Tibber electricity prices',
|
||||
favicon: 'img/logo.svg',
|
||||
|
||||
future: {
|
||||
v4: true,
|
||||
},
|
||||
|
||||
url: 'https://jpawlowski.github.io',
|
||||
baseUrl: '/hass.tibber_prices/user/',
|
||||
|
||||
organizationName: 'jpawlowski',
|
||||
projectName: 'hass.tibber_prices',
|
||||
deploymentBranch: 'gh-pages',
|
||||
trailingSlash: false,
|
||||
|
||||
onBrokenLinks: 'warn',
|
||||
|
||||
markdown: {
|
||||
mermaid: true,
|
||||
hooks: {
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
themes: ['@docusaurus/theme-mermaid'],
|
||||
|
||||
plugins: [
|
||||
'docusaurus-lunr-search',
|
||||
],
|
||||
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
headTags: [
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'preconnect',
|
||||
href: 'https://fonts.googleapis.com',
|
||||
},
|
||||
},
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'preconnect',
|
||||
href: 'https://fonts.gstatic.com',
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
},
|
||||
{
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'stylesheet',
|
||||
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
{
|
||||
docs: {
|
||||
routeBasePath: '/',
|
||||
sidebarPath: './sidebars.ts',
|
||||
editUrl: ({versionDocsDirPath, docPath}) => {
|
||||
if (versionDocsDirPath.includes('_versioned_')) {
|
||||
const version = versionDocsDirPath.match(/version-([^/]+)/)?.[1] || 'main';
|
||||
return `https://github.com/jpawlowski/hass.tibber_prices/tree/${version}/docs/user/docs/${docPath}`;
|
||||
}
|
||||
return `https://github.com/jpawlowski/hass.tibber_prices/tree/main/docs/user/docs/${docPath}`;
|
||||
},
|
||||
showLastUpdateTime: true,
|
||||
versions: {
|
||||
current: {
|
||||
label: 'Next 🚧',
|
||||
banner: 'unreleased',
|
||||
badge: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
mermaid: {
|
||||
theme: {light: 'base', dark: 'dark'},
|
||||
options: {
|
||||
themeVariables: {
|
||||
// Light mode colors
|
||||
primaryColor: '#e6f7ff',
|
||||
primaryTextColor: '#1a1a1a',
|
||||
primaryBorderColor: '#00b9e7',
|
||||
lineColor: '#00b9e7',
|
||||
secondaryColor: '#e6fff5',
|
||||
secondaryTextColor: '#1a1a1a',
|
||||
secondaryBorderColor: '#00ffa3',
|
||||
tertiaryColor: '#fff9e6',
|
||||
tertiaryTextColor: '#1a1a1a',
|
||||
tertiaryBorderColor: '#ffb800',
|
||||
noteBkgColor: '#e6f7ff',
|
||||
noteTextColor: '#1a1a1a',
|
||||
noteBorderColor: '#00b9e7',
|
||||
// Node styling
|
||||
mainBkg: '#ffffff',
|
||||
nodeBorder: '#00b9e7',
|
||||
clusterBkg: '#f0f9ff',
|
||||
clusterBorder: '#00b9e7',
|
||||
// Font styling
|
||||
fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
|
||||
fontSize: '14px',
|
||||
},
|
||||
},
|
||||
},
|
||||
image: 'img/social-card.png',
|
||||
colorMode: {
|
||||
respectPrefersColorScheme: true,
|
||||
},
|
||||
docs: {
|
||||
sidebar: {
|
||||
hideable: true,
|
||||
autoCollapseCategories: true,
|
||||
},
|
||||
},
|
||||
navbar: {
|
||||
title: 'Tibber Prices HA',
|
||||
logo: {
|
||||
alt: 'Tibber Prices Integration Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: '/intro',
|
||||
label: 'User Guide',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
href: 'https://jpawlowski.github.io/hass.tibber_prices/developer/',
|
||||
label: 'Developer Docs',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'docsVersionDropdown',
|
||||
position: 'right',
|
||||
dropdownActiveClassDisabled: true,
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Documentation',
|
||||
items: [
|
||||
{
|
||||
label: 'User Guide',
|
||||
to: '/intro',
|
||||
},
|
||||
{
|
||||
label: 'Developer Guide',
|
||||
href: 'https://jpawlowski.github.io/hass.tibber_prices/developer/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub Issues',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices/issues',
|
||||
},
|
||||
{
|
||||
label: 'Home Assistant Community',
|
||||
href: 'https://community.home-assistant.io/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices',
|
||||
},
|
||||
{
|
||||
label: 'Release Notes',
|
||||
href: 'https://github.com/jpawlowski/hass.tibber_prices/releases',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Not affiliated with Tibber AS. Community-maintained custom integration. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
additionalLanguages: ['bash', 'yaml', 'json'],
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
||||
export default config;
|
||||
20443
docs/user/package-lock.json
generated
Normal file
50
docs/user/package.json
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "docs-split-user",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@docusaurus/theme-mermaid": "^3.9.2",
|
||||
"@giscus/react": "^3.1.0",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-lunr-search": "^3.6.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.9.2",
|
||||
"@docusaurus/tsconfig": "3.9.2",
|
||||
"@docusaurus/types": "3.9.2",
|
||||
"typescript": "~5.6.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 3 chrome version",
|
||||
"last 3 firefox version",
|
||||
"last 5 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0"
|
||||
}
|
||||
}
|
||||
63
docs/user/sidebars.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
|
||||
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
const sidebars: SidebarsConfig = {
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
{
|
||||
type: 'category',
|
||||
label: '🚀 Getting Started',
|
||||
items: ['installation', 'configuration'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '📖 Core Concepts',
|
||||
items: ['concepts', 'glossary'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '📊 Features',
|
||||
items: ['sensors', 'period-calculation', 'dynamic-icons', 'icon-colors', 'actions'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '🎨 Visualization',
|
||||
items: ['dashboard-examples', 'chart-examples'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '🤖 Automation',
|
||||
items: ['automation-examples'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '🔧 Help & Support',
|
||||
items: ['faq', 'troubleshooting'],
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default sidebars;
|
||||
24
docs/user/src/components/GiscusComponent.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import Giscus from '@giscus/react';
|
||||
import { useColorMode } from '@docusaurus/theme-common';
|
||||
|
||||
export default function GiscusComponent() {
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Giscus
|
||||
repo="jpawlowski/hass.tibber_prices"
|
||||
repoId="R_kgDOObwUag"
|
||||
category="General"
|
||||
categoryId="DIC_kwDOObwUas4CzVw_"
|
||||
mapping="pathname"
|
||||
strict="0"
|
||||
reactionsEnabled="1"
|
||||
emitMetadata="0"
|
||||
inputPosition="top"
|
||||
theme={colorMode === 'dark' ? 'dark' : 'light'}
|
||||
lang="en"
|
||||
loading="lazy"
|
||||
/>
|
||||
);
|
||||
}
|
||||
71
docs/user/src/components/HomepageFeatures/index.tsx
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import type {ReactNode} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Heading from '@theme/Heading';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
type FeatureItem = {
|
||||
title: string;
|
||||
Svg: React.ComponentType<React.ComponentProps<'svg'>>;
|
||||
description: ReactNode;
|
||||
};
|
||||
|
||||
const FeatureList: FeatureItem[] = [
|
||||
{
|
||||
title: 'Easy to Use',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Docusaurus was designed from the ground up to be easily installed and
|
||||
used to get your website up and running quickly.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Focus on What Matters',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Docusaurus lets you focus on your docs, and we'll do the chores. Go
|
||||
ahead and move your docs into the <code>docs</code> directory.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Powered by React',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Extend or customize your website layout by reusing React. Docusaurus can
|
||||
be extended while reusing the same header and footer.
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
function Feature({title, Svg, description}: FeatureItem) {
|
||||
return (
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center">
|
||||
<Svg className={styles.featureSvg} role="img" />
|
||||
</div>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<Heading as="h3">{title}</Heading>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HomepageFeatures(): ReactNode {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
11
docs/user/src/components/HomepageFeatures/styles.module.css
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
214
docs/user/src/css/custom.css
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* Modern font stack */
|
||||
:root {
|
||||
--ifm-font-family-base: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
--ifm-heading-font-family: 'Space Grotesk', var(--ifm-font-family-base);
|
||||
--ifm-font-family-monospace: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
/* Tibber-inspired electric color scheme */
|
||||
:root {
|
||||
/* Primary: Electric blue */
|
||||
--ifm-color-primary: #00b9e7;
|
||||
--ifm-color-primary-dark: #00a7d0;
|
||||
--ifm-color-primary-darker: #009ec4;
|
||||
--ifm-color-primary-darkest: #0082a2;
|
||||
--ifm-color-primary-light: #00cbfe;
|
||||
--ifm-color-primary-lighter: #19d1ff;
|
||||
--ifm-color-primary-lightest: #4dddff;
|
||||
|
||||
/* Accent: Energy green */
|
||||
--ifm-color-success: #00ffa3;
|
||||
|
||||
/* Warning: Price orange */
|
||||
--ifm-color-warning: #ffb800;
|
||||
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 185, 231, 0.1);
|
||||
|
||||
/* Modern border radius */
|
||||
--ifm-global-radius: 0.75rem;
|
||||
--ifm-button-border-radius: 0.75rem;
|
||||
--ifm-card-border-radius: 1rem;
|
||||
--ifm-code-border-radius: 0.5rem;
|
||||
|
||||
/* Subtle shadows for depth */
|
||||
--ifm-global-shadow-lw: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
--ifm-global-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
--ifm-global-shadow-tl: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
|
||||
/* Hero background gradient */
|
||||
--ifm-hero-background-color: linear-gradient(135deg, #00b9e7 0%, #00ffa3 100%);
|
||||
}
|
||||
|
||||
/* Dark mode with electric theme */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #00d4ff;
|
||||
--ifm-color-primary-dark: #00c0e6;
|
||||
--ifm-color-primary-darker: #00b5d9;
|
||||
--ifm-color-primary-darkest: #0095b3;
|
||||
--ifm-color-primary-light: #19ddff;
|
||||
--ifm-color-primary-lighter: #33e1ff;
|
||||
--ifm-color-primary-lightest: #66e9ff;
|
||||
|
||||
/* Accent: Brighter green in dark mode */
|
||||
--ifm-color-success: #00ffb3;
|
||||
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 212, 255, 0.15);
|
||||
|
||||
/* Darker background for better contrast */
|
||||
--ifm-background-color: #1a1a1a;
|
||||
--ifm-background-surface-color: #242424;
|
||||
|
||||
/* Darker shadows for dark mode */
|
||||
--ifm-global-shadow-lw: 0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2);
|
||||
--ifm-global-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
||||
--ifm-global-shadow-tl: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Hero section styling */
|
||||
.hero--primary {
|
||||
background: linear-gradient(135deg, #00b9e7 0%, #0099cc 50%, #ffb800 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero--primary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(0, 185, 231, 0.95) 0%, rgba(0, 153, 204, 0.95) 50%, rgba(255, 184, 0, 0.85) 100%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.hero--primary .container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .hero--primary {
|
||||
background: linear-gradient(135deg, #00506b 0%, #003d52 50%, #665000 100%);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .hero--primary::before {
|
||||
background: linear-gradient(135deg, rgba(0, 80, 107, 0.95) 0%, rgba(0, 61, 82, 0.95) 50%, rgba(102, 80, 0, 0.85) 100%);
|
||||
}
|
||||
|
||||
/* Unreleased version banner styling */
|
||||
[data-theme='light'] .theme-doc-version-banner {
|
||||
background-color: #fff4e6;
|
||||
border-color: #ffb800;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .theme-doc-version-banner {
|
||||
background-color: #2d2000;
|
||||
border-color: #ffb800;
|
||||
}
|
||||
|
||||
/* Make code blocks stand out */
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 185, 231, 0.2);
|
||||
display: block;
|
||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 212, 255, 0.2);
|
||||
}
|
||||
|
||||
/* Sidebar customization */
|
||||
.theme-doc-sidebar-container {
|
||||
border-right: 1px solid var(--ifm-toc-border-color);
|
||||
}
|
||||
|
||||
/* Table of contents highlighting */
|
||||
.table-of-contents__link--active {
|
||||
color: var(--ifm-color-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Admonition styling */
|
||||
.admonition {
|
||||
border-left-width: 4px;
|
||||
}
|
||||
|
||||
.admonition-note {
|
||||
border-left-color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.admonition-tip {
|
||||
border-left-color: var(--ifm-color-success);
|
||||
}
|
||||
|
||||
.admonition-warning {
|
||||
border-left-color: var(--ifm-color-warning);
|
||||
}
|
||||
|
||||
/* Features section on homepage */
|
||||
.features {
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.features h3 {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .features h3 {
|
||||
color: var(--ifm-color-primary-lighter);
|
||||
}
|
||||
|
||||
/* Card styling with modern shadows */
|
||||
.card {
|
||||
border-radius: var(--ifm-card-border-radius);
|
||||
box-shadow: var(--ifm-global-shadow-md);
|
||||
transition: box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: var(--ifm-global-shadow-tl);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Navbar with subtle shadow */
|
||||
.navbar {
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
}
|
||||
|
||||
/* Code blocks with modern styling */
|
||||
code {
|
||||
border-radius: var(--ifm-code-border-radius);
|
||||
}
|
||||
|
||||
/* Buttons with modern feel */
|
||||
.button {
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.025em;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--ifm-global-shadow-md);
|
||||
}
|
||||
|
||||
/* Headings with Space Grotesk */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--ifm-heading-font-family);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
/* Smooth transitions everywhere */
|
||||
* {
|
||||
transition-property: background-color, border-color, color, fill, stroke;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
23
docs/user/src/pages/index.module.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 996px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
117
docs/user/src/pages/index.tsx
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import type {ReactNode} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import {useColorMode} from '@docusaurus/theme-common';
|
||||
import Layout from '@theme/Layout';
|
||||
import Heading from '@theme/Heading';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
function HomepageHeader() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {colorMode} = useColorMode();
|
||||
const headerUrl = useBaseUrl(colorMode === 'dark' ? '/img/header-dark.svg' : '/img/header.svg');
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<div style={{ marginBottom: '2rem' }}>
|
||||
<img src={headerUrl} alt="Tibber Prices for Tibber" style={{ maxWidth: '600px', width: '100%', height: 'auto' }} />
|
||||
</div>
|
||||
<Heading as="h1" className="hero__title">
|
||||
{siteConfig.title}
|
||||
</Heading>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/intro">
|
||||
Get Started →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
function HomepageFeatures() {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>⚡ Quarter-Hourly Precision</h3>
|
||||
<p>
|
||||
Track electricity prices with 15-minute intervals. Get accurate price data
|
||||
synchronized with your Tibber smart meter for optimal energy planning.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>📊 Smart Price Analysis</h3>
|
||||
<p>
|
||||
Automatic detection of best and peak price periods with configurable filters.
|
||||
Statistical analysis with trailing/leading 24h averages for context.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🎨 Beautiful Visualizations</h3>
|
||||
<p>
|
||||
Auto-generated ApexCharts configurations with dynamic Y-axis scaling.
|
||||
Dynamic icons and color-coded sensors for stunning dashboards.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row margin-top--lg">
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🤖 Automation Ready</h3>
|
||||
<p>
|
||||
Control energy-intensive appliances based on price levels. Run dishwashers,
|
||||
heat pumps, and EV chargers during cheap periods automatically.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>💰 Multi-Currency Support</h3>
|
||||
<p>
|
||||
Full support for EUR (ct), NOK (øre), SEK (öre) with proper minor units.
|
||||
Display prices the way you're used to seeing them.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>🔧 HACS Integration</h3>
|
||||
<p>
|
||||
Easy installation via Home Assistant Community Store. Regular updates and
|
||||
active development with comprehensive documentation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): ReactNode {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title="Home"
|
||||
description="Custom Home Assistant integration for Tibber electricity price management">
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
7
docs/user/src/pages/markdown-page.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Markdown page example
|
||||
---
|
||||
|
||||
# Markdown page example
|
||||
|
||||
You don't need React to write simple standalone pages.
|
||||
22
docs/user/src/theme/DocItem/Footer/index.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
import DocItemFooter from '@theme-original/DocItem/Footer';
|
||||
import GiscusComponent from '@site/src/components/GiscusComponent';
|
||||
import { useDoc } from '@docusaurus/plugin-content-docs/client';
|
||||
|
||||
export default function DocItemFooterWrapper(props) {
|
||||
const { frontMatter } = useDoc();
|
||||
|
||||
// Allow disabling comments per page via frontmatter
|
||||
const enableComments = frontMatter.comments !== false;
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocItemFooter {...props} />
|
||||
{enableComments && (
|
||||
<div style={{ marginTop: '3rem' }}>
|
||||
<GiscusComponent />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
0
docs/user/static/.nojekyll
Normal file
BIN
docs/user/static/img/charts/rolling-window-autozoom.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/user/static/img/charts/rolling-window.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
docs/user/static/img/charts/today.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
docs/user/static/img/docusaurus-social-card.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/user/static/img/docusaurus.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
BIN
docs/user/static/img/entities-overview.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
74
docs/user/static/img/header-dark.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name (light text for dark mode) -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#E8E8E8">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#B0B0B0">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider (lighter) -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#666666"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text (lighter) -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#888888">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text (light text for dark mode) -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#E8E8E8">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
74
docs/user/static/img/header.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#333333">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#666666">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#CCCCCC"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#999999">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#333333">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
BIN
docs/user/static/img/logo.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
29
docs/user/static/img/logo.svg
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Tibber Prices Logo: Lightning bolt + Price tag + T -->
|
||||
<defs>
|
||||
<linearGradient id="boltGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Stylized lightning bolt (Tibber inspired) -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGradient)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGradient)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Currency symbol inside price tag -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
171
docs/user/static/img/undraw_docusaurus_mountain.svg
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
|
||||
<title>Easy to Use</title>
|
||||
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
|
||||
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
|
||||
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
|
||||
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
|
||||
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
|
||||
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
|
||||
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
|
||||
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
|
||||
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
|
||||
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
|
||||
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
|
||||
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
|
||||
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
|
||||
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
|
||||
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 31 KiB |
170
docs/user/static/img/undraw_docusaurus_react.svg
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
|
||||
<title>Powered by React</title>
|
||||
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
|
||||
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
|
||||
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
|
||||
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
|
||||
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
|
||||
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
|
||||
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
|
||||
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
|
||||
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
|
||||
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
|
||||
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
|
||||
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
|
||||
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
|
||||
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
|
||||
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
|
||||
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
|
||||
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="React-icon" transform="translate(906.3 541.56)">
|
||||
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
|
||||
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
|
||||
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
|
||||
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 35 KiB |
40
docs/user/static/img/undraw_docusaurus_tree.svg
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
|
||||
<title>Focus on What Matters</title>
|
||||
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
|
||||
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
|
||||
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
|
||||
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
|
||||
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
|
||||
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
|
||||
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
|
||||
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
|
||||
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
|
||||
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
|
||||
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
8
docs/user/tsconfig.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@docusaurus/tsconfig",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": [".docusaurus", "build"]
|
||||
}
|
||||
74
images/header-dark.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name (light text for dark mode) -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#E8E8E8">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#B0B0B0">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider (lighter) -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#666666"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text (lighter) -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#888888">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text (light text for dark mode) -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#E8E8E8">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
74
images/header.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<svg viewBox="0 0 600 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="600" height="100" fill="transparent"/>
|
||||
|
||||
<!-- Custom Integration Logo (left side) -->
|
||||
<defs>
|
||||
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#00D4FF;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0099CC;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="priceGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g transform="translate(35, 50) scale(0.25)">
|
||||
<!-- Lightning bolt -->
|
||||
<path d="M 100 20 L 70 90 L 100 85 L 80 150 L 140 80 L 110 85 Z"
|
||||
fill="url(#boltGrad)"
|
||||
stroke="none"/>
|
||||
|
||||
<!-- Price tag circle -->
|
||||
<circle cx="145" cy="50" r="35" fill="url(#priceGrad)" stroke="white" stroke-width="4"/>
|
||||
|
||||
<!-- Euro symbol -->
|
||||
<text x="145" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="32"
|
||||
font-weight="bold"
|
||||
fill="white"
|
||||
text-anchor="middle">€</text>
|
||||
</g>
|
||||
|
||||
<!-- Integration Name -->
|
||||
<text x="90" y="45"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="24"
|
||||
font-weight="700"
|
||||
fill="#333333">Tibber Prices</text>
|
||||
|
||||
<text x="90" y="65"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="normal"
|
||||
fill="#666666">Custom Integration</text>
|
||||
|
||||
<!-- Vertical Divider -->
|
||||
<line x1="270" y1="25" x2="270" y2="75"
|
||||
stroke="#CCCCCC"
|
||||
stroke-width="2"/>
|
||||
|
||||
<!-- "for" text -->
|
||||
<text x="290" y="55"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="normal"
|
||||
fill="#999999">for</text>
|
||||
|
||||
<!-- Tibber Logo (right side - simplified) -->
|
||||
<g transform="translate(335, 50)">
|
||||
<!-- Lightning bolt symbol -->
|
||||
<path d="M 0 -30 L -15 5 L 0 0 L -8 25 L 18 -5 L 5 0 Z"
|
||||
fill="#00D4FF"
|
||||
stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- Tibber Text -->
|
||||
<text x="365" y="58"
|
||||
font-family="Arial, sans-serif"
|
||||
font-size="28"
|
||||
font-weight="bold"
|
||||
fill="#333333">Tibber</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
24
scripts/docs/build-all
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build both documentation sites
|
||||
|
||||
set -e
|
||||
|
||||
# Find repository root (where .git directory is)
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
cd "$REPO_ROOT" || exit 1
|
||||
|
||||
echo "🔨 Building User Documentation..."
|
||||
cd docs/user
|
||||
npm run build
|
||||
cd ../..
|
||||
|
||||
echo ""
|
||||
echo "🔨 Building Developer Documentation..."
|
||||
cd docs/developer
|
||||
npm run build
|
||||
cd ../..
|
||||
|
||||
echo ""
|
||||
echo "✅ Both documentation sites built successfully!"
|
||||
echo " - User docs: docs/user/build/"
|
||||
echo " - Developer docs: docs/developer/build/"
|
||||
14
scripts/docs/dev-developer
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
# Start Developer Documentation development server
|
||||
|
||||
set -e
|
||||
|
||||
# Find repository root (where .git directory is)
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
cd "$REPO_ROOT/docs/developer" || exit 1
|
||||
|
||||
echo "Starting Developer Documentation development server..."
|
||||
echo "Access at: http://localhost:3001/hass.tibber_prices/developer/"
|
||||
echo ""
|
||||
|
||||
npm start -- --port 3001 --host 0.0.0.0 --poll 1000
|
||||
14
scripts/docs/dev-user
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
# Start User Documentation development server
|
||||
|
||||
set -e
|
||||
|
||||
# Find repository root (where .git directory is)
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
cd "$REPO_ROOT/docs/user" || exit 1
|
||||
|
||||
echo "Starting User Documentation development server..."
|
||||
echo "Access at: http://localhost:3000/hass.tibber_prices/user/"
|
||||
echo ""
|
||||
|
||||
npm start -- --host 0.0.0.0 --poll 1000
|
||||