mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-22 03:49:18 +02:00
Security hardening (maziggy/bambuddy-security #17)
This commit is contained in:
@@ -12,8 +12,9 @@ import zlib
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, Query, Request
|
||||
from fastapi.responses import Response, StreamingResponse
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -1649,30 +1650,45 @@ async def camera_status(
|
||||
}
|
||||
|
||||
|
||||
class ExternalCameraTestRequest(BaseModel):
|
||||
url: str
|
||||
camera_type: str
|
||||
|
||||
|
||||
@router.post("/{printer_id}/camera/external/test")
|
||||
async def test_external_camera(
|
||||
printer_id: int,
|
||||
url: str,
|
||||
camera_type: str,
|
||||
body: ExternalCameraTestRequest | None = Body(default=None),
|
||||
url: str | None = None,
|
||||
camera_type: str | None = None,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User | None = RequirePrinterPermissionIfAuthEnabled(Permission.CAMERA_VIEW),
|
||||
):
|
||||
"""Test external camera connection.
|
||||
|
||||
The URL comes in the body: it may carry the camera login, and a query
|
||||
string ends up in the access log. The query form is still accepted from
|
||||
an older page.
|
||||
|
||||
Args:
|
||||
printer_id: Printer ID (for authorization)
|
||||
url: Camera URL or USB device path to test
|
||||
camera_type: Camera type ("mjpeg", "rtsp", "snapshot", "usb")
|
||||
body / url: Camera URL or USB device path to test
|
||||
body / camera_type: Camera type ("mjpeg", "rtsp", "snapshot", "usb")
|
||||
|
||||
Returns:
|
||||
Dict with {success: bool, error?: str, resolution?: str}
|
||||
"""
|
||||
target_url = body.url if body else url
|
||||
target_type = body.camera_type if body else camera_type
|
||||
if not target_url or not target_type:
|
||||
raise HTTPException(status_code=422, detail="url and camera_type are required")
|
||||
|
||||
# Verify printer exists (for authorization)
|
||||
await get_printer_or_404(printer_id, db)
|
||||
|
||||
from backend.app.services.external_camera import test_connection
|
||||
|
||||
return await test_connection(url, camera_type)
|
||||
return await test_connection(target_url, target_type)
|
||||
|
||||
|
||||
@router.get("/{printer_id}/camera/check-plate")
|
||||
|
||||
@@ -40,13 +40,27 @@ import re
|
||||
# makes the work per offset constant. 63 is far above any real scheme (the
|
||||
# longest registered one is under 20 characters), and a longer pseudo-scheme
|
||||
# still gets its secret masked — the match simply starts from a later offset.
|
||||
URL_CREDENTIALS_PATTERN = re.compile(
|
||||
r"(?P<scheme>[a-zA-Z][a-zA-Z0-9+.\-]{0,63}://)(?P<user>[^/:@\s]+):(?P<secret>[^/\s]+)@"
|
||||
)
|
||||
URL_CREDENTIALS_PATTERN = re.compile(r"(?P<scheme>[a-zA-Z][a-zA-Z0-9+.\-]{0,63}://)(?P<login>[^/\s]+)@")
|
||||
|
||||
|
||||
def _mask_login(match: re.Match[str]) -> str:
|
||||
# The login runs to the last @ before the path. It may hold an unencoded ?
|
||||
# or #, which cannot be told from a query: masked rather than risk it. Its
|
||||
# user part (up to the first ':') survives; without a ':' it may be a
|
||||
# token, so it all goes.
|
||||
login = match.group("login")
|
||||
shown = f"{login.split(':', 1)[0]}:[REDACTED]" if ":" in login else "[REDACTED]"
|
||||
return f"{match.group('scheme')}{shown}@"
|
||||
|
||||
|
||||
def redact_url_credentials(text: str | None) -> str | None:
|
||||
"""Mask the password in every ``scheme://user:secret@host`` URL in *text*.
|
||||
"""Mask the login secret in every ``scheme://login@host`` URL in *text*.
|
||||
|
||||
The login runs to the last ``@`` before the path (``?`` and ``#``
|
||||
included, when in doubt it is masked), so an empty user
|
||||
(``:secret@``), an unencoded ``@`` in the user and a bare token
|
||||
(``token@``, masked whole) are covered as well as ``user:secret@``.
|
||||
Also used for camera URLs shown to those who may not edit the printer.
|
||||
|
||||
Subprocesses echo their input URL back at us — ffmpeg prints the RTSP
|
||||
input in its ``Input #0`` line, so logging its stderr verbatim publishes
|
||||
@@ -59,7 +73,7 @@ def redact_url_credentials(text: str | None) -> str | None:
|
||||
"""
|
||||
if not text or "://" not in text or "@" not in text:
|
||||
return text
|
||||
return URL_CREDENTIALS_PATTERN.sub(r"\g<scheme>\g<user>:[REDACTED]@", text)
|
||||
return URL_CREDENTIALS_PATTERN.sub(_mask_login, text)
|
||||
|
||||
|
||||
# ``?token=<value>`` and its kin. The SPA passes its short-lived WebSocket and
|
||||
@@ -70,7 +84,7 @@ def redact_url_credentials(text: str | None) -> str | None:
|
||||
# and from there anything that collects container logs -- the appliance's
|
||||
# support bundle among them. The value ends at the next ``&``, whitespace or
|
||||
# quote, which is where uvicorn's format closes the path.
|
||||
QUERY_TOKEN_PATTERN = re.compile(r"(?P<key>[?&](?:token|access_token|api_key)=)[^&\s\"']+")
|
||||
QUERY_TOKEN_PATTERN = re.compile(r"(?P<key>[?&](?:token|access_token|api_key|url)=)[^&\s\"']+")
|
||||
|
||||
|
||||
def redact_query_tokens(text: str | None) -> str | None:
|
||||
|
||||
@@ -7,6 +7,26 @@ from backend.app.schemas.printer_location import normalize_location_name
|
||||
from backend.app.utils.printer_models import supports_nozzle_flow_type
|
||||
|
||||
|
||||
def _mask_url_login(url: str | None) -> str | None:
|
||||
"""A stored camera URL with its login secret masked.
|
||||
|
||||
One URL, not a log line: the login runs to the last ``@`` before the
|
||||
first ``/`` after the scheme, whitespace, ``?`` and ``#`` included (when
|
||||
in doubt it is masked). The user part up to the first ``:`` survives;
|
||||
without a ``:`` the login may be a token and goes whole.
|
||||
"""
|
||||
if not url or "://" not in url:
|
||||
return url
|
||||
start = url.index("://") + 3
|
||||
slash = url.find("/", start)
|
||||
end = len(url) if slash == -1 else slash
|
||||
if "@" not in url[start:end]:
|
||||
return url
|
||||
login, host = url[start:end].rsplit("@", 1)
|
||||
shown = f"{login.split(':', 1)[0]}:[REDACTED]" if ":" in login else "[REDACTED]"
|
||||
return f"{url[:start]}{shown}@{host}{url[end:]}"
|
||||
|
||||
|
||||
class PrinterBase(BaseModel):
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
serial_number: str = Field(..., min_length=1, max_length=50)
|
||||
@@ -159,9 +179,15 @@ class PrinterResponse(PrinterBase):
|
||||
)
|
||||
return cls(**data)
|
||||
|
||||
@field_validator("external_camera_url", "external_camera_snapshot_url", mode="after")
|
||||
@classmethod
|
||||
def _camera_credentials(cls, value: str | None) -> str | None:
|
||||
"""Readers see the camera URLs without the password in them."""
|
||||
return _mask_url_login(value)
|
||||
|
||||
|
||||
class PrinterResponseWithSecret(PrinterResponse):
|
||||
"""PrinterResponse + access_code. Returned ONLY to callers with
|
||||
"""PrinterResponse + access_code and the full camera URLs. Returned ONLY to callers with
|
||||
PRINTERS_UPDATE (Admin / Operator JWTs, or single-trust auth-disabled mode).
|
||||
|
||||
Viewers and API keys never receive this shape — they get the bare
|
||||
@@ -171,6 +197,12 @@ class PrinterResponseWithSecret(PrinterResponse):
|
||||
|
||||
access_code: str
|
||||
|
||||
@field_validator("external_camera_url", "external_camera_snapshot_url", mode="after")
|
||||
@classmethod
|
||||
def _camera_credentials(cls, value: str | None) -> str | None:
|
||||
"""Editors keep the full camera URLs, to edit them."""
|
||||
return value
|
||||
|
||||
|
||||
class HMSErrorResponse(BaseModel):
|
||||
code: str
|
||||
|
||||
@@ -14,7 +14,7 @@ from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.app.core.config import settings
|
||||
from backend.app.core.logging_filters import URL_CREDENTIALS_PATTERN, redact_query_tokens
|
||||
from backend.app.core.logging_filters import URL_CREDENTIALS_PATTERN, redact_query_tokens, redact_url_credentials
|
||||
from backend.app.models.printer import Printer
|
||||
from backend.app.models.settings import Settings
|
||||
from backend.app.models.user import User
|
||||
@@ -64,6 +64,13 @@ def parse_log_line(line: str) -> LogEntry | None:
|
||||
return None
|
||||
|
||||
|
||||
def _redacted(entry: LogEntry) -> LogEntry:
|
||||
# Lines on disk may predate a redaction: masked as they are read, before
|
||||
# any search, so a search cannot confirm a secret either.
|
||||
entry.message = redact_url_credentials(redact_query_tokens(entry.message)) or ""
|
||||
return entry
|
||||
|
||||
|
||||
def read_log_entries(
|
||||
limit: int = 200,
|
||||
level_filter: str | None = None,
|
||||
@@ -95,6 +102,7 @@ def read_log_entries(
|
||||
if parsed:
|
||||
# Found a new log entry start
|
||||
if current_entry:
|
||||
current_entry = _redacted(current_entry)
|
||||
# Apply filters and add previous entry (without multi_line_buffer - it belongs to new entry)
|
||||
should_include = True
|
||||
|
||||
@@ -130,6 +138,7 @@ def read_log_entries(
|
||||
# Don't forget the last (oldest) entry
|
||||
# Note: any remaining multi_line_buffer would be orphaned lines before the first entry
|
||||
if current_entry and len(entries) < limit:
|
||||
current_entry = _redacted(current_entry)
|
||||
should_include = True
|
||||
if level_filter and current_entry.level.upper() != level_filter.upper():
|
||||
should_include = False
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
"""External camera credentials reach only those who may edit the printer.
|
||||
|
||||
The camera login commonly sits in its URL (rtsp://user:password@host/...).
|
||||
Printer readers got both camera URLs as stored; the printer access code was
|
||||
already withheld from them. Readers now get the URLs with the password
|
||||
replaced; editors keep the full URLs they need to edit them.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
|
||||
|
||||
STREAM = "rtsp://cam:stream-pw@192.168.1.50:554/stream"
|
||||
SNAPSHOT = "http://cam:snap-pw@192.168.1.50/snapshot.jpg"
|
||||
|
||||
|
||||
async def _admin(client: AsyncClient) -> dict[str, str]:
|
||||
await client.post(
|
||||
"/api/v1/auth/setup",
|
||||
json={"auth_enabled": True, "admin_username": "camadmin", "admin_password": "AdminPass1!"},
|
||||
)
|
||||
login = await client.post("/api/v1/auth/login", json={"username": "camadmin", "password": "AdminPass1!"})
|
||||
return {"Authorization": f"Bearer {login.json()['access_token']}"}
|
||||
|
||||
|
||||
async def _viewer(client: AsyncClient, admin: dict[str, str]) -> dict[str, str]:
|
||||
group = await client.post(
|
||||
"/api/v1/groups/", headers=admin, json={"name": "camview", "permissions": ["printers:read"]}
|
||||
)
|
||||
await client.post(
|
||||
"/api/v1/users/",
|
||||
headers=admin,
|
||||
json={"username": "camviewer", "password": "UserPass1!", "group_ids": [group.json()["id"]]},
|
||||
)
|
||||
login = await client.post("/api/v1/auth/login", json={"username": "camviewer", "password": "UserPass1!"})
|
||||
return {"Authorization": f"Bearer {login.json()['access_token']}"}
|
||||
|
||||
|
||||
async def _api_key(client: AsyncClient, admin: dict[str, str]) -> dict[str, str]:
|
||||
key = await client.post("/api/v1/api-keys/", headers=admin, json={"name": "reader", "can_read_status": True})
|
||||
return {"X-API-Key": key.json()["key"]}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def camera_printer(printer_factory):
|
||||
return await printer_factory(
|
||||
name="Cam", external_camera_enabled=True, external_camera_url=STREAM, external_camera_snapshot_url=SNAPSHOT
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("who", ["viewer", "api_key"])
|
||||
async def test_a_reader_gets_the_camera_urls_without_their_passwords(async_client: AsyncClient, camera_printer, who):
|
||||
admin = await _admin(async_client)
|
||||
headers = await (_viewer if who == "viewer" else _api_key)(async_client, admin)
|
||||
|
||||
listed = await async_client.get("/api/v1/printers/", headers=headers)
|
||||
single = await async_client.get(f"/api/v1/printers/{camera_printer.id}", headers=headers)
|
||||
|
||||
assert listed.status_code == 200 and single.status_code == 200, (listed.text, single.text)
|
||||
for body in (listed.json()[0], single.json()):
|
||||
assert "stream-pw" not in body["external_camera_url"]
|
||||
assert "snap-pw" not in body["external_camera_snapshot_url"]
|
||||
assert body["external_camera_url"].endswith("@192.168.1.50:554/stream")
|
||||
assert "stream-pw" not in listed.text + single.text
|
||||
|
||||
|
||||
async def test_an_editor_gets_the_full_camera_urls(async_client: AsyncClient, camera_printer):
|
||||
admin = await _admin(async_client)
|
||||
|
||||
single = (await async_client.get(f"/api/v1/printers/{camera_printer.id}", headers=admin)).json()
|
||||
listed = (await async_client.get("/api/v1/printers/", headers=admin)).json()[0]
|
||||
|
||||
for body in (single, listed):
|
||||
assert body["external_camera_url"] == STREAM
|
||||
assert body["external_camera_snapshot_url"] == SNAPSHOT
|
||||
|
||||
|
||||
async def test_an_edit_leaves_the_stored_camera_url_alone(async_client: AsyncClient, camera_printer, db_session):
|
||||
"""The update's response is the reader shape; nothing it shows is written back."""
|
||||
from backend.app.models.printer import Printer
|
||||
|
||||
printer_id = camera_printer.id
|
||||
admin = await _admin(async_client)
|
||||
|
||||
response = await async_client.patch(f"/api/v1/printers/{printer_id}", headers=admin, json={"camera_rotation": 90})
|
||||
|
||||
assert response.status_code == 200, response.text
|
||||
db_session.expire_all()
|
||||
stored = await db_session.get(Printer, printer_id)
|
||||
assert stored.external_camera_url == STREAM and stored.external_camera_snapshot_url == SNAPSHOT
|
||||
|
||||
|
||||
async def test_the_camera_test_takes_the_url_in_its_body_and_still_in_the_query(
|
||||
async_client: AsyncClient, camera_printer
|
||||
):
|
||||
"""In the body it stays out of the access log; the query form is kept for a
|
||||
cached older page."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
printer_id = camera_printer.id
|
||||
admin = await _admin(async_client)
|
||||
|
||||
with patch(
|
||||
"backend.app.services.external_camera.test_connection",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"success": True},
|
||||
) as test:
|
||||
body = await async_client.post(
|
||||
f"/api/v1/printers/{printer_id}/camera/external/test",
|
||||
headers=admin,
|
||||
json={"url": STREAM, "camera_type": "rtsp"},
|
||||
)
|
||||
query = await async_client.post(
|
||||
f"/api/v1/printers/{printer_id}/camera/external/test",
|
||||
headers=admin,
|
||||
params={"url": STREAM, "camera_type": "rtsp"},
|
||||
)
|
||||
|
||||
assert body.status_code == 200, body.text
|
||||
assert query.status_code == 200, query.text
|
||||
assert [c.args for c in test.await_args_list] == [(STREAM, "rtsp"), (STREAM, "rtsp")]
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Log lines written before a redaction existed are masked when read.
|
||||
|
||||
The filters only mask lines written from now on; ``bambuddy.log`` can still
|
||||
hold older ones with a camera login (an access line with the camera URL in
|
||||
its query, a URL in a shape an older pattern missed). Lines are masked as
|
||||
they are read, before the search filter, so a search cannot confirm a secret
|
||||
either.
|
||||
"""
|
||||
|
||||
from backend.app.core.config import settings
|
||||
from backend.app.services.log_reader import read_log_entries
|
||||
|
||||
ACCESS = (
|
||||
"2026-10-01 10:00:00,000 INFO [uvicorn.access] [-] 127.0.0.1:1 - "
|
||||
'"POST /api/v1/printers/1/camera/external/test'
|
||||
'?url=rtsp%3A%2F%2Fadmin%3Aold-pw-1%40cam%2Fs&camera_type=rtsp HTTP/1.1" 200'
|
||||
)
|
||||
APP = (
|
||||
"2026-10-01 10:00:01,000 INFO [backend.app.services.external_camera] [x] "
|
||||
"Testing camera connection: type=rtsp, url=rtsp://:old-pw-2@10.0.0.5/s..."
|
||||
)
|
||||
TRACE = [
|
||||
"2026-10-01 10:00:02,000 ERROR [backend.app.services.external_camera] [x] Stream failed",
|
||||
" Input #0, rtsp, from 'http://old-token-3@10.0.0.5/snap.jpg':",
|
||||
]
|
||||
|
||||
|
||||
def _write(tmp_path, monkeypatch):
|
||||
(tmp_path / "bambuddy.log").write_text("\n".join([ACCESS, APP, *TRACE]) + "\n", encoding="utf-8")
|
||||
monkeypatch.setattr(settings, "log_dir", tmp_path)
|
||||
|
||||
|
||||
def test_old_lines_come_back_masked(tmp_path, monkeypatch):
|
||||
_write(tmp_path, monkeypatch)
|
||||
|
||||
entries, _total = read_log_entries(limit=50)
|
||||
|
||||
text = "\n".join(e.message for e in entries)
|
||||
assert len(entries) == 3
|
||||
for secret in ("old-pw-1", "old-pw-2", "old-token-3"):
|
||||
assert secret not in text
|
||||
assert "camera_type=rtsp" in text
|
||||
|
||||
|
||||
def test_a_search_cannot_confirm_a_secret(tmp_path, monkeypatch):
|
||||
_write(tmp_path, monkeypatch)
|
||||
|
||||
for secret in ("old-pw-1", "old-pw-2", "old-token-3"):
|
||||
entries, _total = read_log_entries(limit=50, search=secret)
|
||||
assert entries == [], secret
|
||||
@@ -59,6 +59,17 @@ class TestRedactUrlCredentials:
|
||||
result = redact_url_credentials("rtsp://bblp:code@10.0.0.1/live/user@example")
|
||||
assert result == "rtsp://bblp:[REDACTED]@10.0.0.1/live/user@example"
|
||||
|
||||
def test_masks_every_login_shape_a_camera_accepts(self):
|
||||
"""An empty user, an unencoded @ in the user, a bare token: the login
|
||||
is everything up to the last @ before the path."""
|
||||
for url, expected in (
|
||||
("from 'rtsp://:pw123@10.0.0.5/s'", "from 'rtsp://:[REDACTED]@10.0.0.5/s'"),
|
||||
("rtsp://me@example.com:pw123@10.0.0.5/s", "rtsp://me@example.com:[REDACTED]@10.0.0.5/s"),
|
||||
("GET http://tok123@10.0.0.5/snap.jpg failed", "GET http://[REDACTED]@10.0.0.5/snap.jpg failed"),
|
||||
("rtsp://admin:pa:ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
):
|
||||
assert redact_url_credentials(url) == expected
|
||||
|
||||
def test_leaves_credential_free_text_alone(self):
|
||||
for untouched in (
|
||||
"Connection refused",
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Printer readers see the camera URLs without the login secret, whatever shape
|
||||
the login takes; editors see them as stored."""
|
||||
|
||||
import pytest
|
||||
|
||||
from backend.app.schemas.printer import PrinterResponse, PrinterResponseWithSecret
|
||||
|
||||
BASE = {
|
||||
"id": 1,
|
||||
"name": "P",
|
||||
"serial_number": "00M09A000000001",
|
||||
"ip_address": "192.168.1.10",
|
||||
"model": "X1C",
|
||||
"is_active": True,
|
||||
"created_at": "2026-10-13T00:00:00",
|
||||
"updated_at": "2026-10-13T00:00:00",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("stored", "shown"),
|
||||
[
|
||||
("rtsp://admin:pw@10.0.0.5:554/s", "rtsp://admin:[REDACTED]@10.0.0.5:554/s"),
|
||||
("http://:pw@10.0.0.5/snap.jpg", "http://:[REDACTED]@10.0.0.5/snap.jpg"),
|
||||
("rtsp://me@example.com:pw@10.0.0.5/s", "rtsp://me@example.com:[REDACTED]@10.0.0.5/s"),
|
||||
("http://secrettoken@10.0.0.5/snap.jpg", "http://[REDACTED]@10.0.0.5/snap.jpg"),
|
||||
("rtsp://admin:p@ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
("rtsp://admin:pa:ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
("http://admin:pw@10.0.0.5", "http://admin:[REDACTED]@10.0.0.5"),
|
||||
("http://admin:pw@10.0.0.5/s?x=1#y", "http://admin:[REDACTED]@10.0.0.5/s?x=1#y"),
|
||||
("http://10.0.0.5/snap.jpg?a=b@c", "http://10.0.0.5/snap.jpg?a=b@c"),
|
||||
("http://10.0.0.5/path@thing", "http://10.0.0.5/path@thing"),
|
||||
# Without a path, an @ in the query or fragment cannot be told from
|
||||
# a password containing ? or #: masked rather than risk the password.
|
||||
("http://10.0.0.5?a=b@c", "http://[REDACTED]@c"),
|
||||
("http://10.0.0.5#a@b", "http://[REDACTED]@b"),
|
||||
("rtsp://admin:pa#ss@10.0.0.5:554/s", "rtsp://admin:[REDACTED]@10.0.0.5:554/s"),
|
||||
("rtsp://admin:pa?ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
("rtsp://admin:my pw@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
("rtsp://admin:my\tpw@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
|
||||
("/dev/video0", "/dev/video0"),
|
||||
("", ""),
|
||||
(None, None),
|
||||
],
|
||||
)
|
||||
def test_readers_never_see_the_login_secret(stored, shown):
|
||||
reader = PrinterResponse(**BASE, external_camera_url=stored, external_camera_snapshot_url=stored)
|
||||
editor = PrinterResponseWithSecret(
|
||||
**BASE, access_code="12345678", external_camera_url=stored, external_camera_snapshot_url=stored
|
||||
)
|
||||
|
||||
assert reader.external_camera_url == shown
|
||||
assert reader.external_camera_snapshot_url == shown
|
||||
assert editor.external_camera_url == stored
|
||||
@@ -111,3 +111,16 @@ def test_support_bundle_sanitizer_masks_tokens():
|
||||
line = f'INFO: 192.168.255.4:0 - "WebSocket /api/v1/ws?token={TOKEN}" [accepted]'
|
||||
assert TOKEN not in sanitize_log_content(line)
|
||||
assert "token=[REDACTED]" in sanitize_log_content(line)
|
||||
|
||||
|
||||
def test_a_camera_url_in_the_query_is_masked():
|
||||
"""The camera test sent the camera URL, login included, in its query."""
|
||||
line = (
|
||||
'"POST /api/v1/printers/1/camera/external/test'
|
||||
'?url=rtsp%3A%2F%2Fcam%3Apw123%40192.168.1.50%3A554%2Fs&camera_type=rtsp HTTP/1.1" 200'
|
||||
)
|
||||
|
||||
result = redact_query_tokens(line)
|
||||
|
||||
assert "pw123" not in result
|
||||
assert "camera_type=rtsp" in result
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* The camera test sends the camera URL, which may carry the camera login, in
|
||||
* its body: a query string ends up in the server's access log.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { server } from '../mocks/server';
|
||||
import { api } from '../../api/client';
|
||||
|
||||
afterEach(() => server.resetHandlers());
|
||||
|
||||
describe('testExternalCamera', () => {
|
||||
it('sends the URL in the body, not the query', async () => {
|
||||
let seenUrl = '';
|
||||
let body: unknown = null;
|
||||
server.use(
|
||||
http.post('*/api/v1/printers/:id/camera/external/test', async ({ request }) => {
|
||||
seenUrl = request.url;
|
||||
body = await request.json();
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
);
|
||||
|
||||
await api.testExternalCamera(3, 'rtsp://cam:pw123@10.0.0.5/s', 'rtsp');
|
||||
|
||||
expect(seenUrl).not.toContain('pw123');
|
||||
expect(new URL(seenUrl).search).toBe('');
|
||||
expect(body).toEqual({ url: 'rtsp://cam:pw123@10.0.0.5/s', camera_type: 'rtsp' });
|
||||
});
|
||||
});
|
||||
@@ -5126,9 +5126,11 @@ export const api = {
|
||||
// running (Obico polling, a snapshot) rather than a connection this test
|
||||
// opened — a single-reader camera is shared rather than opened twice, so
|
||||
// the result is real but says nothing about reaching the camera just now.
|
||||
// In the body: the URL may carry the camera login, and a query string
|
||||
// ends up in the server's access log.
|
||||
request<{ success: boolean; error?: string; resolution?: string; coalesced?: boolean }>(
|
||||
`/printers/${printerId}/camera/external/test?url=${encodeURIComponent(url)}&camera_type=${encodeURIComponent(cameraType)}`,
|
||||
{ method: 'POST' }
|
||||
`/printers/${printerId}/camera/external/test`,
|
||||
{ method: 'POST', body: JSON.stringify({ url, camera_type: cameraType }) }
|
||||
),
|
||||
|
||||
// Print Control
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{C as e}from"./client-S4xOa3gM.js";var t=e();function n({variant:e=`primary`,size:n=`md`,className:r=``,children:i,...a}){return(0,t.jsx)(`button`,{className:`inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-bambu-dark disabled:opacity-50 disabled:cursor-not-allowed ${{primary:`bg-bambu-green hover:bg-bambu-green-light text-white focus:ring-bambu-green`,secondary:`bg-bambu-dark-tertiary hover:bg-bambu-gray-dark text-white focus:ring-bambu-gray`,danger:`bg-red-600 hover:bg-red-700 text-white focus:ring-red-500`,ghost:`bg-transparent hover:bg-bambu-dark-tertiary text-bambu-gray-light hover:text-white`}[e]} ${{sm:`px-3 py-1.5 text-sm gap-1.5 min-h-[44px] md:min-h-0`,md:`px-4 py-2 text-sm gap-2 min-h-[44px] md:min-h-0`,lg:`px-6 py-3 text-base gap-2 min-h-[48px] md:min-h-0`}[n]} ${r}`,...a,children:i})}export{n as t};
|
||||
import{C as e}from"./client-C3LdD0iY.js";var t=e();function n({variant:e=`primary`,size:n=`md`,className:r=``,children:i,...a}){return(0,t.jsx)(`button`,{className:`inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-bambu-dark disabled:opacity-50 disabled:cursor-not-allowed ${{primary:`bg-bambu-green hover:bg-bambu-green-light text-white focus:ring-bambu-green`,secondary:`bg-bambu-dark-tertiary hover:bg-bambu-gray-dark text-white focus:ring-bambu-gray`,danger:`bg-red-600 hover:bg-red-700 text-white focus:ring-red-500`,ghost:`bg-transparent hover:bg-bambu-dark-tertiary text-bambu-gray-light hover:text-white`}[e]} ${{sm:`px-3 py-1.5 text-sm gap-1.5 min-h-[44px] md:min-h-0`,md:`px-4 py-2 text-sm gap-2 min-h-[44px] md:min-h-0`,lg:`px-6 py-3 text-base gap-2 min-h-[48px] md:min-h-0`}[n]} ${r}`,...a,children:i})}export{n as t};
|
||||
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,g as i,w as a}from"./client-S4xOa3gM.js";import{t as o}from"./useQuery-CCrbj-1e.js";import{a as s,t as c}from"./CameraWall-CDYZxLAy.js";import{Bn as l,Wn as u,yt as d,zn as f}from"./index-PPJXJ7Xk.js";var p=e(n(),1),m=t(),h=5e3,g=4,_=8,v=1,y=16,b=2,x=60;function S(e,t,n,r){let i=parseInt(e??``,10);return Number.isFinite(i)?Math.min(r,Math.max(n,i)):t}function C(e,t,n,r,i,a){return e.has(t)?S(e.get(t),r,i,a):S(localStorage.getItem(n),r,i,a)}function w(e){let t=e.get(`size`)?.toLowerCase(),n=s.indexOf(t);if(n>=0)return n+1;let r=parseInt(localStorage.getItem(`camWallTileSize`)??``,10);return r>=1&&r<=4?r:2}function T(){let{t:e}=a(),t=l(),{authEnabled:n,loading:s,user:S}=d(),[T]=u(),E=T.get(`token`),D=E!=null&&E!==``,[O,k]=(0,p.useState)(()=>C(T,`maxLive`,`camWallMaxLive`,g,v,y)),[A,j]=(0,p.useState)(()=>C(T,`interval`,`camWallSnapshotSec`,_,b,x)),[M]=(0,p.useState)(()=>w(T)),[N,P]=(0,p.useState)(()=>{let e=T.get(`status`)??localStorage.getItem(`camWallStatusMode`);return(D?[`off`,`compact`]:[`off`,`compact`,`full`]).includes(e)?e:`compact`});(0,p.useEffect)(()=>{if(D)return i(E),()=>i(null)},[D,E]);let F=o({queryKey:[`camwall-printers`,E],queryFn:()=>r.getCamWallPrinters(E??void 0),enabled:D,refetchInterval:h}),I=o({queryKey:[`printers`],queryFn:()=>r.getPrinters(),enabled:!D&&!s&&(!n||S!==null),refetchInterval:h}),L=(0,p.useMemo)(()=>{let e=new Map;for(let t of F.data??[])e.set(t.id,{connected:t.connected,state:t.state,progress:t.progress,remaining_time:t.remaining_time,layer_num:t.layer_num,total_layers:t.total_layers,hms_errors:t.hms_errors});return e},[F.data]);if(!D&&s)return(0,m.jsx)(`div`,{className:`flex min-h-screen items-center justify-center bg-bambu-dark text-bambu-gray`,children:e(`common.loading`)});if(!D&&n&&!S)return(0,m.jsx)(f,{to:`/login`,replace:!0,state:{from:t}});let R=D?F:I,z=D?F.data??[]:I.data??[];return R.isError?(0,m.jsx)(`div`,{className:`flex min-h-screen items-center justify-center bg-bambu-dark p-6 text-center`,children:(0,m.jsx)(`p`,{className:`max-w-md text-sm text-red-400`,children:e(D?`printers.camWall.page.tokenRejected`:`printers.camWall.page.loadFailed`)})}):(0,m.jsx)(`div`,{className:`min-h-screen bg-bambu-dark p-4`,children:(0,m.jsx)(c,{printers:z,maxLive:O,snapshotIntervalSec:A,statusMode:N,tileSize:M,statuses:D?L:void 0,showSettings:!D,onTileClick:D?void 0:e=>window.open(`/camera/${e}`,`camera-${e}`),onChangeMaxLive:e=>{k(e),localStorage.setItem(`camWallMaxLive`,String(e))},onChangeSnapshotIntervalSec:e=>{j(e),localStorage.setItem(`camWallSnapshotSec`,String(e))},onChangeStatusMode:e=>{P(e),localStorage.setItem(`camWallStatusMode`,e)}})})}export{T as CamWallPage,T as default};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,g as i,w as a}from"./client-C3LdD0iY.js";import{t as o}from"./useQuery-BSYE6Prb.js";import{a as s,t as c}from"./CameraWall-Cg-tcG8a.js";import{Bn as l,Wn as u,yt as d,zn as f}from"./index-DEbGNNhA.js";var p=e(n(),1),m=t(),h=5e3,g=4,_=8,v=1,y=16,b=2,x=60;function S(e,t,n,r){let i=parseInt(e??``,10);return Number.isFinite(i)?Math.min(r,Math.max(n,i)):t}function C(e,t,n,r,i,a){return e.has(t)?S(e.get(t),r,i,a):S(localStorage.getItem(n),r,i,a)}function w(e){let t=e.get(`size`)?.toLowerCase(),n=s.indexOf(t);if(n>=0)return n+1;let r=parseInt(localStorage.getItem(`camWallTileSize`)??``,10);return r>=1&&r<=4?r:2}function T(){let{t:e}=a(),t=l(),{authEnabled:n,loading:s,user:S}=d(),[T]=u(),E=T.get(`token`),D=E!=null&&E!==``,[O,k]=(0,p.useState)(()=>C(T,`maxLive`,`camWallMaxLive`,g,v,y)),[A,j]=(0,p.useState)(()=>C(T,`interval`,`camWallSnapshotSec`,_,b,x)),[M]=(0,p.useState)(()=>w(T)),[N,P]=(0,p.useState)(()=>{let e=T.get(`status`)??localStorage.getItem(`camWallStatusMode`);return(D?[`off`,`compact`]:[`off`,`compact`,`full`]).includes(e)?e:`compact`});(0,p.useEffect)(()=>{if(D)return i(E),()=>i(null)},[D,E]);let F=o({queryKey:[`camwall-printers`,E],queryFn:()=>r.getCamWallPrinters(E??void 0),enabled:D,refetchInterval:h}),I=o({queryKey:[`printers`],queryFn:()=>r.getPrinters(),enabled:!D&&!s&&(!n||S!==null),refetchInterval:h}),L=(0,p.useMemo)(()=>{let e=new Map;for(let t of F.data??[])e.set(t.id,{connected:t.connected,state:t.state,progress:t.progress,remaining_time:t.remaining_time,layer_num:t.layer_num,total_layers:t.total_layers,hms_errors:t.hms_errors});return e},[F.data]);if(!D&&s)return(0,m.jsx)(`div`,{className:`flex min-h-screen items-center justify-center bg-bambu-dark text-bambu-gray`,children:e(`common.loading`)});if(!D&&n&&!S)return(0,m.jsx)(f,{to:`/login`,replace:!0,state:{from:t}});let R=D?F:I,z=D?F.data??[]:I.data??[];return R.isError?(0,m.jsx)(`div`,{className:`flex min-h-screen items-center justify-center bg-bambu-dark p-6 text-center`,children:(0,m.jsx)(`p`,{className:`max-w-md text-sm text-red-400`,children:e(D?`printers.camWall.page.tokenRejected`:`printers.camWall.page.loadFailed`)})}):(0,m.jsx)(`div`,{className:`min-h-screen bg-bambu-dark p-4`,children:(0,m.jsx)(c,{printers:z,maxLive:O,snapshotIntervalSec:A,statusMode:N,tileSize:M,statuses:D?L:void 0,showSettings:!D,onTileClick:D?void 0:e=>window.open(`/camera/${e}`,`camera-${e}`),onChangeMaxLive:e=>{k(e),localStorage.setItem(`camWallMaxLive`,String(e))},onChangeSnapshotIntervalSec:e=>{j(e),localStorage.setItem(`camWallSnapshotSec`,String(e))},onChangeStatusMode:e=>{P(e),localStorage.setItem(`camWallStatusMode`,e)}})})}export{T as CamWallPage,T as default};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n}from"./client-S4xOa3gM.js";var r=e(n(),1),i=t(),a=(0,r.createContext)(`normal`);function o({density:e,children:t}){return(0,i.jsx)(a.Provider,{value:e,children:t})}function s({children:e,className:t=``,onClick:n,onContextMenu:r,...a}){return(0,i.jsx)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary card-shadow ${n?`cursor-pointer`:``} ${t}`,onClick:n,onContextMenu:r,...a,children:e})}function c({children:e,className:t=``,dense:n}){let o=(0,r.useContext)(a)===`dense`;return(0,i.jsx)(`div`,{className:`${n??o?`px-4 py-2.5`:`px-6 py-4`} border-b border-bambu-dark-tertiary ${t}`,children:e})}function l({children:e,className:t=``,dense:n}){let o=(0,r.useContext)(a)===`dense`;return(0,i.jsx)(`div`,{className:`${n??o?`p-4`:`p-6`} ${t}`,children:e})}export{c as i,l as n,o as r,s as t};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n}from"./client-C3LdD0iY.js";var r=e(n(),1),i=t(),a=(0,r.createContext)(`normal`);function o({density:e,children:t}){return(0,i.jsx)(a.Provider,{value:e,children:t})}function s({children:e,className:t=``,onClick:n,onContextMenu:r,...a}){return(0,i.jsx)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary card-shadow ${n?`cursor-pointer`:``} ${t}`,onClick:n,onContextMenu:r,...a,children:e})}function c({children:e,className:t=``,dense:n}){let o=(0,r.useContext)(a)===`dense`;return(0,i.jsx)(`div`,{className:`${n??o?`px-4 py-2.5`:`px-6 py-4`} border-b border-bambu-dark-tertiary ${t}`,children:e})}function l({children:e,className:t=``,dense:n}){let o=(0,r.useContext)(a)===`dense`;return(0,i.jsx)(`div`,{className:`${n??o?`p-4`:`p-6`} ${t}`,children:e})}export{c as i,l as n,o as r,s as t};
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,w as r}from"./client-S4xOa3gM.js";import{a as i,i as a}from"./info-DQoQ-N03.js";import{t as o}from"./eye-off-BAETyyqx.js";import{t as s}from"./grip-vertical-Ho5ILpqf.js";import{n as c,t as l}from"./Card-DzC7lYtY.js";import{t as u}from"./Button-DSQo4CdN.js";import{Gt as d,Sn as f}from"./index-PPJXJ7Xk.js";var p=e(n(),1),m=t();function h({isOpen:e,onClose:t,columns:n,defaultColumns:h,onSave:g}){let{t:_}=r(),[v,y]=(0,p.useState)(n),[b,x]=(0,p.useState)(null),S=(0,p.useRef)(null);if((0,p.useEffect)(()=>{e&&y(n.map(e=>({...e})))},[e,n]),(0,p.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t]),!e)return null;let C=e=>{y(t=>t.map((t,n)=>n===e?{...t,visible:!t.visible}:t))},w=(e,t)=>{t<0||t>=v.length||y(n=>{let r=[...n],[i]=r.splice(e,1);return r.splice(t,0,i),r})},T=(e,t)=>{S.current=t,x(t),e.dataTransfer.effectAllowed=`move`},E=(e,t)=>{e.preventDefault(),e.dataTransfer.dropEffect=`move`;let n=S.current;n!==null&&n!==t&&(w(n,t),S.current=t,x(t))},D=e=>{e.preventDefault()},O=()=>{S.current=null,x(null)},k=()=>{y(h.map(e=>({...e})))},A=()=>{g(v),t()},j=v.filter(e=>e.visible).length;return(0,m.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,m.jsx)(l,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:(0,m.jsxs)(c,{className:`p-6 flex flex-col min-h-0`,children:[(0,m.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-2`,children:_(`inventory.configureColumns`)}),(0,m.jsxs)(`p`,{className:`text-sm text-bambu-gray mb-4`,children:[_(`inventory.configureColumnsDesc`),(0,m.jsxs)(`span`,{className:`ml-2 text-bambu-gray/60`,children:[`(`,j,` `,_(`inventory.of`),` `,v.length,` `,_(`inventory.visible`),`)`]})]}),(0,m.jsx)(`div`,{className:`space-y-1 overflow-y-auto flex-1 min-h-0 pr-1`,children:v.map((e,t)=>(0,m.jsxs)(`div`,{className:`flex items-center gap-2 p-2 rounded-lg border transition-colors ${b===t?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary bg-bambu-dark-tertiary/50`} ${e.visible?``:`opacity-50`}`,draggable:!0,onDragStart:e=>T(e,t),onDragOver:e=>E(e,t),onDrop:D,onDragEnd:O,children:[(0,m.jsx)(`div`,{className:`cursor-grab text-bambu-gray/50 hover:text-bambu-gray`,children:(0,m.jsx)(s,{className:`w-4 h-4`})}),(0,m.jsx)(`span`,{className:`flex-1 font-medium text-sm text-white`,children:e.label}),(0,m.jsxs)(`div`,{className:`flex items-center gap-0.5`,children:[(0,m.jsx)(`button`,{onClick:()=>w(t,t-1),disabled:t===0,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:_(`inventory.moveUp`),children:(0,m.jsx)(a,{className:`w-4 h-4`})}),(0,m.jsx)(`button`,{onClick:()=>w(t,t+1),disabled:t===v.length-1,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:_(`inventory.moveDown`),children:(0,m.jsx)(i,{className:`w-4 h-4`})})]}),(0,m.jsx)(`button`,{onClick:()=>C(t),className:`p-1.5 rounded transition-colors ${e.visible?`text-bambu-green hover:bg-bambu-green/10`:`text-bambu-gray/50 hover:bg-bambu-dark-secondary`}`,title:e.visible?_(`inventory.hideColumn`):_(`inventory.showColumn`),children:e.visible?(0,m.jsx)(f,{className:`w-4 h-4`}):(0,m.jsx)(o,{className:`w-4 h-4`})})]},e.id))}),(0,m.jsxs)(`div`,{className:`flex items-center gap-3 mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:[(0,m.jsxs)(u,{variant:`secondary`,onClick:k,className:`mr-auto`,children:[(0,m.jsx)(d,{className:`w-4 h-4`}),_(`inventory.reset`)]}),(0,m.jsx)(u,{variant:`secondary`,onClick:t,children:_(`inventory.cancel`)}),(0,m.jsx)(u,{onClick:A,children:_(`inventory.applyChanges`)})]})]})})})}export{h as t};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,w as r}from"./client-C3LdD0iY.js";import{a as i,i as a}from"./info-jpcgNqAh.js";import{t as o}from"./eye-off-BKHC5oyQ.js";import{t as s}from"./grip-vertical-eoFY62AH.js";import{n as c,t as l}from"./Card-BvtE18YT.js";import{t as u}from"./Button-B2stjvVl.js";import{Gt as d,Sn as f}from"./index-DEbGNNhA.js";var p=e(n(),1),m=t();function h({isOpen:e,onClose:t,columns:n,defaultColumns:h,onSave:g}){let{t:_}=r(),[v,y]=(0,p.useState)(n),[b,x]=(0,p.useState)(null),S=(0,p.useRef)(null);if((0,p.useEffect)(()=>{e&&y(n.map(e=>({...e})))},[e,n]),(0,p.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t]),!e)return null;let C=e=>{y(t=>t.map((t,n)=>n===e?{...t,visible:!t.visible}:t))},w=(e,t)=>{t<0||t>=v.length||y(n=>{let r=[...n],[i]=r.splice(e,1);return r.splice(t,0,i),r})},T=(e,t)=>{S.current=t,x(t),e.dataTransfer.effectAllowed=`move`},E=(e,t)=>{e.preventDefault(),e.dataTransfer.dropEffect=`move`;let n=S.current;n!==null&&n!==t&&(w(n,t),S.current=t,x(t))},D=e=>{e.preventDefault()},O=()=>{S.current=null,x(null)},k=()=>{y(h.map(e=>({...e})))},A=()=>{g(v),t()},j=v.filter(e=>e.visible).length;return(0,m.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,m.jsx)(l,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:(0,m.jsxs)(c,{className:`p-6 flex flex-col min-h-0`,children:[(0,m.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-2`,children:_(`inventory.configureColumns`)}),(0,m.jsxs)(`p`,{className:`text-sm text-bambu-gray mb-4`,children:[_(`inventory.configureColumnsDesc`),(0,m.jsxs)(`span`,{className:`ml-2 text-bambu-gray/60`,children:[`(`,j,` `,_(`inventory.of`),` `,v.length,` `,_(`inventory.visible`),`)`]})]}),(0,m.jsx)(`div`,{className:`space-y-1 overflow-y-auto flex-1 min-h-0 pr-1`,children:v.map((e,t)=>(0,m.jsxs)(`div`,{className:`flex items-center gap-2 p-2 rounded-lg border transition-colors ${b===t?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary bg-bambu-dark-tertiary/50`} ${e.visible?``:`opacity-50`}`,draggable:!0,onDragStart:e=>T(e,t),onDragOver:e=>E(e,t),onDrop:D,onDragEnd:O,children:[(0,m.jsx)(`div`,{className:`cursor-grab text-bambu-gray/50 hover:text-bambu-gray`,children:(0,m.jsx)(s,{className:`w-4 h-4`})}),(0,m.jsx)(`span`,{className:`flex-1 font-medium text-sm text-white`,children:e.label}),(0,m.jsxs)(`div`,{className:`flex items-center gap-0.5`,children:[(0,m.jsx)(`button`,{onClick:()=>w(t,t-1),disabled:t===0,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:_(`inventory.moveUp`),children:(0,m.jsx)(a,{className:`w-4 h-4`})}),(0,m.jsx)(`button`,{onClick:()=>w(t,t+1),disabled:t===v.length-1,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:_(`inventory.moveDown`),children:(0,m.jsx)(i,{className:`w-4 h-4`})})]}),(0,m.jsx)(`button`,{onClick:()=>C(t),className:`p-1.5 rounded transition-colors ${e.visible?`text-bambu-green hover:bg-bambu-green/10`:`text-bambu-gray/50 hover:bg-bambu-dark-secondary`}`,title:e.visible?_(`inventory.hideColumn`):_(`inventory.showColumn`),children:e.visible?(0,m.jsx)(f,{className:`w-4 h-4`}):(0,m.jsx)(o,{className:`w-4 h-4`})})]},e.id))}),(0,m.jsxs)(`div`,{className:`flex items-center gap-3 mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:[(0,m.jsxs)(u,{variant:`secondary`,onClick:k,className:`mr-auto`,children:[(0,m.jsx)(d,{className:`w-4 h-4`}),_(`inventory.reset`)]}),(0,m.jsx)(u,{variant:`secondary`,onClick:t,children:_(`inventory.cancel`)}),(0,m.jsx)(u,{onClick:A,children:_(`inventory.applyChanges`)})]})]})})})}export{h as t};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,t as i,w as a}from"./client-S4xOa3gM.js";import{t as o}from"./link-2-Bh3w8_iz.js";import{t as s}from"./loader-circle-BKXgelDY.js";import{t as c}from"./triangle-alert-D9uK6ZqX.js";import{Wn as l,yt as u}from"./index-PPJXJ7Xk.js";var d=e(n(),1),f=t();function p(e,t){let n=new URL(e);for(let[e,r]of Object.entries(t))r&&n.searchParams.set(e,r);return n.toString()}function m(){let{t:e}=a(),{authEnabled:t,loading:n}=u(),[m]=l(),[h,g]=(0,d.useState)({kind:`loading`}),_=(0,d.useRef)(!1),v=m.get(`client_id`)??``,y=m.get(`redirect_uri`)??``,b=m.get(`state`)??``,x=m.get(`code_challenge`)??``,S=m.get(`code_challenge_method`)??``,C=async()=>{g({kind:`redirecting`});try{let e=await r.connectAuthorize({client_id:v,redirect_uri:y,code_challenge:x,code_challenge_method:`S256`});window.location.replace(p(e.redirect_uri,{code:e.code,state:b}))}catch(t){g({kind:`error`,message:t instanceof Error?t.message:e(`connectedApps.authorize.failed`)})}};return(0,d.useEffect)(()=>{if(!(n||_.current)){if(_.current=!0,!t){g({kind:`error`,message:e(`connectedApps.authorize.authDisabled`)});return}if(!v||!y||!x||S!==`S256`){g({kind:`error`,message:e(`connectedApps.authorize.invalidRequest`)});return}r.getConnectAuthorizeInfo(v,y).then(e=>{e.already_granted?C():g({kind:`consent`,info:e})}).catch(t=>{g({kind:`error`,message:t instanceof i&&t.status===409?e(`connectedApps.authorize.authDisabled`):e(`connectedApps.authorize.invalidRequest`)})})}},[n,t]),(0,f.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-bambu-dark p-4`,children:(0,f.jsxs)(`div`,{className:`max-w-md w-full space-y-6 p-8 bg-gradient-to-br from-bambu-card to-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary shadow-lg`,children:[(h.kind===`loading`||h.kind===`redirecting`)&&(0,f.jsxs)(`div`,{className:`flex flex-col items-center gap-3 text-bambu-gray`,role:`status`,children:[(0,f.jsx)(s,{className:`w-8 h-8 animate-spin text-bambu-green`}),(0,f.jsx)(`p`,{children:h.kind===`loading`?e(`connectedApps.authorize.checking`):e(`connectedApps.authorize.redirecting`)})]}),h.kind===`error`&&(0,f.jsxs)(`div`,{className:`text-center space-y-3`,children:[(0,f.jsx)(c,{className:`w-10 h-10 mx-auto text-yellow-600 dark:text-yellow-400`}),(0,f.jsx)(`h1`,{className:`text-xl font-semibold text-white`,children:e(`connectedApps.authorize.errorTitle`)}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:h.message})]}),h.kind===`consent`&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`div`,{className:`text-center space-y-3`,children:[(0,f.jsx)(`div`,{className:`w-14 h-14 mx-auto rounded-full bg-bambu-green/20 flex items-center justify-center`,children:(0,f.jsx)(o,{className:`w-7 h-7 text-bambu-green`})}),(0,f.jsx)(`h1`,{className:`text-xl font-semibold text-white text-balance`,children:e(`connectedApps.authorize.title`,{app:h.info.app_name})}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:e(`connectedApps.authorize.signedInAs`,{username:h.info.username})})]}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:e(`connectedApps.authorize.sharedData`,{app:h.info.app_name})}),(0,f.jsxs)(`div`,{className:`flex gap-3`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>{window.location.replace(p(y,{error:`access_denied`,state:b}))},className:`flex-1 px-4 py-2 bg-bambu-dark-tertiary text-white rounded-md hover:bg-bambu-dark-tertiary/80 focus:outline-none focus-visible:ring-2 focus-visible:ring-bambu-green`,children:e(`connectedApps.authorize.deny`)}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void C(),className:`flex-1 px-4 py-2 bg-bambu-green text-white rounded-md hover:bg-bambu-green/90 focus:outline-none focus-visible:ring-2 focus-visible:ring-white`,children:e(`connectedApps.authorize.allow`)})]})]})]})})}export{m as ConnectAuthorizePage};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,t as i,w as a}from"./client-C3LdD0iY.js";import{t as o}from"./link-2-BrJ-i2LF.js";import{t as s}from"./loader-circle-CbaPxZRP.js";import{t as c}from"./triangle-alert-BUlaDyuA.js";import{Wn as l,yt as u}from"./index-DEbGNNhA.js";var d=e(n(),1),f=t();function p(e,t){let n=new URL(e);for(let[e,r]of Object.entries(t))r&&n.searchParams.set(e,r);return n.toString()}function m(){let{t:e}=a(),{authEnabled:t,loading:n}=u(),[m]=l(),[h,g]=(0,d.useState)({kind:`loading`}),_=(0,d.useRef)(!1),v=m.get(`client_id`)??``,y=m.get(`redirect_uri`)??``,b=m.get(`state`)??``,x=m.get(`code_challenge`)??``,S=m.get(`code_challenge_method`)??``,C=async()=>{g({kind:`redirecting`});try{let e=await r.connectAuthorize({client_id:v,redirect_uri:y,code_challenge:x,code_challenge_method:`S256`});window.location.replace(p(e.redirect_uri,{code:e.code,state:b}))}catch(t){g({kind:`error`,message:t instanceof Error?t.message:e(`connectedApps.authorize.failed`)})}};return(0,d.useEffect)(()=>{if(!(n||_.current)){if(_.current=!0,!t){g({kind:`error`,message:e(`connectedApps.authorize.authDisabled`)});return}if(!v||!y||!x||S!==`S256`){g({kind:`error`,message:e(`connectedApps.authorize.invalidRequest`)});return}r.getConnectAuthorizeInfo(v,y).then(e=>{e.already_granted?C():g({kind:`consent`,info:e})}).catch(t=>{g({kind:`error`,message:t instanceof i&&t.status===409?e(`connectedApps.authorize.authDisabled`):e(`connectedApps.authorize.invalidRequest`)})})}},[n,t]),(0,f.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-bambu-dark p-4`,children:(0,f.jsxs)(`div`,{className:`max-w-md w-full space-y-6 p-8 bg-gradient-to-br from-bambu-card to-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary shadow-lg`,children:[(h.kind===`loading`||h.kind===`redirecting`)&&(0,f.jsxs)(`div`,{className:`flex flex-col items-center gap-3 text-bambu-gray`,role:`status`,children:[(0,f.jsx)(s,{className:`w-8 h-8 animate-spin text-bambu-green`}),(0,f.jsx)(`p`,{children:h.kind===`loading`?e(`connectedApps.authorize.checking`):e(`connectedApps.authorize.redirecting`)})]}),h.kind===`error`&&(0,f.jsxs)(`div`,{className:`text-center space-y-3`,children:[(0,f.jsx)(c,{className:`w-10 h-10 mx-auto text-yellow-600 dark:text-yellow-400`}),(0,f.jsx)(`h1`,{className:`text-xl font-semibold text-white`,children:e(`connectedApps.authorize.errorTitle`)}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:h.message})]}),h.kind===`consent`&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`div`,{className:`text-center space-y-3`,children:[(0,f.jsx)(`div`,{className:`w-14 h-14 mx-auto rounded-full bg-bambu-green/20 flex items-center justify-center`,children:(0,f.jsx)(o,{className:`w-7 h-7 text-bambu-green`})}),(0,f.jsx)(`h1`,{className:`text-xl font-semibold text-white text-balance`,children:e(`connectedApps.authorize.title`,{app:h.info.app_name})}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:e(`connectedApps.authorize.signedInAs`,{username:h.info.username})})]}),(0,f.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:e(`connectedApps.authorize.sharedData`,{app:h.info.app_name})}),(0,f.jsxs)(`div`,{className:`flex gap-3`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>{window.location.replace(p(y,{error:`access_denied`,state:b}))},className:`flex-1 px-4 py-2 bg-bambu-dark-tertiary text-white rounded-md hover:bg-bambu-dark-tertiary/80 focus:outline-none focus-visible:ring-2 focus-visible:ring-bambu-green`,children:e(`connectedApps.authorize.deny`)}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void C(),className:`flex-1 px-4 py-2 bg-bambu-green text-white rounded-md hover:bg-bambu-green/90 focus:outline-none focus-visible:ring-2 focus-visible:ring-white`,children:e(`connectedApps.authorize.allow`)})]})]})]})})}export{m as ConnectAuthorizePage};
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,w as r}from"./client-S4xOa3gM.js";import{t as i}from"./createLucideIcon-CozFoJIa.js";import{t as a}from"./check-VKvTBKbR.js";import{t as o}from"./copy-B-3YTgwv.js";var s=i(`monitor-play`,[[`path`,{d:`M15.033 9.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56V7.648a.645.645 0 0 1 .967-.56z`,key:`vbtd3f`}],[`path`,{d:`M12 17v4`,key:`1riwvh`}],[`path`,{d:`M8 21h8`,key:`1ev6f3`}],[`rect`,{x:`2`,y:`3`,width:`20`,height:`14`,rx:`2`,key:`x3v2xh`}]]),c=i(`scan-eye`,[[`path`,{d:`M3 7V5a2 2 0 0 1 2-2h2`,key:`aa7l1z`}],[`path`,{d:`M17 3h2a2 2 0 0 1 2 2v2`,key:`4qcy5o`}],[`path`,{d:`M21 17v2a2 2 0 0 1-2 2h-2`,key:`6vwrx8`}],[`path`,{d:`M7 21H5a2 2 0 0 1-2-2v-2`,key:`ioqczr`}],[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`path`,{d:`M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0`,key:`11ak4c`}]]),l=[120,220,260],u=[55,75,90],d=[35,45,60],f=[50,75,100],p=[{key:`nozzle_temp_presets`,defaults:l,lo:0,hi:320,unit:`C`},{key:`bed_temp_presets`,defaults:u,lo:0,hi:140,unit:`C`},{key:`chamber_temp_presets`,defaults:d,lo:0,hi:65,unit:`C`},{key:`fan_speed_presets`,defaults:f,lo:0,hi:100,unit:`%`}];function m(e,t,n,r){if(!e)return[...t];try{let t=JSON.parse(e);if(Array.isArray(t)&&t.length===3&&t.every(e=>Number.isInteger(e)&&e>=n&&e<=r))return t}catch{}return[...t]}function h(e,t){return[{label:`Off`,value:0},...e.map(e=>({label:`${e} ${t}`,value:e}))]}var g=e(n(),1),_=t();function v({value:e,titleKey:t=`printers.copyToClipboard`,copiedTitleKey:n=`printers.copied`,className:i=`ml-2 p-1 rounded hover:bg-bambu-dark-tertiary text-bambu-gray hover:text-white transition-colors`,iconClassName:s=`w-3.5 h-3.5`}){let{t:c}=r(),[l,u]=(0,g.useState)(!1);return(0,_.jsx)(`button`,{onClick:async()=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t);try{if(t.select(),!document.execCommand(`copy`))return}finally{document.body.removeChild(t)}}u(!0),setTimeout(()=>u(!1),2e3)}catch{}},className:i,title:c(l?n:t),children:l?(0,_.jsx)(a,{className:`${s} text-bambu-green`}):(0,_.jsx)(o,{className:s})})}export{l as a,m as c,f as i,c as l,u as n,p as o,d as r,h as s,v as t,s as u};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,w as r}from"./client-C3LdD0iY.js";import{t as i}from"./createLucideIcon-DiLOIyaZ.js";import{t as a}from"./check-DMVASzXX.js";import{t as o}from"./copy-BMNoF6UH.js";var s=i(`monitor-play`,[[`path`,{d:`M15.033 9.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56V7.648a.645.645 0 0 1 .967-.56z`,key:`vbtd3f`}],[`path`,{d:`M12 17v4`,key:`1riwvh`}],[`path`,{d:`M8 21h8`,key:`1ev6f3`}],[`rect`,{x:`2`,y:`3`,width:`20`,height:`14`,rx:`2`,key:`x3v2xh`}]]),c=i(`scan-eye`,[[`path`,{d:`M3 7V5a2 2 0 0 1 2-2h2`,key:`aa7l1z`}],[`path`,{d:`M17 3h2a2 2 0 0 1 2 2v2`,key:`4qcy5o`}],[`path`,{d:`M21 17v2a2 2 0 0 1-2 2h-2`,key:`6vwrx8`}],[`path`,{d:`M7 21H5a2 2 0 0 1-2-2v-2`,key:`ioqczr`}],[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`path`,{d:`M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0`,key:`11ak4c`}]]),l=[120,220,260],u=[55,75,90],d=[35,45,60],f=[50,75,100],p=[{key:`nozzle_temp_presets`,defaults:l,lo:0,hi:320,unit:`C`},{key:`bed_temp_presets`,defaults:u,lo:0,hi:140,unit:`C`},{key:`chamber_temp_presets`,defaults:d,lo:0,hi:65,unit:`C`},{key:`fan_speed_presets`,defaults:f,lo:0,hi:100,unit:`%`}];function m(e,t,n,r){if(!e)return[...t];try{let t=JSON.parse(e);if(Array.isArray(t)&&t.length===3&&t.every(e=>Number.isInteger(e)&&e>=n&&e<=r))return t}catch{}return[...t]}function h(e,t){return[{label:`Off`,value:0},...e.map(e=>({label:`${e} ${t}`,value:e}))]}var g=e(n(),1),_=t();function v({value:e,titleKey:t=`printers.copyToClipboard`,copiedTitleKey:n=`printers.copied`,className:i=`ml-2 p-1 rounded hover:bg-bambu-dark-tertiary text-bambu-gray hover:text-white transition-colors`,iconClassName:s=`w-3.5 h-3.5`}){let{t:c}=r(),[l,u]=(0,g.useState)(!1);return(0,_.jsx)(`button`,{onClick:async()=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t);try{if(t.select(),!document.execCommand(`copy`))return}finally{document.body.removeChild(t)}}u(!0),setTimeout(()=>u(!1),2e3)}catch{}},className:i,title:c(l?n:t),children:l?(0,_.jsx)(a,{className:`${s} text-bambu-green`}):(0,_.jsx)(o,{className:s})})}export{l as a,m as c,f as i,c as l,u as n,p as o,d as r,h as s,v as t,s as u};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,w as i}from"./client-S4xOa3gM.js";import{t as a}from"./useQuery-CCrbj-1e.js";import{t as o}from"./loader-circle-BKXgelDY.js";import{t as s}from"./triangle-alert-D9uK6ZqX.js";import{Un as c,Vn as l,vt as u}from"./index-PPJXJ7Xk.js";var d=e(n(),1),f=t();function p(){let{t:e}=i(),{id:t}=c(),{mode:n}=u(),l=(0,d.useRef)(null),p=m(l);g(l);let{data:h,isLoading:_,error:v}=a({queryKey:[`external-link`,t],queryFn:()=>r.getExternalLink(Number(t)),enabled:!!t});return _?(0,f.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,f.jsx)(o,{className:`w-8 h-8 text-bambu-green animate-spin`})}):v||!h?(0,f.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-4 text-bambu-gray`,children:[(0,f.jsx)(s,{className:`w-12 h-12`}),(0,f.jsx)(`p`,{children:e(`common.linkNotFound`)})]}):(0,f.jsx)(`iframe`,{ref:l,src:h.url,onLoad:p,className:`h-full w-full border-0`,style:{colorScheme:n},title:h.name,sandbox:`allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox`})}function m(e){let{resolvedMode:t,darkStyle:n,darkBackground:r,darkAccent:i,lightStyle:a,lightBackground:o,lightAccent:s}=u(),c=t===`dark`,l=c?n:a,f=c?r:o,p=c?i:s,m=(0,d.useCallback)(()=>{let n=e.current;if(!n?.contentWindow)return;let r;try{r=new URL(n.src).origin}catch{return}n.contentWindow.postMessage({type:`bambuddy:theme`,mode:t,style:l,background:f,accent:p,canNavigate:!0},r)},[e,t,l,f,p]);return(0,d.useEffect)(()=>m(),[m]),(0,d.useEffect)(()=>{let t=t=>{t.source===e.current?.contentWindow&&t.data?.type===`bambuddy:theme-request`&&m()};return window.addEventListener(`message`,t),()=>window.removeEventListener(`message`,t)},[e,m]),m}var h=512;function g(e){let t=l();(0,d.useEffect)(()=>{let n=n=>{let r=e.current;if(!r?.contentWindow||n.source!==r.contentWindow||n.data?.type!==`bambuddy:navigate`)return;let i;try{i=new URL(r.src).origin}catch{return}if(n.origin!==i)return;let a=_(n.data.path);a!==null&&t(a)};return window.addEventListener(`message`,n),()=>window.removeEventListener(`message`,n)},[e,t])}function _(e){if(typeof e!=`string`||e.length>h||!e.startsWith(`/`)||e.startsWith(`//`)||e.includes(`\\`))return null;let t;try{t=new URL(e,window.location.origin)}catch{return null}return t.origin===window.location.origin?t.pathname+t.search+t.hash:null}export{p as ExternalLinkPage};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,w as i}from"./client-C3LdD0iY.js";import{t as a}from"./useQuery-BSYE6Prb.js";import{t as o}from"./loader-circle-CbaPxZRP.js";import{t as s}from"./triangle-alert-BUlaDyuA.js";import{Un as c,Vn as l,vt as u}from"./index-DEbGNNhA.js";var d=e(n(),1),f=t();function p(){let{t:e}=i(),{id:t}=c(),{mode:n}=u(),l=(0,d.useRef)(null),p=m(l);g(l);let{data:h,isLoading:_,error:v}=a({queryKey:[`external-link`,t],queryFn:()=>r.getExternalLink(Number(t)),enabled:!!t});return _?(0,f.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,f.jsx)(o,{className:`w-8 h-8 text-bambu-green animate-spin`})}):v||!h?(0,f.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-4 text-bambu-gray`,children:[(0,f.jsx)(s,{className:`w-12 h-12`}),(0,f.jsx)(`p`,{children:e(`common.linkNotFound`)})]}):(0,f.jsx)(`iframe`,{ref:l,src:h.url,onLoad:p,className:`h-full w-full border-0`,style:{colorScheme:n},title:h.name,sandbox:`allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox`})}function m(e){let{resolvedMode:t,darkStyle:n,darkBackground:r,darkAccent:i,lightStyle:a,lightBackground:o,lightAccent:s}=u(),c=t===`dark`,l=c?n:a,f=c?r:o,p=c?i:s,m=(0,d.useCallback)(()=>{let n=e.current;if(!n?.contentWindow)return;let r;try{r=new URL(n.src).origin}catch{return}n.contentWindow.postMessage({type:`bambuddy:theme`,mode:t,style:l,background:f,accent:p,canNavigate:!0},r)},[e,t,l,f,p]);return(0,d.useEffect)(()=>m(),[m]),(0,d.useEffect)(()=>{let t=t=>{t.source===e.current?.contentWindow&&t.data?.type===`bambuddy:theme-request`&&m()};return window.addEventListener(`message`,t),()=>window.removeEventListener(`message`,t)},[e,m]),m}var h=512;function g(e){let t=l();(0,d.useEffect)(()=>{let n=n=>{let r=e.current;if(!r?.contentWindow||n.source!==r.contentWindow||n.data?.type!==`bambuddy:navigate`)return;let i;try{i=new URL(r.src).origin}catch{return}if(n.origin!==i)return;let a=_(n.data.path);a!==null&&t(a)};return window.addEventListener(`message`,n),()=>window.removeEventListener(`message`,n)},[e,t])}function _(e){if(typeof e!=`string`||e.length>h||!e.startsWith(`/`)||e.startsWith(`//`)||e.includes(`\\`))return null;let t;try{t=new URL(e,window.location.origin)}catch{return null}return t.origin===window.location.origin?t.pathname+t.search+t.hash:null}export{p as ExternalLinkPage};
|
||||
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,w as i}from"./client-S4xOa3gM.js";import{t as a}from"./useQuery-CCrbj-1e.js";import{t as o}from"./arrow-left-CJE7AWqE.js";import{t as s}from"./GcodeToolpathViewer-DkkwF32o.js";import{Vn as c,Wn as l}from"./index-PPJXJ7Xk.js";var u=e(n(),1),d=t();function f(){let e=c(),[t,n]=l(),{t:f}=i(),p=t.get(`archive`),m=t.get(`library_file`),h=t.get(`plate`),g=a({queryKey:[`gcode-viewer-archive-colors`,p],queryFn:()=>r.getArchiveCapabilities(Number(p)),enabled:!!p,staleTime:5*6e4,retry:!1}),_=a({queryKey:[`gcode-viewer-library-colors`,m],queryFn:()=>r.getLibraryFilePlates(Number(m)),enabled:!!m,staleTime:5*6e4,retry:!1}),v=a({queryKey:[`gcode-viewer-archive-plates`,p],queryFn:()=>r.getArchivePlates(Number(p)),enabled:!!p,staleTime:5*6e4,retry:!1}),y=(0,u.useMemo)(()=>(p?v.data?.plates:_.data?.plates)??[],[p,v.data,_.data]),b=(0,u.useMemo)(()=>h?Number(h):y.length===0?null:Math.min(...y.map(e=>e.index)),[h,y]),x=e=>{if(e===b)return;let r=new URLSearchParams(t);r.set(`plate`,String(e)),n(r,{replace:!0})},S=(0,u.useMemo)(()=>{if(p)return g.data?.filament_colors;let e=y.find(e=>e.index===b)||y[0];if(!e?.filaments?.length)return;let t=[];for(let n of e.filaments){let e=Math.max(0,(n.slot_id??1)-1);n.color&&(t[e]=n.color)}return t.length>0?t:void 0},[p,g.data,y,b]),C=(0,u.useMemo)(()=>{let e=e=>h?`${e}?plate=${encodeURIComponent(h)}`:e;return p?e(r.getArchiveGcode(Number(p))):m?e(r.getLibraryFileGcodeUrl(Number(m))):null},[p,m,h]),w=()=>{window.history.length>1?e(-1):e(p?`/archives`:`/files`)},T=p?f(`gcodeViewer.backToArchives`,`Back to Archives`):f(`gcodeViewer.backToFiles`,`Back to File Manager`);return(0,d.jsxs)(`div`,{className:`flex flex-col min-h-[calc(100vh-64px)] lg:h-screen`,children:[(0,d.jsxs)(`div`,{className:`flex-shrink-0 px-4 py-2 border-b border-bambu-dark-tertiary flex flex-wrap items-center gap-x-4 gap-y-2`,children:[(0,d.jsxs)(`button`,{type:`button`,onClick:w,className:`inline-flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors`,children:[(0,d.jsx)(o,{className:`w-4 h-4`}),T]}),y.length>1&&(0,d.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,d.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:f(`gcodeViewer.plates`,`Plates`)}),y.map(e=>(0,d.jsx)(`button`,{type:`button`,onClick:()=>x(e.index),"aria-pressed":e.index===b,title:e.name??void 0,className:`px-2 py-0.5 rounded text-xs transition-colors ${e.index===b?`bg-bambu-green text-white`:`bg-bambu-dark-tertiary text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white`}`,children:f(`gcodeViewer.plateN`,`Plate {{n}}`,{n:e.index})},e.index))]})]}),C?(0,d.jsx)(s,{gcodeUrl:C,filamentColors:S,className:`flex-1 min-h-0`}):(0,d.jsx)(`div`,{className:`flex-1 flex items-center justify-center text-sm text-bambu-gray`,children:f(`gcodeViewer.noSource`,`No file was given to preview.`)})]})}export{f as GCodeViewerPage};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,w as i}from"./client-C3LdD0iY.js";import{t as a}from"./useQuery-BSYE6Prb.js";import{t as o}from"./arrow-left-CSvb6Y3A.js";import{t as s}from"./GcodeToolpathViewer-N4Eow1eU.js";import{Vn as c,Wn as l}from"./index-DEbGNNhA.js";var u=e(n(),1),d=t();function f(){let e=c(),[t,n]=l(),{t:f}=i(),p=t.get(`archive`),m=t.get(`library_file`),h=t.get(`plate`),g=a({queryKey:[`gcode-viewer-archive-colors`,p],queryFn:()=>r.getArchiveCapabilities(Number(p)),enabled:!!p,staleTime:5*6e4,retry:!1}),_=a({queryKey:[`gcode-viewer-library-colors`,m],queryFn:()=>r.getLibraryFilePlates(Number(m)),enabled:!!m,staleTime:5*6e4,retry:!1}),v=a({queryKey:[`gcode-viewer-archive-plates`,p],queryFn:()=>r.getArchivePlates(Number(p)),enabled:!!p,staleTime:5*6e4,retry:!1}),y=(0,u.useMemo)(()=>(p?v.data?.plates:_.data?.plates)??[],[p,v.data,_.data]),b=(0,u.useMemo)(()=>h?Number(h):y.length===0?null:Math.min(...y.map(e=>e.index)),[h,y]),x=e=>{if(e===b)return;let r=new URLSearchParams(t);r.set(`plate`,String(e)),n(r,{replace:!0})},S=(0,u.useMemo)(()=>{if(p)return g.data?.filament_colors;let e=y.find(e=>e.index===b)||y[0];if(!e?.filaments?.length)return;let t=[];for(let n of e.filaments){let e=Math.max(0,(n.slot_id??1)-1);n.color&&(t[e]=n.color)}return t.length>0?t:void 0},[p,g.data,y,b]),C=(0,u.useMemo)(()=>{let e=e=>h?`${e}?plate=${encodeURIComponent(h)}`:e;return p?e(r.getArchiveGcode(Number(p))):m?e(r.getLibraryFileGcodeUrl(Number(m))):null},[p,m,h]),w=()=>{window.history.length>1?e(-1):e(p?`/archives`:`/files`)},T=p?f(`gcodeViewer.backToArchives`,`Back to Archives`):f(`gcodeViewer.backToFiles`,`Back to File Manager`);return(0,d.jsxs)(`div`,{className:`flex flex-col min-h-[calc(100vh-64px)] lg:h-screen`,children:[(0,d.jsxs)(`div`,{className:`flex-shrink-0 px-4 py-2 border-b border-bambu-dark-tertiary flex flex-wrap items-center gap-x-4 gap-y-2`,children:[(0,d.jsxs)(`button`,{type:`button`,onClick:w,className:`inline-flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors`,children:[(0,d.jsx)(o,{className:`w-4 h-4`}),T]}),y.length>1&&(0,d.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,d.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:f(`gcodeViewer.plates`,`Plates`)}),y.map(e=>(0,d.jsx)(`button`,{type:`button`,onClick:()=>x(e.index),"aria-pressed":e.index===b,title:e.name??void 0,className:`px-2 py-0.5 rounded text-xs transition-colors ${e.index===b?`bg-bambu-green text-white`:`bg-bambu-dark-tertiary text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white`}`,children:f(`gcodeViewer.plateN`,`Plate {{n}}`,{n:e.index})},e.index))]})]}),C?(0,d.jsx)(s,{gcodeUrl:C,filamentColors:S,className:`flex-1 min-h-0`}):(0,d.jsx)(`div`,{className:`flex-1 flex items-center justify-center text-sm text-bambu-gray`,children:f(`gcodeViewer.noSource`,`No file was given to preview.`)})]})}export{f as GCodeViewerPage};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,l as i,w as a}from"./client-S4xOa3gM.js";import{t as o}from"./loader-circle-BKXgelDY.js";import{n as s,t as c}from"./zoom-out-BQgmQEI6.js";import{t as l}from"./file-DDkFXH-b.js";import{Gt as u,un as d}from"./index-PPJXJ7Xk.js";import{n as f,r as p,t as m}from"./usePreviewFullscreen-CdnRN5TO.js";var h=e(n(),1),g=t(),_=.4,v=8,y=1.25,b=30,x=Math.log(y)/b,S=e=>Math.min(v,Math.max(_,e)),C={x:0,y:0};function w(e){return e.deltaMode===1?e.deltaY*16:e.deltaMode===2?e.deltaY*100:e.deltaY}function T({libraryFileId:e,filename:t,fileSize:n,onClose:_}){let{t:v}=a(),T=m(),{isFullscreen:E,toggleFullscreen:D}=T,O=(0,h.useRef)(null),k=(0,h.useRef)(null),[A,j]=(0,h.useState)(null),[M,N]=(0,h.useState)(!1),[P,F]=(0,h.useState)(null),[I,L]=(0,h.useState)(1),[R,z]=(0,h.useState)(C),[B,V]=(0,h.useState)(!1),H=(0,h.useRef)(1),U=(0,h.useRef)(C),W=(0,h.useRef)(new Map),G=(0,h.useRef)(null),K=(0,h.useCallback)((e,t)=>{let n=O.current,r=k.current;if(!n||!r)return e;let i=Math.max(0,(r.offsetWidth*t-n.clientWidth)/2),a=Math.max(0,(r.offsetHeight*t-n.clientHeight)/2);return{x:Math.min(i,Math.max(-i,e.x)),y:Math.min(a,Math.max(-a,e.y))}},[]),q=(0,h.useCallback)((e,t)=>{H.current=e,U.current=t,L(e),z(t)},[]),J=(0,h.useCallback)((e,t,n)=>{let r=H.current,i=S(r*e);if(i===r)return;let a=O.current,o=U.current,s={x:o.x*(i/r),y:o.y*(i/r)};if(a){let e=a.getBoundingClientRect(),c=(t??e.left+e.width/2)-(e.left+e.width/2),l=(n??e.top+e.height/2)-(e.top+e.height/2),u=i/r;s={x:c-(c-o.x)*u,y:l-(l-o.y)*u}}q(i,K(s,i))},[K,q]),Y=(0,h.useCallback)(()=>q(1,C),[q]);(0,h.useEffect)(()=>{let t=!1,a=null;if(j(null),N(!1),F(null),q(1,C),n>52428800){F(v(`fileManager.preview.tooLarge`,{size:l(n)}));return}let o={},s=i();return s&&(o.Authorization=`Bearer ${s}`),(async()=>{let n=await fetch(r.getLibraryFileDownloadUrl(e),{headers:o});if(!n.ok)throw Error(`HTTP ${n.status}`);let i=await n.blob();t||(a=URL.createObjectURL(i),j(a))})().catch(e=>{console.error(`[image-preview] load failed`,e),t||F(v(`fileManager.preview.error`))}),()=>{t=!0,a&&URL.revokeObjectURL(a)}},[e,n,v,q]),(0,h.useEffect)(()=>{let e=e=>{e.ctrlKey||e.metaKey||e.altKey||(e.key===`+`||e.key===`=`?(e.preventDefault(),J(y)):e.key===`-`?(e.preventDefault(),J(1/y)):e.key===`0`&&(e.preventDefault(),Y()))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[Y,J]),(0,h.useEffect)(()=>{let e=O.current;if(!e)return;let t=e=>{e.preventDefault();let t=Math.max(-30,Math.min(b,w(e)));J(Math.exp(-t*x),e.clientX,e.clientY)};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[J,A]);let X=e=>{W.current.set(e.pointerId,{x:e.clientX,y:e.clientY}),G.current=null,W.current.size===1&&H.current>1&&(e.currentTarget.setPointerCapture(e.pointerId),V(!0))},Z=e=>{W.current.delete(e.pointerId),G.current=null,W.current.size===0&&V(!1)},Q=e=>{let t=W.current,n=t.get(e.pointerId);if(!n)return;if(e.pointerType===`mouse`&&e.buttons===0){Z(e);return}if(t.set(e.pointerId,{x:e.clientX,y:e.clientY}),t.size===1){if(H.current<=1)return;let t={x:U.current.x+(e.clientX-n.x),y:U.current.y+(e.clientY-n.y)};q(H.current,K(t,H.current));return}if(t.size!==2)return;let[r,i]=Array.from(t.values()),a=Math.hypot(r.x-i.x,r.y-i.y),o=G.current;G.current=a,o!=null&&o>0&&a>0&&J(a/o,(r.x+i.x)/2,(r.y+i.y)/2)},$=I>1;return(0,g.jsx)(f,{title:t,fullscreen:T,onClose:_,icon:(0,g.jsx)(d,{className:`w-5 h-5 text-bambu-green flex-shrink-0`}),actions:A?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`button`,{onClick:()=>J(1/y),className:p,"aria-label":v(`fileManager.preview.zoomOut`),children:(0,g.jsx)(c,{className:`w-4 h-4`})}),(0,g.jsx)(`button`,{onClick:()=>J(y),className:p,"aria-label":v(`fileManager.preview.zoomIn`),children:(0,g.jsx)(s,{className:`w-4 h-4`})}),(0,g.jsx)(`button`,{onClick:Y,className:p,"aria-label":v(`fileManager.preview.resetZoom`),children:(0,g.jsx)(u,{className:`w-4 h-4`})})]}):void 0,children:(0,g.jsx)(`div`,{ref:O,"data-testid":`image-preview-content`,className:`relative flex-1 min-h-0 overflow-hidden bg-bambu-dark flex items-center justify-center touch-none ${E?``:`rounded-b-lg`} ${$?B?`cursor-grabbing`:`cursor-grab`:``}`,onDoubleClick:D,onPointerDown:X,onPointerMove:Q,onPointerUp:Z,onPointerCancel:Z,onPointerLeave:Z,children:P?(0,g.jsx)(`p`,{className:`text-bambu-gray text-center p-6`,children:P}):(0,g.jsxs)(g.Fragment,{children:[A&&(0,g.jsx)(`img`,{ref:k,src:A,alt:t,draggable:!1,onLoad:()=>N(!0),onError:()=>F(v(`fileManager.preview.error`)),style:{transform:`translate(${R.x}px, ${R.y}px) scale(${I})`},className:`max-w-full max-h-full object-contain select-none`}),!M&&(0,g.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center pointer-events-none`,children:(0,g.jsx)(o,{className:`w-8 h-8 text-bambu-green animate-spin`})})]})})})}export{T as ImagePreviewModal};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r,l as i,w as a}from"./client-C3LdD0iY.js";import{t as o}from"./loader-circle-CbaPxZRP.js";import{n as s,t as c}from"./zoom-out-CpxEPaFQ.js";import{t as l}from"./file-DDkFXH-b.js";import{Gt as u,un as d}from"./index-DEbGNNhA.js";import{n as f,r as p,t as m}from"./usePreviewFullscreen-Bd6UWAwo.js";var h=e(n(),1),g=t(),_=.4,v=8,y=1.25,b=30,x=Math.log(y)/b,S=e=>Math.min(v,Math.max(_,e)),C={x:0,y:0};function w(e){return e.deltaMode===1?e.deltaY*16:e.deltaMode===2?e.deltaY*100:e.deltaY}function T({libraryFileId:e,filename:t,fileSize:n,onClose:_}){let{t:v}=a(),T=m(),{isFullscreen:E,toggleFullscreen:D}=T,O=(0,h.useRef)(null),k=(0,h.useRef)(null),[A,j]=(0,h.useState)(null),[M,N]=(0,h.useState)(!1),[P,F]=(0,h.useState)(null),[I,L]=(0,h.useState)(1),[R,z]=(0,h.useState)(C),[B,V]=(0,h.useState)(!1),H=(0,h.useRef)(1),U=(0,h.useRef)(C),W=(0,h.useRef)(new Map),G=(0,h.useRef)(null),K=(0,h.useCallback)((e,t)=>{let n=O.current,r=k.current;if(!n||!r)return e;let i=Math.max(0,(r.offsetWidth*t-n.clientWidth)/2),a=Math.max(0,(r.offsetHeight*t-n.clientHeight)/2);return{x:Math.min(i,Math.max(-i,e.x)),y:Math.min(a,Math.max(-a,e.y))}},[]),q=(0,h.useCallback)((e,t)=>{H.current=e,U.current=t,L(e),z(t)},[]),J=(0,h.useCallback)((e,t,n)=>{let r=H.current,i=S(r*e);if(i===r)return;let a=O.current,o=U.current,s={x:o.x*(i/r),y:o.y*(i/r)};if(a){let e=a.getBoundingClientRect(),c=(t??e.left+e.width/2)-(e.left+e.width/2),l=(n??e.top+e.height/2)-(e.top+e.height/2),u=i/r;s={x:c-(c-o.x)*u,y:l-(l-o.y)*u}}q(i,K(s,i))},[K,q]),Y=(0,h.useCallback)(()=>q(1,C),[q]);(0,h.useEffect)(()=>{let t=!1,a=null;if(j(null),N(!1),F(null),q(1,C),n>52428800){F(v(`fileManager.preview.tooLarge`,{size:l(n)}));return}let o={},s=i();return s&&(o.Authorization=`Bearer ${s}`),(async()=>{let n=await fetch(r.getLibraryFileDownloadUrl(e),{headers:o});if(!n.ok)throw Error(`HTTP ${n.status}`);let i=await n.blob();t||(a=URL.createObjectURL(i),j(a))})().catch(e=>{console.error(`[image-preview] load failed`,e),t||F(v(`fileManager.preview.error`))}),()=>{t=!0,a&&URL.revokeObjectURL(a)}},[e,n,v,q]),(0,h.useEffect)(()=>{let e=e=>{e.ctrlKey||e.metaKey||e.altKey||(e.key===`+`||e.key===`=`?(e.preventDefault(),J(y)):e.key===`-`?(e.preventDefault(),J(1/y)):e.key===`0`&&(e.preventDefault(),Y()))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[Y,J]),(0,h.useEffect)(()=>{let e=O.current;if(!e)return;let t=e=>{e.preventDefault();let t=Math.max(-30,Math.min(b,w(e)));J(Math.exp(-t*x),e.clientX,e.clientY)};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[J,A]);let X=e=>{W.current.set(e.pointerId,{x:e.clientX,y:e.clientY}),G.current=null,W.current.size===1&&H.current>1&&(e.currentTarget.setPointerCapture(e.pointerId),V(!0))},Z=e=>{W.current.delete(e.pointerId),G.current=null,W.current.size===0&&V(!1)},Q=e=>{let t=W.current,n=t.get(e.pointerId);if(!n)return;if(e.pointerType===`mouse`&&e.buttons===0){Z(e);return}if(t.set(e.pointerId,{x:e.clientX,y:e.clientY}),t.size===1){if(H.current<=1)return;let t={x:U.current.x+(e.clientX-n.x),y:U.current.y+(e.clientY-n.y)};q(H.current,K(t,H.current));return}if(t.size!==2)return;let[r,i]=Array.from(t.values()),a=Math.hypot(r.x-i.x,r.y-i.y),o=G.current;G.current=a,o!=null&&o>0&&a>0&&J(a/o,(r.x+i.x)/2,(r.y+i.y)/2)},$=I>1;return(0,g.jsx)(f,{title:t,fullscreen:T,onClose:_,icon:(0,g.jsx)(d,{className:`w-5 h-5 text-bambu-green flex-shrink-0`}),actions:A?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`button`,{onClick:()=>J(1/y),className:p,"aria-label":v(`fileManager.preview.zoomOut`),children:(0,g.jsx)(c,{className:`w-4 h-4`})}),(0,g.jsx)(`button`,{onClick:()=>J(y),className:p,"aria-label":v(`fileManager.preview.zoomIn`),children:(0,g.jsx)(s,{className:`w-4 h-4`})}),(0,g.jsx)(`button`,{onClick:Y,className:p,"aria-label":v(`fileManager.preview.resetZoom`),children:(0,g.jsx)(u,{className:`w-4 h-4`})})]}):void 0,children:(0,g.jsx)(`div`,{ref:O,"data-testid":`image-preview-content`,className:`relative flex-1 min-h-0 overflow-hidden bg-bambu-dark flex items-center justify-center touch-none ${E?``:`rounded-b-lg`} ${$?B?`cursor-grabbing`:`cursor-grab`:``}`,onDoubleClick:D,onPointerDown:X,onPointerMove:Q,onPointerUp:Z,onPointerCancel:Z,onPointerLeave:Z,children:P?(0,g.jsx)(`p`,{className:`text-bambu-gray text-center p-6`,children:P}):(0,g.jsxs)(g.Fragment,{children:[A&&(0,g.jsx)(`img`,{ref:k,src:A,alt:t,draggable:!1,onLoad:()=>N(!0),onError:()=>F(v(`fileManager.preview.error`)),style:{transform:`translate(${R.x}px, ${R.y}px) scale(${I})`},className:`max-w-full max-h-full object-contain select-none`}),!M&&(0,g.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center pointer-events-none`,children:(0,g.jsx)(o,{className:`w-8 h-8 text-bambu-green animate-spin`})})]})})})}export{T as ImagePreviewModal};
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r}from"./client-S4xOa3gM.js";var i=e(n(),1);function a(e,t=null,n=0){let[a,o]=(0,i.useState)(null);return(0,i.useEffect)(()=>{if(!e)return;let i=new AbortController,a;return r.getOverlayLogo(t,i.signal).then(e=>{i.signal.aborted||(e?(a=URL.createObjectURL(e),o({url:a,token:t,revision:n})):o(null))}).catch(()=>{i.signal.aborted||o(null)}),()=>{i.abort(),a&&URL.revokeObjectURL(a)}},[e,t,n]),e&&a?.token===t&&a.revision===n?a.url:null}var o={logo:!1,logoRevision:0,from:``,to:``};function s(e){return/^#[0-9a-f]{6}$/i.test(e)}function c(e,t){return e&&t&&s(e)&&s(t)?`linear-gradient(to right, ${e}, ${t})`:void 0}function l(e){if(e)return{backgroundImage:e,backgroundClip:`text`,WebkitBackgroundClip:`text`,color:`transparent`,WebkitTextFillColor:`transparent`}}var u={landscape:{width:1920,height:1080},portrait:{width:1080,height:1920}},d=t();function f({layout:e,preview:t=!1,children:n}){let r=(0,i.useRef)(null),[a,o]=(0,i.useState)(0),{width:s,height:c}=u[e];(0,i.useLayoutEffect)(()=>{let e=r.current;if(!e)return;let t=()=>o(Math.min(e.clientWidth/s,e.clientHeight/c));if(t(),typeof ResizeObserver>`u`)return window.addEventListener(`resize`,t),()=>window.removeEventListener(`resize`,t);let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[s,c]);let l={width:s,height:c,"--overlay-vmin":`10.8px`,"--overlay-height":`${c}px`,position:`absolute`,top:`50%`,left:`50%`,transform:`translate(-50%, -50%) scale(${a})`,transformOrigin:`center`};return(0,d.jsx)(`div`,{ref:r,className:t?`relative w-full overflow-hidden`:`fixed inset-0 overflow-hidden`,style:t?{aspectRatio:`${s} / ${c}`}:void 0,children:(0,d.jsx)(`div`,{style:l,children:n})})}export{c as a,s as i,u as n,l as o,o as r,a as s,f as t};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,a as r}from"./client-C3LdD0iY.js";var i=e(n(),1);function a(e,t=null,n=0){let[a,o]=(0,i.useState)(null);return(0,i.useEffect)(()=>{if(!e)return;let i=new AbortController,a;return r.getOverlayLogo(t,i.signal).then(e=>{i.signal.aborted||(e?(a=URL.createObjectURL(e),o({url:a,token:t,revision:n})):o(null))}).catch(()=>{i.signal.aborted||o(null)}),()=>{i.abort(),a&&URL.revokeObjectURL(a)}},[e,t,n]),e&&a?.token===t&&a.revision===n?a.url:null}var o={logo:!1,logoRevision:0,from:``,to:``};function s(e){return/^#[0-9a-f]{6}$/i.test(e)}function c(e,t){return e&&t&&s(e)&&s(t)?`linear-gradient(to right, ${e}, ${t})`:void 0}function l(e){if(e)return{backgroundImage:e,backgroundClip:`text`,WebkitBackgroundClip:`text`,color:`transparent`,WebkitTextFillColor:`transparent`}}var u={landscape:{width:1920,height:1080},portrait:{width:1080,height:1920}},d=t();function f({layout:e,preview:t=!1,children:n}){let r=(0,i.useRef)(null),[a,o]=(0,i.useState)(0),{width:s,height:c}=u[e];(0,i.useLayoutEffect)(()=>{let e=r.current;if(!e)return;let t=()=>o(Math.min(e.clientWidth/s,e.clientHeight/c));if(t(),typeof ResizeObserver>`u`)return window.addEventListener(`resize`,t),()=>window.removeEventListener(`resize`,t);let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[s,c]);let l={width:s,height:c,"--overlay-vmin":`10.8px`,"--overlay-height":`${c}px`,position:`absolute`,top:`50%`,left:`50%`,transform:`translate(-50%, -50%) scale(${a})`,transformOrigin:`center`};return(0,d.jsx)(`div`,{ref:r,className:t?`relative w-full overflow-hidden`:`fixed inset-0 overflow-hidden`,style:t?{aspectRatio:`${s} / ${c}`}:void 0,children:(0,d.jsx)(`div`,{style:l,children:n})})}export{c as a,s as i,u as n,l as o,o as r,a as s,f as t};
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n}from"./client-S4xOa3gM.js";import{n as r}from"./filamentSwatchHelpers-D3oXQSGk.js";import{t as i}from"./spoolPaint-CrvpHqdD.js";var a=e(n(),1),o=t();function s({spool:e,inset:t,size:n,border:i}){let s=n>=80?`card`:`preview`,c=(0,a.useMemo)(()=>r({effectSize:s,rgba:e.rgba,extraColors:e.extra_colors,effectType:e.effect_type,subtype:e.subtype}),[s,e.rgba,e.extra_colors,e.effect_type,e.subtype]),l=`${t*100}%`;return(0,o.jsx)(`div`,{"data-testid":`spool-paint`,className:`absolute rounded-full box-border`,style:{top:l,left:l,right:l,bottom:l,...c,backgroundPosition:`center`,border:i}})}function c({inset:e}){let t=`${e*100}%`;return(0,o.jsx)(`div`,{"data-testid":`spool-shade`,className:`absolute rounded-full`,style:{top:t,left:t,right:t,bottom:t,backgroundColor:`rgba(0, 0, 0, 0.15)`}})}function l({color:e,isEmpty:t,size:n=32,spool:r}){return t?(0,o.jsx)(`div`,{className:`rounded-full border-2 border-dashed border-zinc-500 flex items-center justify-center`,style:{width:n,height:n},children:(0,o.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-zinc-600`})}):i(r)?(0,o.jsxs)(`div`,{className:`relative shrink-0`,style:{width:n,height:n},children:[(0,o.jsx)(s,{spool:r,size:n,inset:2/32,border:`${1.5*n/32}px solid rgba(255, 255, 255, 0.7)`}),(0,o.jsx)(c,{inset:5/32})]}):(0,o.jsxs)(`svg`,{width:n,height:n,viewBox:`0 0 32 32`,children:[(0,o.jsx)(`circle`,{cx:`16`,cy:`16`,r:`14`,fill:e,stroke:`white`,strokeWidth:`1.5`,strokeOpacity:`0.7`}),(0,o.jsx)(`circle`,{cx:`16`,cy:`16`,r:`11`,fill:e,style:{filter:`brightness(0.85)`}})]})}export{s as n,c as r,l as t};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n}from"./client-C3LdD0iY.js";import{n as r}from"./filamentSwatchHelpers-D3oXQSGk.js";import{t as i}from"./spoolPaint-CrvpHqdD.js";var a=e(n(),1),o=t();function s({spool:e,inset:t,size:n,border:i}){let s=n>=80?`card`:`preview`,c=(0,a.useMemo)(()=>r({effectSize:s,rgba:e.rgba,extraColors:e.extra_colors,effectType:e.effect_type,subtype:e.subtype}),[s,e.rgba,e.extra_colors,e.effect_type,e.subtype]),l=`${t*100}%`;return(0,o.jsx)(`div`,{"data-testid":`spool-paint`,className:`absolute rounded-full box-border`,style:{top:l,left:l,right:l,bottom:l,...c,backgroundPosition:`center`,border:i}})}function c({inset:e}){let t=`${e*100}%`;return(0,o.jsx)(`div`,{"data-testid":`spool-shade`,className:`absolute rounded-full`,style:{top:t,left:t,right:t,bottom:t,backgroundColor:`rgba(0, 0, 0, 0.15)`}})}function l({color:e,isEmpty:t,size:n=32,spool:r}){return t?(0,o.jsx)(`div`,{className:`rounded-full border-2 border-dashed border-zinc-500 flex items-center justify-center`,style:{width:n,height:n},children:(0,o.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-zinc-600`})}):i(r)?(0,o.jsxs)(`div`,{className:`relative shrink-0`,style:{width:n,height:n},children:[(0,o.jsx)(s,{spool:r,size:n,inset:2/32,border:`${1.5*n/32}px solid rgba(255, 255, 255, 0.7)`}),(0,o.jsx)(c,{inset:5/32})]}):(0,o.jsxs)(`svg`,{width:n,height:n,viewBox:`0 0 32 32`,children:[(0,o.jsx)(`circle`,{cx:`16`,cy:`16`,r:`14`,fill:e,stroke:`white`,strokeWidth:`1.5`,strokeOpacity:`0.7`}),(0,o.jsx)(`circle`,{cx:`16`,cy:`16`,r:`11`,fill:e,style:{filter:`brightness(0.85)`}})]})}export{s as n,c as r,l as t};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{C as e}from"./client-S4xOa3gM.js";var t=e();function n({checked:e,onChange:n,disabled:r}){return(0,t.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":e,disabled:r,onClick:t=>{t.preventDefault(),t.stopPropagation(),r||n(!e)},className:`relative inline-flex w-11 h-7 md:w-9 md:h-5 rounded-full transition-colors flex-shrink-0 focus:outline-none focus:ring-2 focus:ring-bambu-green focus:ring-offset-2 focus:ring-offset-bambu-dark ${r?`bg-bambu-dark-tertiary/50 cursor-not-allowed opacity-50`:e?`bg-bambu-green cursor-pointer`:`bg-bambu-dark-tertiary cursor-pointer hover:bg-bambu-dark-tertiary/80`}`,children:(0,t.jsx)(`span`,{className:`pointer-events-none absolute top-[3px] md:top-[2px] left-[3px] md:left-[2px] w-5 h-5 md:w-4 md:h-4 bg-white rounded-full shadow transition-transform duration-200 ease-in-out ${e?`translate-x-4`:`translate-x-0`}`})})}export{n as t};
|
||||
import{C as e}from"./client-C3LdD0iY.js";var t=e();function n({checked:e,onChange:n,disabled:r}){return(0,t.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":e,disabled:r,onClick:t=>{t.preventDefault(),t.stopPropagation(),r||n(!e)},className:`relative inline-flex w-11 h-7 md:w-9 md:h-5 rounded-full transition-colors flex-shrink-0 focus:outline-none focus:ring-2 focus:ring-bambu-green focus:ring-offset-2 focus:ring-offset-bambu-dark ${r?`bg-bambu-dark-tertiary/50 cursor-not-allowed opacity-50`:e?`bg-bambu-green cursor-pointer`:`bg-bambu-dark-tertiary cursor-pointer hover:bg-bambu-dark-tertiary/80`}`,children:(0,t.jsx)(`span`,{className:`pointer-events-none absolute top-[3px] md:top-[2px] left-[3px] md:left-[2px] w-5 h-5 md:w-4 md:h-4 bg-white rounded-full shadow transition-transform duration-200 ease-in-out ${e?`translate-x-4`:`translate-x-0`}`})})}export{n as t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`arrow-up-down`,[[`path`,{d:`m21 16-4 4-4-4`,key:`f6ql7i`}],[`path`,{d:`M17 20V4`,key:`1ejh1v`}],[`path`,{d:`m3 8 4-4 4 4`,key:`11wl7u`}],[`path`,{d:`M7 4v16`,key:`1glfcx`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`arrow-up-down`,[[`path`,{d:`m21 16-4 4-4-4`,key:`f6ql7i`}],[`path`,{d:`M17 20V4`,key:`1ejh1v`}],[`path`,{d:`m3 8 4-4 4 4`,key:`11wl7u`}],[`path`,{d:`M7 4v16`,key:`1glfcx`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`box`,[[`path`,{d:`M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z`,key:`hh9hay`}],[`path`,{d:`m3.3 7 8.7 5 8.7-5`,key:`g66t2b`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`box`,[[`path`,{d:`M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z`,key:`hh9hay`}],[`path`,{d:`m3.3 7 8.7 5 8.7-5`,key:`g66t2b`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`briefcase`,[[`path`,{d:`M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16`,key:`jecpp`}],[`rect`,{width:`20`,height:`14`,x:`2`,y:`6`,rx:`2`,key:`i6l2r4`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`briefcase`,[[`path`,{d:`M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16`,key:`jecpp`}],[`rect`,{width:`20`,height:`14`,x:`2`,y:`6`,rx:`2`,key:`i6l2r4`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`calendar`,[[`path`,{d:`M8 2v4`,key:`1cmpym`}],[`path`,{d:`M16 2v4`,key:`4m81vk`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`4`,rx:`2`,key:`1hopcy`}],[`path`,{d:`M3 10h18`,key:`8toen8`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`calendar`,[[`path`,{d:`M8 2v4`,key:`1cmpym`}],[`path`,{d:`M16 2v4`,key:`4m81vk`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`4`,rx:`2`,key:`1hopcy`}],[`path`,{d:`M3 10h18`,key:`8toen8`}]]);export{t};
|
||||
@@ -0,0 +1 @@
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]);export{t};
|
||||
@@ -1 +0,0 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`chevrons-left`,[[`path`,{d:`m11 17-5-5 5-5`,key:`13zhaf`}],[`path`,{d:`m18 17-5-5 5-5`,key:`h8a8et`}]]),n=e(`chevrons-right`,[[`path`,{d:`m6 17 5-5-5-5`,key:`xnjwq`}],[`path`,{d:`m13 17 5-5-5-5`,key:`17xmmf`}]]);export{t as n,n as t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`chevrons-left`,[[`path`,{d:`m11 17-5-5 5-5`,key:`13zhaf`}],[`path`,{d:`m18 17-5-5 5-5`,key:`h8a8et`}]]),n=e(`chevrons-right`,[[`path`,{d:`m6 17 5-5-5-5`,key:`xnjwq`}],[`path`,{d:`m13 17 5-5-5-5`,key:`17xmmf`}]]);export{t as n,n as t};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`cloud-off`,[[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M5.782 5.782A7 7 0 0 0 9 19h8.5a4.5 4.5 0 0 0 1.307-.193`,key:`yfwify`}],[`path`,{d:`M21.532 16.5A4.5 4.5 0 0 0 17.5 10h-1.79A7.008 7.008 0 0 0 10 5.07`,key:`jlfiyv`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`cloud-off`,[[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M5.782 5.782A7 7 0 0 0 9 19h8.5a4.5 4.5 0 0 0 1.307-.193`,key:`yfwify`}],[`path`,{d:`M21.532 16.5A4.5 4.5 0 0 0 17.5 10h-1.79A7.008 7.008 0 0 0 10 5.07`,key:`jlfiyv`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`cog`,[[`path`,{d:`M11 10.27 7 3.34`,key:`16pf9h`}],[`path`,{d:`m11 13.73-4 6.93`,key:`794ttg`}],[`path`,{d:`M12 22v-2`,key:`1osdcq`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M14 12h8`,key:`4f43i9`}],[`path`,{d:`m17 20.66-1-1.73`,key:`eq3orb`}],[`path`,{d:`m17 3.34-1 1.73`,key:`2wel8s`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`m20.66 17-1.73-1`,key:`sg0v6f`}],[`path`,{d:`m20.66 7-1.73 1`,key:`1ow05n`}],[`path`,{d:`m3.34 17 1.73-1`,key:`nuk764`}],[`path`,{d:`m3.34 7 1.73 1`,key:`1ulond`}],[`circle`,{cx:`12`,cy:`12`,r:`2`,key:`1c9p78`}],[`circle`,{cx:`12`,cy:`12`,r:`8`,key:`46899m`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`cog`,[[`path`,{d:`M11 10.27 7 3.34`,key:`16pf9h`}],[`path`,{d:`m11 13.73-4 6.93`,key:`794ttg`}],[`path`,{d:`M12 22v-2`,key:`1osdcq`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M14 12h8`,key:`4f43i9`}],[`path`,{d:`m17 20.66-1-1.73`,key:`eq3orb`}],[`path`,{d:`m17 3.34-1 1.73`,key:`2wel8s`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`m20.66 17-1.73-1`,key:`sg0v6f`}],[`path`,{d:`m20.66 7-1.73 1`,key:`1ow05n`}],[`path`,{d:`m3.34 17 1.73-1`,key:`nuk764`}],[`path`,{d:`m3.34 7 1.73 1`,key:`1ulond`}],[`circle`,{cx:`12`,cy:`12`,r:`2`,key:`1c9p78`}],[`circle`,{cx:`12`,cy:`12`,r:`8`,key:`46899m`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`coins`,[[`circle`,{cx:`8`,cy:`8`,r:`6`,key:`3yglwk`}],[`path`,{d:`M18.09 10.37A6 6 0 1 1 10.34 18`,key:`t5s6rm`}],[`path`,{d:`M7 6h1v4`,key:`1obek4`}],[`path`,{d:`m16.71 13.88.7.71-2.82 2.82`,key:`1rbuyh`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`coins`,[[`circle`,{cx:`8`,cy:`8`,r:`6`,key:`3yglwk`}],[`path`,{d:`M18.09 10.37A6 6 0 1 1 10.34 18`,key:`t5s6rm`}],[`path`,{d:`M7 6h1v4`,key:`1obek4`}],[`path`,{d:`m16.71 13.88.7.71-2.82 2.82`,key:`1rbuyh`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`columns-2`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M12 3v18`,key:`108xh3`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`columns-2`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M12 3v18`,key:`108xh3`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`cpu`,[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`cpu`,[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]);export{t};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{D as t}from"./client-S4xOa3gM.js";var n=e(t()),r=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),i=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),a=e=>{let t=i(e);return t.charAt(0).toUpperCase()+t.slice(1)},o=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),s=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0},c={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},l=(0,n.forwardRef)(({color:e=`currentColor`,size:t=24,strokeWidth:r=2,absoluteStrokeWidth:i,className:a=``,children:l,iconNode:u,...d},f)=>(0,n.createElement)(`svg`,{ref:f,...c,width:t,height:t,stroke:e,strokeWidth:i?Number(r)*24/Number(t):r,className:o(`lucide`,a),...!l&&!s(d)&&{"aria-hidden":`true`},...d},[...u.map(([e,t])=>(0,n.createElement)(e,t)),...Array.isArray(l)?l:[l]])),u=(e,t)=>{let i=(0,n.forwardRef)(({className:i,...s},c)=>(0,n.createElement)(l,{ref:c,iconNode:t,className:o(`lucide-${r(a(e))}`,`lucide-${e}`,i),...s}));return i.displayName=a(e),i};export{u as t};
|
||||
import{i as e}from"./chunk-aKtaBQYM.js";import{D as t}from"./client-C3LdD0iY.js";var n=e(t()),r=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),i=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),a=e=>{let t=i(e);return t.charAt(0).toUpperCase()+t.slice(1)},o=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),s=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0},c={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},l=(0,n.forwardRef)(({color:e=`currentColor`,size:t=24,strokeWidth:r=2,absoluteStrokeWidth:i,className:a=``,children:l,iconNode:u,...d},f)=>(0,n.createElement)(`svg`,{ref:f,...c,width:t,height:t,stroke:e,strokeWidth:i?Number(r)*24/Number(t):r,className:o(`lucide`,a),...!l&&!s(d)&&{"aria-hidden":`true`},...d},[...u.map(([e,t])=>(0,n.createElement)(e,t)),...Array.isArray(l)?l:[l]])),u=(e,t)=>{let i=(0,n.forwardRef)(({className:i,...s},c)=>(0,n.createElement)(l,{ref:c,iconNode:t,className:o(`lucide-${r(a(e))}`,`lucide-${e}`,i),...s}));return i.displayName=a(e),i};export{u as t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`dollar-sign`,[[`line`,{x1:`12`,x2:`12`,y1:`2`,y2:`22`,key:`7eqyqh`}],[`path`,{d:`M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6`,key:`1b0p4s`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`dollar-sign`,[[`line`,{x1:`12`,x2:`12`,y1:`2`,y2:`22`,key:`7eqyqh`}],[`path`,{d:`M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6`,key:`1b0p4s`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`droplet`,[[`path`,{d:`M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z`,key:`c7niix`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`droplet`,[[`path`,{d:`M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z`,key:`c7niix`}]]);export{t};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`ellipsis-vertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`ellipsis-vertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`cable`,[[`path`,{d:`M17 19a1 1 0 0 1-1-1v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2a1 1 0 0 1-1 1z`,key:`trhst0`}],[`path`,{d:`M17 21v-2`,key:`ds4u3f`}],[`path`,{d:`M19 14V6.5a1 1 0 0 0-7 0v11a1 1 0 0 1-7 0V10`,key:`1mo9zo`}],[`path`,{d:`M21 21v-2`,key:`eo0ou`}],[`path`,{d:`M3 5V3`,key:`1k5hjh`}],[`path`,{d:`M4 10a2 2 0 0 1-2-2V6a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2z`,key:`1dd30t`}],[`path`,{d:`M7 5V3`,key:`1t1388`}]]),n=e(`fan`,[[`path`,{d:`M10.827 16.379a6.082 6.082 0 0 1-8.618-7.002l5.412 1.45a6.082 6.082 0 0 1 7.002-8.618l-1.45 5.412a6.082 6.082 0 0 1 8.618 7.002l-5.412-1.45a6.082 6.082 0 0 1-7.002 8.618l1.45-5.412Z`,key:`484a7f`}],[`path`,{d:`M12 12v.01`,key:`u5ubse`}]]);export{t as n,n as t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`cable`,[[`path`,{d:`M17 19a1 1 0 0 1-1-1v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2a1 1 0 0 1-1 1z`,key:`trhst0`}],[`path`,{d:`M17 21v-2`,key:`ds4u3f`}],[`path`,{d:`M19 14V6.5a1 1 0 0 0-7 0v11a1 1 0 0 1-7 0V10`,key:`1mo9zo`}],[`path`,{d:`M21 21v-2`,key:`eo0ou`}],[`path`,{d:`M3 5V3`,key:`1k5hjh`}],[`path`,{d:`M4 10a2 2 0 0 1-2-2V6a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2z`,key:`1dd30t`}],[`path`,{d:`M7 5V3`,key:`1t1388`}]]),n=e(`fan`,[[`path`,{d:`M10.827 16.379a6.082 6.082 0 0 1-8.618-7.002l5.412 1.45a6.082 6.082 0 0 1 7.002-8.618l-1.45 5.412a6.082 6.082 0 0 1 8.618 7.002l-5.412-1.45a6.082 6.082 0 0 1-7.002 8.618l1.45-5.412Z`,key:`484a7f`}],[`path`,{d:`M12 12v.01`,key:`u5ubse`}]]);export{t as n,n as t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`file-box`,[[`path`,{d:`M14.5 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v3.8`,key:`1kchwa`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M11.7 14.2 7 17l-4.7-2.8`,key:`1yk8tc`}],[`path`,{d:`M3 13.1a2 2 0 0 0-.999 1.76v3.24a2 2 0 0 0 .969 1.78L6 21.7a2 2 0 0 0 2.03.01L11 19.9a2 2 0 0 0 1-1.76V14.9a2 2 0 0 0-.97-1.78L8 11.3a2 2 0 0 0-2.03-.01z`,key:`19flxy`}],[`path`,{d:`M7 17v5`,key:`1yj1jh`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`file-box`,[[`path`,{d:`M14.5 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v3.8`,key:`1kchwa`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M11.7 14.2 7 17l-4.7-2.8`,key:`1yk8tc`}],[`path`,{d:`M3 13.1a2 2 0 0 0-.999 1.76v3.24a2 2 0 0 0 .969 1.78L6 21.7a2 2 0 0 0 2.03.01L11 19.9a2 2 0 0 0 1-1.76V14.9a2 2 0 0 0-.97-1.78L8 11.3a2 2 0 0 0-2.03-.01z`,key:`19flxy`}],[`path`,{d:`M7 17v5`,key:`1yj1jh`}]]);export{t};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`file-spreadsheet`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M8 13h2`,key:`yr2amv`}],[`path`,{d:`M14 13h2`,key:`un5t4a`}],[`path`,{d:`M8 17h2`,key:`2yhykz`}],[`path`,{d:`M14 17h2`,key:`10kma7`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`file-spreadsheet`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M8 13h2`,key:`yr2amv`}],[`path`,{d:`M14 13h2`,key:`un5t4a`}],[`path`,{d:`M8 17h2`,key:`2yhykz`}],[`path`,{d:`M14 17h2`,key:`10kma7`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`funnel`,[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`funnel`,[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]]);export{t};
|
||||
@@ -1 +1 @@
|
||||
import{t as e}from"./createLucideIcon-CozFoJIa.js";var t=e(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]);export{t};
|
||||
import{t as e}from"./createLucideIcon-DiLOIyaZ.js";var t=e(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]);export{t};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user