Compare commits

..

3 Commits

Author SHA1 Message Date
orangecoding
0e29c9b9c6 next release version 2026-05-07 12:45:52 +02:00
datenwurm
f60c5859f9 feat: Add grid/table view toggle to listings overview (#305)
* feat: Add delete button to listing detail view

* feat: Add grid/table view toggle to listings overview

---------

Co-authored-by: datenwurm <git@datenwurm.net>
2026-05-07 12:12:49 +02:00
datenwurm
ee54cc495b feat: Add delete button to listing detail view (#304)
Co-authored-by: datenwurm <git@datenwurm.net>
2026-05-07 11:53:51 +02:00
14 changed files with 1111 additions and 724 deletions

View File

@@ -109,4 +109,21 @@ export default async function userSettingsPlugin(fastify) {
return reply.code(500).send({ error: error.message });
}
});
fastify.post('/listings-view-mode', async (request, reply) => {
const userId = request.session.currentUser;
const { listings_view_mode } = request.body;
if (listings_view_mode !== 'grid' && listings_view_mode !== 'table') {
return reply.code(400).send({ error: 'listings_view_mode must be "grid" or "table".' });
}
try {
upsertSettings({ listings_view_mode }, userId);
return { success: true };
} catch (error) {
logger.error('Error updating listings view mode setting', error);
return reply.code(500).send({ error: error.message });
}
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "fredy",
"version": "21.1.1",
"version": "21.2.0",
"description": "[F]ind [R]eal [E]states [d]amn eas[y].",
"scripts": {
"prepare": "husky",
@@ -62,9 +62,9 @@
"Firefox ESR"
],
"dependencies": {
"@douyinfe/semi-icons": "^2.96.0",
"@douyinfe/semi-ui": "2.96.0",
"@douyinfe/semi-ui-19": "^2.96.0",
"@douyinfe/semi-icons": "^2.96.1",
"@douyinfe/semi-ui": "2.96.1",
"@douyinfe/semi-ui-19": "^2.96.1",
"@fastify/cookie": "^11.0.2",
"@fastify/helmet": "^13.0.2",
"@fastify/session": "^11.1.1",
@@ -88,27 +88,27 @@
"nodemailer": "^8.0.7",
"p-throttle": "^8.1.0",
"package-up": "^5.0.0",
"puppeteer": "^24.42.0",
"puppeteer": "^24.43.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"query-string": "9.3.1",
"react": "19.2.5",
"react": "19.2.6",
"react-chartjs-2": "^5.3.1",
"react-dom": "19.2.5",
"react-dom": "19.2.6",
"react-range-slider-input": "^3.3.5",
"react-router": "7.14.2",
"react-router-dom": "7.14.2",
"resend": "^6.12.2",
"react-router": "7.15.0",
"react-router-dom": "7.15.0",
"resend": "^6.12.3",
"semver": "^7.7.4",
"slack": "11.0.2",
"vite": "8.0.10",
"vite": "8.0.11",
"x-var": "^3.0.1",
"zustand": "^5.0.12"
"zustand": "^5.0.13"
},
"devDependencies": {
"@babel/core": "7.29.0",
"@babel/eslint-parser": "7.28.6",
"@babel/preset-env": "7.29.3",
"@babel/preset-env": "7.29.5",
"@babel/preset-react": "7.28.5",
"@eslint/js": "^10.0.1",
"chalk": "^5.6.2",

BIN
ui/src/assets/news/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

View File

@@ -1,10 +1,11 @@
{
"key": "00e6b81777a275f5a140fc9101cb943810db6a69f6eb3927319c5aee0c876542",
"key": "00e6b81777a275f5a140fc9101cb943810db6a69f6eb3927319c5aee0c876515",
"content":
[
{
"title": "Open in...Fredy ;)",
"text": "With the latest version of Fredy, every notification now comes with a link that opens the listing directly inside Fredy. This is also a key step toward an upcoming...milestone :).<br/>To make this work, Fredy needs to know where it lives on the network. We try to guess the public base URL, but lets be honest, you probably know better. Take a quick look at the baseUrl in the system settings and fix it if it looks off."
"title": "Table overview for listings",
"text": "Thanks to https://github.com/datenwurm, we now have a table overview for listings. If you decide to use the table view, the decision will be stored.",
"media": "1.png"
}
]
}

View File

@@ -3,14 +3,7 @@
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
import { useState, useEffect, useMemo } from 'react';
import {
useSearchParamState,
parseNumber,
parseString,
parseNullableBoolean,
} from '../../../hooks/useSearchParamState.js';
import { Button, Pagination, Toast, Input, Select, Empty, Radio, RadioGroup, Tooltip } from '@douyinfe/semi-ui-19';
import { Button, Tooltip } from '@douyinfe/semi-ui-19';
import {
IconBriefcase,
IconCart,
@@ -19,323 +12,117 @@ import {
IconMapPin,
IconStar,
IconStarStroked,
IconSearch,
IconEyeOpened,
IconArrowUp,
IconArrowDown,
} from '@douyinfe/semi-icons';
import { useNavigate, useSearchParams } from 'react-router-dom';
import ListingDeletionModal from '../../ListingDeletionModal.jsx';
import no_image from '../../../assets/no_image.png';
import * as timeService from '../../../services/time/timeService.js';
import { xhrDelete, xhrPost } from '../../../services/xhr.js';
import { useActions, useSelector } from '../../../services/state/store.js';
import { debounce } from '../../../utils';
import './ListingsGrid.less';
import { IllustrationNoResult, IllustrationNoResultDark } from '@douyinfe/semi-illustrations';
const ListingsGrid = () => {
const listingsData = useSelector((state) => state.listingsData);
const providers = useSelector((state) => state.provider);
const jobs = useSelector((state) => state.jobsData.jobs);
const actions = useActions();
const navigate = useNavigate();
const sp = useSearchParams();
const [page, setPage] = useSearchParamState(sp, 'page', 1, parseNumber);
const pageSize = 40;
const [sortField, setSortField] = useSearchParamState(sp, 'sort', 'created_at', parseString);
const [sortDir, setSortDir] = useSearchParamState(sp, 'dir', 'desc', parseString);
const [freeTextFilter, setFreeTextFilter] = useSearchParamState(sp, 'q', null, parseString);
const [watchListFilter, setWatchListFilter] = useSearchParamState(sp, 'watch', null, parseNullableBoolean);
const [jobNameFilter, setJobNameFilter] = useSearchParamState(sp, 'job', null, parseString);
const [activityFilter, setActivityFilter] = useSearchParamState(sp, 'active', null, parseNullableBoolean);
const [providerFilter, setProviderFilter] = useSearchParamState(sp, 'provider', null, parseString);
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const [listingToDelete, setListingToDelete] = useState(null);
const loadData = () => {
actions.listingsData.getListingsData({
page,
pageSize,
sortfield: sortField,
sortdir: sortDir,
freeTextFilter,
filter: { watchListFilter, jobNameFilter, activityFilter, providerFilter },
});
};
useEffect(() => {
loadData();
}, [page, sortField, sortDir, freeTextFilter, providerFilter, activityFilter, jobNameFilter, watchListFilter]);
const handleFilterChange = useMemo(
() =>
debounce((value) => {
setFreeTextFilter(value || null);
setPage(1);
}, 500),
[],
);
useEffect(() => {
return () => {
// cleanup debounced handler to avoid memory leaks
handleFilterChange.cancel && handleFilterChange.cancel();
};
}, [handleFilterChange]);
const handleWatch = async (e, item) => {
e.preventDefault();
e.stopPropagation();
try {
await xhrPost('/api/listings/watch', { listingId: item.id });
Toast.success(item.isWatched === 1 ? 'Listing removed from Watchlist' : 'Listing added to Watchlist');
loadData();
} catch (e) {
console.error(e);
Toast.error('Failed to operate Watchlist');
}
};
const handlePageChange = (_page) => {
setPage(_page);
};
const confirmDeletion = async (hardDelete) => {
try {
await xhrDelete('/api/listings/', { ids: [listingToDelete], hardDelete });
Toast.success('Listing successfully removed');
loadData();
} catch (error) {
Toast.error(error.message || 'Error deleting listing');
} finally {
setDeleteModalVisible(false);
setListingToDelete(null);
}
};
return (
<div className="listingsGrid">
<div className="listingsGrid__topbar">
<Input
className="listingsGrid__topbar__search"
prefix={<IconSearch />}
showClear
placeholder="Search"
defaultValue={freeTextFilter ?? ''}
onChange={handleFilterChange}
/>
<RadioGroup
type="button"
buttonSize="middle"
value={activityFilter === null ? 'all' : String(activityFilter)}
onChange={(e) => {
const v = e.target.value;
setActivityFilter(v === 'all' ? null : v === 'true');
setPage(1);
}}
>
<Radio value="all">All</Radio>
<Radio value="true">Active</Radio>
<Radio value="false">Inactive</Radio>
</RadioGroup>
<RadioGroup
type="button"
buttonSize="middle"
value={watchListFilter === null ? 'all' : String(watchListFilter)}
onChange={(e) => {
const v = e.target.value;
setWatchListFilter(v === 'all' ? null : v === 'true');
setPage(1);
}}
>
<Radio value="all">All</Radio>
<Radio value="true">Watched</Radio>
<Radio value="false">Unwatched</Radio>
</RadioGroup>
<Select
placeholder="Provider"
showClear
onChange={(val) => {
setProviderFilter(val);
setPage(1);
}}
value={providerFilter}
style={{ width: 130 }}
>
{providers?.map((p) => (
<Select.Option key={p.id} value={p.id}>
{p.name}
</Select.Option>
))}
</Select>
<Select
placeholder="Job"
showClear
onChange={(val) => {
setJobNameFilter(val);
setPage(1);
}}
value={jobNameFilter}
style={{ width: 130 }}
>
{jobs?.map((j) => (
<Select.Option key={j.id} value={j.id}>
{j.name}
</Select.Option>
))}
</Select>
<Select prefix="Sort by" style={{ width: 185 }} value={sortField} onChange={(val) => setSortField(val)}>
<Select.Option value="job_name">Job Name</Select.Option>
<Select.Option value="created_at">Listing Date</Select.Option>
<Select.Option value="price">Price</Select.Option>
<Select.Option value="provider">Provider</Select.Option>
</Select>
<Button
icon={sortDir === 'asc' ? <IconArrowUp /> : <IconArrowDown />}
onClick={() => setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))}
title={sortDir === 'asc' ? 'Ascending' : 'Descending'}
/>
</div>
{(listingsData?.result || []).length === 0 && (
<Empty
image={<IllustrationNoResult />}
darkModeImage={<IllustrationNoResultDark />}
description="No listings available yet..."
/>
)}
<div className="listingsGrid__grid">
{(listingsData?.result || []).map((item) => (
<div
key={item.id}
className="listingsGrid__card"
style={{ cursor: 'pointer' }}
role="button"
tabIndex={0}
onClick={() => navigate(`/listings/listing/${item.id}`)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') navigate(`/listings/listing/${item.id}`);
}}
>
<div className="listingsGrid__card__image-wrapper">
<img
src={item.image_url || no_image}
alt={item.title}
onError={(e) => {
e.target.src = no_image;
}}
/>
{!item.is_active && (
<div className="listingsGrid__card__inactive-watermark">
<span>Inactive</span>
</div>
)}
<button
type="button"
className="listingsGrid__card__star"
onClick={(e) => handleWatch(e, item)}
aria-label={item.isWatched === 1 ? 'Remove from watchlist' : 'Add to watchlist'}
>
{item.isWatched === 1 ? <IconStar /> : <IconStarStroked />}
</button>
</div>
<div className="listingsGrid__card__body">
<div className="listingsGrid__card__title" title={item.title}>
{item.title}
</div>
{item.price && (
<div className="listingsGrid__card__price">
<IconCart size="small" />
{item.price}
</div>
)}
{item.address && (
<div className="listingsGrid__card__meta">
<IconMapPin />
{item.address}
</div>
)}
<div className="listingsGrid__card__meta">
<IconBriefcase />
{item.provider}
</div>
<div className="listingsGrid__card__provider">{timeService.format(item.created_at, false)}</div>
</div>
<div className="listingsGrid__card__actions" onClick={(e) => e.stopPropagation()}>
<Tooltip content="Original Listing">
<Button
size="small"
icon={<IconLink />}
style={{ color: '#60a5fa' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
window.open(item.link, '_blank');
}}
/>
</Tooltip>
<Tooltip content="View in Fredy">
<Button
size="small"
icon={<IconEyeOpened />}
style={{ color: '#34d399' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
navigate(`/listings/listing/${item.id}`);
}}
/>
</Tooltip>
<Tooltip content="Remove">
<Button
size="small"
icon={<IconDelete />}
style={{ color: '#fb7185' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
setListingToDelete(item.id);
setDeleteModalVisible(true);
}}
/>
</Tooltip>
</div>
</div>
))}
</div>
{(listingsData?.result || []).length > 0 && (
<div className="listingsGrid__pagination">
<Pagination
currentPage={page}
pageSize={pageSize}
total={listingsData?.totalNumber || 0}
onPageChange={handlePageChange}
showSizeChanger={false}
/>
</div>
)}
<ListingDeletionModal
visible={deleteModalVisible}
onConfirm={confirmDeletion}
onCancel={() => {
setDeleteModalVisible(false);
setListingToDelete(null);
/**
* @param {{ listings: object[], onWatch: Function, onNavigate: Function, onDelete: Function }} props
*/
const ListingsGrid = ({ listings, onWatch, onNavigate, onDelete }) => (
<div className="listingsGrid__grid">
{listings.map((item) => (
<div
key={item.id}
className="listingsGrid__card"
style={{ cursor: 'pointer' }}
role="button"
tabIndex={0}
onClick={() => onNavigate(item.id)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') onNavigate(item.id);
}}
/>
</div>
);
};
>
<div className="listingsGrid__card__image-wrapper">
<img
src={item.image_url || no_image}
alt={item.title}
onError={(e) => {
e.target.src = no_image;
}}
/>
{!item.is_active && (
<div className="listingsGrid__card__inactive-watermark">
<span>Inactive</span>
</div>
)}
<button
type="button"
className="listingsGrid__card__star"
onClick={(e) => onWatch(e, item)}
aria-label={item.isWatched === 1 ? 'Remove from watchlist' : 'Add to watchlist'}
>
{item.isWatched === 1 ? <IconStar /> : <IconStarStroked />}
</button>
</div>
<div className="listingsGrid__card__body">
<div className="listingsGrid__card__title" title={item.title}>
{item.title}
</div>
{item.price && (
<div className="listingsGrid__card__price">
<IconCart size="small" />
{item.price}
</div>
)}
{item.address && (
<div className="listingsGrid__card__meta">
<IconMapPin />
{item.address}
</div>
)}
<div className="listingsGrid__card__meta">
<IconBriefcase />
{item.provider}
</div>
<div className="listingsGrid__card__provider">{timeService.format(item.created_at, false)}</div>
</div>
<div className="listingsGrid__card__actions" onClick={(e) => e.stopPropagation()}>
<Tooltip content="Original Listing">
<Button
size="small"
icon={<IconLink />}
style={{ color: '#60a5fa' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
window.open(item.link, '_blank');
}}
/>
</Tooltip>
<Tooltip content="View in Fredy">
<Button
size="small"
icon={<IconEyeOpened />}
style={{ color: '#34d399' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
onNavigate(item.id);
}}
/>
</Tooltip>
<Tooltip content="Remove">
<Button
size="small"
icon={<IconDelete />}
style={{ color: '#fb7185' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
onDelete(item.id);
}}
/>
</Tooltip>
</div>
</div>
))}
</div>
);
export default ListingsGrid;

View File

@@ -1,181 +1,143 @@
@import '../../../tokens.less';
.listingsGrid {
&__topbar {
.listingsGrid__grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 12px;
}
.listingsGrid__card {
background: @color-elevated !important;
border: 1px solid @color-border !important;
border-radius: @radius-card !important;
overflow: hidden;
transition: transform @transition-card, box-shadow @transition-card;
display: flex;
flex-direction: column;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 24px -4px rgba(0,0,0,0.6);
}
&__image-wrapper {
position: relative;
height: 160px;
overflow: hidden;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
}
&__inactive-watermark {
position: absolute;
inset: 0;
display: flex;
align-items: center;
gap: @space-3;
margin-bottom: @space-4;
flex-wrap: wrap;
justify-content: center;
background: rgba(0,0,0,0.35);
&__search {
min-width: 200px;
flex: 1;
}
@media (max-width: 768px) {
.listingsGrid__topbar__search {
width: 100%;
flex: unset;
}
.semi-radio-group {
flex: 1;
}
.semi-select {
flex: 1;
min-width: 100px;
width: auto !important;
}
span {
font-size: 18px;
font-weight: 800;
color: rgba(251,113,133,0.9);
text-transform: uppercase;
letter-spacing: 0.15em;
transform: rotate(-30deg);
border: 2px solid rgba(251,113,133,0.5);
padding: 4px 12px;
border-radius: @radius-chip;
backdrop-filter: blur(2px);
}
}
&__grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 12px;
}
&__card {
background: @color-elevated !important;
border: 1px solid @color-border !important;
border-radius: @radius-card !important;
overflow: hidden;
transition: transform @transition-card, box-shadow @transition-card;
&__star {
position: absolute;
top: 8px;
right: 8px;
background: rgba(0,0,0,0.5);
border: none;
border-radius: 50%;
width: 28px;
height: 28px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background @transition-fast;
padding: 0;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 24px -4px rgba(0,0,0,0.6);
background: rgba(0,0,0,0.75);
}
&__image-wrapper {
position: relative;
height: 160px;
overflow: hidden;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
svg {
color: @color-accent;
font-size: 14px;
}
}
&__inactive-watermark {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.35);
&__body {
padding: 12px;
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
span {
font-size: 18px;
font-weight: 800;
color: rgba(251,113,133,0.9);
text-transform: uppercase;
letter-spacing: 0.15em;
transform: rotate(-30deg);
border: 2px solid rgba(251,113,133,0.5);
padding: 4px 12px;
border-radius: @radius-chip;
backdrop-filter: blur(2px);
}
}
&__title {
font-weight: 700;
font-size: @text-sm;
color: @color-text;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__star {
position: absolute;
top: 8px;
right: 8px;
background: rgba(0,0,0,0.5);
border: none;
border-radius: 50%;
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background @transition-fast;
padding: 0;
&__price {
font-size: @text-base;
font-weight: 600;
color: @color-success;
display: flex;
align-items: center;
gap: 4px;
}
&:hover {
background: rgba(0,0,0,0.75);
}
&__meta {
font-size: @text-xs;
color: @color-muted;
display: flex;
align-items: center;
gap: 4px;
svg {
color: @color-accent;
font-size: 14px;
}
}
&__body {
padding: 12px;
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
&__title {
font-weight: 700;
font-size: @text-sm;
color: @color-text;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__price {
font-size: @text-base;
font-weight: 600;
color: @color-success;
display: flex;
align-items: center;
gap: 4px;
}
&__meta {
font-size: @text-xs;
color: @color-muted;
display: flex;
align-items: center;
gap: 4px;
.semi-icon {
font-size: 11px;
color: @color-faint;
}
}
&__provider {
font-size: @text-xs;
.semi-icon {
font-size: 11px;
color: @color-faint;
}
}
&__actions {
display: flex;
justify-content: space-around;
padding: 8px 12px;
border-top: 1px solid @color-border;
gap: 4px;
margin-top: auto;
&__provider {
font-size: @text-xs;
color: @color-faint;
}
button {
flex: 1;
border: none !important;
border-radius: @radius-chip !important;
}
&__actions {
display: flex;
justify-content: space-around;
padding: 8px 12px;
border-top: 1px solid @color-border;
gap: 4px;
margin-top: auto;
button {
flex: 1;
border: none !important;
border-radius: @radius-chip !important;
}
}
&__pagination {
margin-top: @space-4;
display: flex;
justify-content: center;
}
}

View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2026 by Christian Kellner.
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
import { useState, useEffect, useMemo } from 'react';
import {
useSearchParamState,
parseNumber,
parseString,
parseNullableBoolean,
} from '../../hooks/useSearchParamState.js';
import { Button, Pagination, Toast, Input, Select, Empty, Radio, RadioGroup, Tooltip } from '@douyinfe/semi-ui-19';
import { IconSearch, IconArrowUp, IconArrowDown, IconGridView, IconList } from '@douyinfe/semi-icons';
import { useNavigate, useSearchParams } from 'react-router-dom';
import ListingDeletionModal from '../ListingDeletionModal.jsx';
import { xhrDelete, xhrPost } from '../../services/xhr.js';
import { useActions, useSelector } from '../../services/state/store.js';
import { debounce } from '../../utils';
import ListingsGrid from '../grid/listings/ListingsGrid.jsx';
import ListingsTable from '../table/ListingsTable.jsx';
import { IllustrationNoResult, IllustrationNoResultDark } from '@douyinfe/semi-illustrations';
import './ListingsOverview.less';
const ListingsOverview = () => {
const listingsData = useSelector((state) => state.listingsData);
const providers = useSelector((state) => state.provider);
const jobs = useSelector((state) => state.jobsData.jobs);
const userSettings = useSelector((state) => state.userSettings.settings);
const actions = useActions();
const navigate = useNavigate();
const sp = useSearchParams();
const viewMode = userSettings?.listings_view_mode ?? 'grid';
const [page, setPage] = useSearchParamState(sp, 'page', 1, parseNumber);
const pageSize = 40;
const [sortField, setSortField] = useSearchParamState(sp, 'sort', 'created_at', parseString);
const [sortDir, setSortDir] = useSearchParamState(sp, 'dir', 'desc', parseString);
const [freeTextFilter, setFreeTextFilter] = useSearchParamState(sp, 'q', null, parseString);
const [watchListFilter, setWatchListFilter] = useSearchParamState(sp, 'watch', null, parseNullableBoolean);
const [jobNameFilter, setJobNameFilter] = useSearchParamState(sp, 'job', null, parseString);
const [activityFilter, setActivityFilter] = useSearchParamState(sp, 'active', null, parseNullableBoolean);
const [providerFilter, setProviderFilter] = useSearchParamState(sp, 'provider', null, parseString);
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const [listingToDelete, setListingToDelete] = useState(null);
const loadData = () => {
actions.listingsData.getListingsData({
page,
pageSize,
sortfield: sortField,
sortdir: sortDir,
freeTextFilter,
filter: { watchListFilter, jobNameFilter, activityFilter, providerFilter },
});
};
useEffect(() => {
loadData();
}, [page, sortField, sortDir, freeTextFilter, providerFilter, activityFilter, jobNameFilter, watchListFilter]);
const handleFilterChange = useMemo(
() =>
debounce((value) => {
setFreeTextFilter(value || null);
setPage(1);
}, 500),
[],
);
useEffect(() => {
return () => {
handleFilterChange.cancel && handleFilterChange.cancel();
};
}, [handleFilterChange]);
const handleWatch = async (e, item) => {
e.preventDefault();
e.stopPropagation();
try {
await xhrPost('/api/listings/watch', { listingId: item.id });
Toast.success(item.isWatched === 1 ? 'Listing removed from Watchlist' : 'Listing added to Watchlist');
loadData();
} catch (e) {
console.error(e);
Toast.error('Failed to operate Watchlist');
}
};
const handleDelete = (id) => {
setListingToDelete(id);
setDeleteModalVisible(true);
};
const handleNavigate = (id) => navigate(`/listings/listing/${id}`);
const confirmDeletion = async (hardDelete) => {
try {
await xhrDelete('/api/listings/', { ids: [listingToDelete], hardDelete });
Toast.success('Listing successfully removed');
loadData();
} catch (error) {
Toast.error(error.message || 'Error deleting listing');
} finally {
setDeleteModalVisible(false);
setListingToDelete(null);
}
};
const listings = listingsData?.result || [];
return (
<div className="listingsOverview">
<div className="listingsOverview__topbar">
<Input
className="listingsOverview__topbar__search"
prefix={<IconSearch />}
showClear
placeholder="Search"
defaultValue={freeTextFilter ?? ''}
onChange={handleFilterChange}
/>
<RadioGroup
type="button"
buttonSize="middle"
value={activityFilter === null ? 'all' : String(activityFilter)}
onChange={(e) => {
const v = e.target.value;
setActivityFilter(v === 'all' ? null : v === 'true');
setPage(1);
}}
>
<Radio value="all">All</Radio>
<Radio value="true">Active</Radio>
<Radio value="false">Inactive</Radio>
</RadioGroup>
<RadioGroup
type="button"
buttonSize="middle"
value={watchListFilter === null ? 'all' : String(watchListFilter)}
onChange={(e) => {
const v = e.target.value;
setWatchListFilter(v === 'all' ? null : v === 'true');
setPage(1);
}}
>
<Radio value="all">All</Radio>
<Radio value="true">Watched</Radio>
<Radio value="false">Unwatched</Radio>
</RadioGroup>
<Select
placeholder="Provider"
showClear
onChange={(val) => {
setProviderFilter(val);
setPage(1);
}}
value={providerFilter}
style={{ width: 130 }}
>
{providers?.map((p) => (
<Select.Option key={p.id} value={p.id}>
{p.name}
</Select.Option>
))}
</Select>
<Select
placeholder="Job"
showClear
onChange={(val) => {
setJobNameFilter(val);
setPage(1);
}}
value={jobNameFilter}
style={{ width: 130 }}
>
{jobs?.map((j) => (
<Select.Option key={j.id} value={j.id}>
{j.name}
</Select.Option>
))}
</Select>
<Select prefix="Sort by" style={{ width: 185 }} value={sortField} onChange={(val) => setSortField(val)}>
<Select.Option value="job_name">Job Name</Select.Option>
<Select.Option value="created_at">Listing Date</Select.Option>
<Select.Option value="price">Price</Select.Option>
<Select.Option value="provider">Provider</Select.Option>
</Select>
<Button
icon={sortDir === 'asc' ? <IconArrowUp /> : <IconArrowDown />}
onClick={() => setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))}
title={sortDir === 'asc' ? 'Ascending' : 'Descending'}
/>
<div className="listingsOverview__topbar__view-toggle">
<Tooltip content="Grid view">
<Button
icon={<IconGridView />}
theme={viewMode === 'grid' ? 'solid' : 'borderless'}
onClick={() => actions.userSettings.setListingsViewMode('grid')}
aria-label="Grid view"
aria-pressed={viewMode === 'grid'}
/>
</Tooltip>
<Tooltip content="Table view">
<Button
icon={<IconList />}
theme={viewMode === 'table' ? 'solid' : 'borderless'}
onClick={() => actions.userSettings.setListingsViewMode('table')}
aria-label="Table view"
aria-pressed={viewMode === 'table'}
/>
</Tooltip>
</div>
</div>
{listings.length === 0 && (
<Empty
image={<IllustrationNoResult />}
darkModeImage={<IllustrationNoResultDark />}
description="No listings available yet..."
/>
)}
{viewMode === 'grid' ? (
<ListingsGrid listings={listings} onWatch={handleWatch} onNavigate={handleNavigate} onDelete={handleDelete} />
) : (
<ListingsTable listings={listings} onWatch={handleWatch} onNavigate={handleNavigate} onDelete={handleDelete} />
)}
{listings.length > 0 && (
<div className="listingsOverview__pagination">
<Pagination
currentPage={page}
pageSize={pageSize}
total={listingsData?.totalNumber || 0}
onPageChange={setPage}
showSizeChanger={false}
/>
</div>
)}
<ListingDeletionModal
visible={deleteModalVisible}
onConfirm={confirmDeletion}
onCancel={() => {
setDeleteModalVisible(false);
setListingToDelete(null);
}}
/>
</div>
);
};
export default ListingsOverview;

View File

@@ -0,0 +1,45 @@
@import '../../tokens.less';
.listingsOverview {
&__topbar {
display: flex;
align-items: center;
gap: @space-3;
margin-bottom: @space-4;
flex-wrap: wrap;
&__search {
min-width: 200px;
flex: 1;
}
&__view-toggle {
display: flex;
gap: 2px;
flex-shrink: 0;
}
@media (max-width: 768px) {
.listingsOverview__topbar__search {
width: 100%;
flex: unset;
}
.semi-radio-group {
flex: 1;
}
.semi-select {
flex: 1;
min-width: 100px;
width: auto !important;
}
}
}
&__pagination {
margin-top: @space-4;
display: flex;
justify-content: center;
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2026 by Christian Kellner.
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
import { Button, Tooltip } from '@douyinfe/semi-ui-19';
import {
IconBriefcase,
IconCart,
IconDelete,
IconLink,
IconMapPin,
IconStar,
IconStarStroked,
IconEyeOpened,
} from '@douyinfe/semi-icons';
import no_image from '../../assets/no_image.png';
import * as timeService from '../../services/time/timeService.js';
import './ListingsTable.less';
/**
* @param {{ listings: object[], onWatch: Function, onNavigate: Function, onDelete: Function }} props
*/
const ListingsTable = ({ listings, onWatch, onNavigate, onDelete }) => (
<div className="listingsTable">
{listings.map((item) => (
<div
key={item.id}
className={`listingsTable__row${!item.is_active ? ' listingsTable__row--inactive' : ''}`}
role="button"
tabIndex={0}
onClick={() => onNavigate(item.id)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') onNavigate(item.id);
}}
>
<div className="listingsTable__row__thumb">
<img
src={item.image_url || no_image}
alt={item.title}
onError={(e) => {
e.target.src = no_image;
}}
/>
</div>
<div className="listingsTable__row__title" title={item.title}>
{item.title}
</div>
<div className="listingsTable__row__price">
{item.price ? (
<>
<IconCart size="small" />
{item.price}
</>
) : (
<span className="listingsTable__row__empty"></span>
)}
</div>
<div className="listingsTable__row__address">
{item.address ? (
<>
<IconMapPin size="small" />
{item.address}
</>
) : (
<span className="listingsTable__row__empty"></span>
)}
</div>
<div className="listingsTable__row__meta">
<IconBriefcase size="small" />
{item.provider}
</div>
<div className="listingsTable__row__date">{timeService.format(item.created_at, false)}</div>
<div className="listingsTable__row__actions" onClick={(e) => e.stopPropagation()}>
<button
type="button"
className="listingsTable__row__star"
onClick={(e) => onWatch(e, item)}
aria-label={item.isWatched === 1 ? 'Remove from watchlist' : 'Add to watchlist'}
>
{item.isWatched === 1 ? <IconStar /> : <IconStarStroked />}
</button>
<Tooltip content="Original Listing">
<Button
size="small"
icon={<IconLink />}
style={{ color: '#60a5fa' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
window.open(item.link, '_blank');
}}
/>
</Tooltip>
<Tooltip content="View in Fredy">
<Button
size="small"
icon={<IconEyeOpened />}
style={{ color: '#34d399' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
onNavigate(item.id);
}}
/>
</Tooltip>
<Tooltip content="Remove">
<Button
size="small"
icon={<IconDelete />}
style={{ color: '#fb7185' }}
theme="borderless"
onClick={(e) => {
e.stopPropagation();
onDelete(item.id);
}}
/>
</Tooltip>
</div>
</div>
))}
</div>
);
export default ListingsTable;

View File

@@ -0,0 +1,142 @@
@import '../../tokens.less';
.listingsTable {
display: flex;
flex-direction: column;
gap: 4px;
&__row {
display: grid;
grid-template-columns: 56px 1fr 140px 200px 120px 110px auto;
align-items: center;
gap: @space-3;
padding: 8px 12px;
background: @color-elevated;
border: 1px solid @color-border;
border-radius: @radius-chip;
cursor: pointer;
transition: background @transition-fast;
&:hover {
background: #252525;
}
&--inactive {
opacity: 0.6;
}
&__thumb {
width: 56px;
height: 40px;
flex-shrink: 0;
border-radius: @radius-chip;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
}
&__title {
font-weight: 600;
font-size: @text-sm;
color: @color-text;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__price {
font-size: @text-sm;
font-weight: 600;
color: @color-success;
display: flex;
align-items: center;
gap: 4px;
white-space: nowrap;
}
&__address {
font-size: @text-xs;
color: @color-muted;
display: flex;
align-items: center;
gap: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__meta {
font-size: @text-xs;
color: @color-muted;
display: flex;
align-items: center;
gap: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__date {
font-size: @text-xs;
color: @color-faint;
white-space: nowrap;
}
&__actions {
display: flex;
align-items: center;
gap: 2px;
}
&__star {
width: 28px;
height: 28px;
background: transparent;
border: none;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0;
transition: background @transition-fast;
flex-shrink: 0;
&:hover {
background: rgba(0, 0, 0, 0.1);
}
svg {
color: @color-accent;
font-size: 14px;
}
}
&__empty {
color: @color-faint;
}
@media (max-width: 900px) {
grid-template-columns: 56px 1fr 120px auto;
.listingsTable__row__address,
.listingsTable__row__meta,
.listingsTable__row__date {
display: none;
}
}
@media (max-width: 560px) {
grid-template-columns: 56px 1fr auto;
.listingsTable__row__price {
display: none;
}
}
}
}

View File

@@ -321,6 +321,20 @@ export const useFredyState = create(
throw Exception;
}
},
async setListingsViewMode(listings_view_mode) {
try {
await xhrPost('/api/user/settings/listings-view-mode', { listings_view_mode });
set((state) => ({
userSettings: {
...state.userSettings,
settings: { ...state.userSettings.settings, listings_view_mode },
},
}));
} catch (Exception) {
console.error('Error while trying to update listings view mode setting. Error:', Exception);
throw Exception;
}
},
},
};

View File

@@ -31,6 +31,7 @@ import {
IconLink,
IconStar,
IconStarStroked,
IconDelete,
IconExpand,
IconGridView,
} from '@douyinfe/semi-icons';
@@ -39,7 +40,8 @@ import 'maplibre-gl/dist/maplibre-gl.css';
import no_image from '../../assets/no_image.png';
import * as timeService from '../../services/time/timeService.js';
import { distanceMeters, getBoundsFromCoords } from './mapUtils.js';
import { xhrPost } from '../../services/xhr.js';
import { xhrPost, xhrDelete } from '../../services/xhr.js';
import ListingDeletionModal from '../../components/ListingDeletionModal.jsx';
import Headline from '../../components/headline/Headline.jsx';
import './ListingDetail.less';
@@ -59,6 +61,7 @@ export default function ListingDetail() {
const mapContainer = useRef(null);
const map = useRef(null);
const [loading, setLoading] = useState(true);
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
useEffect(() => {
async function fetchListing() {
@@ -239,6 +242,18 @@ export default function ListingDetail() {
};
}, [listing, loading, homeAddress]);
const confirmDeletion = async (hardDelete) => {
try {
await xhrDelete('/api/listings/', { ids: [listing.id], hardDelete });
Toast.success('Listing successfully removed');
navigate('/listings');
} catch (e) {
Toast.error(e.message || 'Error deleting listing');
} finally {
setDeleteModalVisible(false);
}
};
const handleWatch = async () => {
try {
await xhrPost('/api/listings/watch', { listingId: listing.id });
@@ -330,6 +345,14 @@ export default function ListingDetail() {
<IconLink style={{ marginRight: 6 }} />
Open listing
</a>
<Button
icon={<IconDelete />}
onClick={() => setDeleteModalVisible(true)}
theme="light"
type="danger"
>
Delete
</Button>
</Space>
</div>
@@ -397,6 +420,12 @@ export default function ListingDetail() {
<div ref={mapContainer} className="listing-detail__map-container" />
)}
</div>
<ListingDeletionModal
visible={deleteModalVisible}
onConfirm={confirmDeletion}
onCancel={() => setDeleteModalVisible(false)}
/>
</div>
);
}

View File

@@ -3,14 +3,14 @@
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
import ListingsGrid from '../../components/grid/listings/ListingsGrid.jsx';
import ListingsOverview from '../../components/listings/ListingsOverview.jsx';
import Headline from '../../components/headline/Headline.jsx';
export default function Listings() {
return (
<>
<Headline text="Listings" />
<ListingsGrid />
<ListingsOverview />
</>
);
}

458
yarn.lock
View File

@@ -497,10 +497,10 @@
"@babel/helper-module-transforms" "^7.28.6"
"@babel/helper-plugin-utils" "^7.28.6"
"@babel/plugin-transform-modules-systemjs@^7.29.0":
version "7.29.0"
resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz"
integrity sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==
"@babel/plugin-transform-modules-systemjs@^7.29.4":
version "7.29.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz#f621105da99919c15cf4bde6fcc7346ef95e7b20"
integrity sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==
dependencies:
"@babel/helper-module-transforms" "^7.28.6"
"@babel/helper-plugin-utils" "^7.28.6"
@@ -731,10 +731,10 @@
"@babel/helper-create-regexp-features-plugin" "^7.28.5"
"@babel/helper-plugin-utils" "^7.28.6"
"@babel/preset-env@7.29.3":
version "7.29.3"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.29.3.tgz#2bbd5b0162e6a762adfe356f4aecdef837a3d574"
integrity sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==
"@babel/preset-env@7.29.5":
version "7.29.5"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.29.5.tgz#c48b7ed94582c8b685e21b8b42de8633ec289268"
integrity sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==
dependencies:
"@babel/compat-data" "^7.29.3"
"@babel/helper-compilation-targets" "^7.28.6"
@@ -775,7 +775,7 @@
"@babel/plugin-transform-member-expression-literals" "^7.27.1"
"@babel/plugin-transform-modules-amd" "^7.27.1"
"@babel/plugin-transform-modules-commonjs" "^7.28.6"
"@babel/plugin-transform-modules-systemjs" "^7.29.0"
"@babel/plugin-transform-modules-systemjs" "^7.29.4"
"@babel/plugin-transform-modules-umd" "^7.27.1"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.29.0"
"@babel/plugin-transform-new-target" "^7.27.1"
@@ -895,34 +895,34 @@
dependencies:
tslib "^2.0.0"
"@douyinfe/semi-animation-react@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.96.0.tgz#ea0284072b7c30b3b53793d03e46353141822b0d"
integrity sha512-ZE+fPOsHGyCC2pgOnTvkf9pONZT2OUZcUJ7hF3EbnBi45xkww1rhiWy2e6sl+dZdx/15LFip9gAqmqIMizWXig==
"@douyinfe/semi-animation-react@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.96.1.tgz#988dc965dc468212504e9a19c1fee0905f2f7dd1"
integrity sha512-uUG4hBss//+38H16w9JqVaukORoCNbnwrZ+1G7tYVjs1pbndvk0vXxLsZVWBOuQk4TqYFAiMPJ0h6A2i+ZdE/Q==
dependencies:
"@douyinfe/semi-animation" "2.96.0"
"@douyinfe/semi-animation-styled" "2.96.0"
"@douyinfe/semi-animation" "2.96.1"
"@douyinfe/semi-animation-styled" "2.96.1"
classnames "^2.2.6"
"@douyinfe/semi-animation-styled@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.96.0.tgz#27b18e3c56a925a19bf50741bf51e0f2c17c1bf3"
integrity sha512-GdTjXYXFSExoE0VD4mGA4wFsFauKpcegm8kBZZYKVyP1FM4ZJ35REqJA1VINKPAS1lljh3lbyPRulltFOqRiDQ==
"@douyinfe/semi-animation-styled@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.96.1.tgz#562079d1751bd72d1a3846e28ed6b5c00b32b94c"
integrity sha512-FaPY6xNOiswNvnZr6uaFOUg60mHrJVeIcJDmLqUCwJ3d3KGcCdEvOrA0T+V1u64CGTXLgAFYRARr2iMwXc2+5g==
"@douyinfe/semi-animation@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.96.0.tgz#228e7ddf8a8e209c268bd69ba1fc28d4aa7b5697"
integrity sha512-v7qhQ64i3/kTF+XkhBpeJvTiFbd6/UuYdh8tIrzaZDuhlzdJ3k1MdBTpec48TDPcXO7K/L9oz9IhSWgpPyr4iQ==
"@douyinfe/semi-animation@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.96.1.tgz#dd13abd08b066a85aca58ec93ed98fff8062face"
integrity sha512-QsfBlTP4WsOGC2of4UPD3AvfWbSq0W0RlXu8F4O0Z954ojDZGAfNuCwzHMAgqgE/vJEHvFA0Hzx4bWn0MT6LGw==
dependencies:
bezier-easing "^2.1.0"
"@douyinfe/semi-foundation@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.96.0.tgz#92ed9afb18cf5e2f0983066de3d861a27fb79c85"
integrity sha512-bR37+zGxwAAfWP2dOkyT66gN1La5PRoaI+rI2KciDgj7B05II0Ax4pybNvBQ0oWP70rR5y8EoQezvQa1Gxz3rg==
"@douyinfe/semi-foundation@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.96.1.tgz#eee03ce5e94a916145b0f2807736bb65119ea3b0"
integrity sha512-RcNN6wlt879u5R4OQJfoZwkSy7RZ4FnfvkHzvI8s2thJ6XOplQHgbF3IDo+fvcwARfUa9hydICL5fNjy6Glk6Q==
dependencies:
"@douyinfe/semi-animation" "2.96.0"
"@douyinfe/semi-json-viewer-core" "2.96.0"
"@douyinfe/semi-animation" "2.96.1"
"@douyinfe/semi-json-viewer-core" "2.96.1"
"@mdx-js/mdx" "^3.0.1"
async-validator "^3.5.0"
classnames "^2.2.6"
@@ -936,44 +936,44 @@
remark-gfm "^4.0.0"
scroll-into-view-if-needed "^2.2.24"
"@douyinfe/semi-icons@2.96.0", "@douyinfe/semi-icons@^2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.96.0.tgz#c57035887fda7f5ba5485b1e2057e66fb1ef19a4"
integrity sha512-DMacIzTGN+JwWt6IOVOpLbnXSf8x7hkcP/Q3ezhXlX89Csk0lgR7XvN082qbcyeCx4nHDjFbEgFCnrpE7OUPhw==
"@douyinfe/semi-icons@2.96.1", "@douyinfe/semi-icons@^2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.96.1.tgz#4f7ebf360771b11d2a31f19ce0c0bd130adb1509"
integrity sha512-x/7OHPKsnK3MYF72j+tWJDpBeZwSAEA6OlRrlqWQCU02wqPqMnedF+j+bueU4ZVK0TaP9A7rjBZx6PZAT/Ssgg==
dependencies:
classnames "^2.2.6"
"@douyinfe/semi-illustrations@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.96.0.tgz#b24efde3aa5c863a1dbc60b70ac841dee12dbd94"
integrity sha512-B6zYSbJ/g1rDy7hplYfiwljGRVnHApMMWVnbilD2li0m2V8W60rP448XHo3SoM+lBNxEWRJ1STKEZajliRk4XQ==
"@douyinfe/semi-illustrations@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.96.1.tgz#cd94c9223026aa7a7335c259bbc271eaffb24fc2"
integrity sha512-/azBr6qSZ+2eWHrFbch3ngYLGpAvmRqS21NcdT+fFFkS/JmmeqPfwN68P6Jr0rfzz1G3QkN19HbjKpHCE50Ylw==
"@douyinfe/semi-json-viewer-core@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-json-viewer-core/-/semi-json-viewer-core-2.96.0.tgz#b6840b634f1705c0391baeb5296d18506d804b54"
integrity sha512-zhL6WF/mlG69mB1pQnXPFH7mb97rHLp6BkSKk5m0pFt02jquo2qjhvYDsziqAFTEkA+npEC7I+eAQhqyHN00zg==
"@douyinfe/semi-json-viewer-core@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-json-viewer-core/-/semi-json-viewer-core-2.96.1.tgz#a06f1491c9732c5c89fe9b3f1be22eb4ce1f1521"
integrity sha512-SRD0fx03IHb7lgNXviR/HuLNsU6H+kZ0LZnxdj/qIAWxqOB91TzRSuiRX8lokUpphFN+NOSj9e92rNktjgNvog==
dependencies:
jsonc-parser "^3.3.1"
"@douyinfe/semi-theme-default@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.96.0.tgz#3ee689a0b0a295ce13a1d4b612ad5736264c7b7c"
integrity sha512-XuExot1vuh0EP8olz6cCGpIxQc1u790sO9mrooBt3ocCzlDXDhGJx1kYzJkHa7LdfDK5AEllFB1eF/QnrFxKUQ==
"@douyinfe/semi-theme-default@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.96.1.tgz#2eeeeb840412939fca5d049ccdaf8281df1ff1b1"
integrity sha512-8UCWJND7o8OIX4HnQz5xlVJriibl+pLGBhz2Mq5SDRkCDDEcqAwjbpwbmgz1uHhZzZly+yq5fMRkvgQTkeD/ig==
"@douyinfe/semi-ui-19@^2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui-19/-/semi-ui-19-2.96.0.tgz#a947d17456ed7ed1b733d4ee2f8e12596b7bd89f"
integrity sha512-I2uMO5pH1ZgKsH8DprKZr/adRGiRqQG9lYW4rAH/ldvlp2XfJTTfqAwiFDVNkPJvMUZTqUH3wM8gs51xhHFSYg==
"@douyinfe/semi-ui-19@^2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui-19/-/semi-ui-19-2.96.1.tgz#c9b7fb06817757e58143de4ba69b4c65caeb7575"
integrity sha512-+60CXg0U0OXWrFyN3+thOKmOdFMJnGss0fyCA8JiQeA7VG5QpneU9qo94IOyAO/jG953IOLRKa8BLWtAwJbumA==
dependencies:
"@dnd-kit/core" "^6.0.8"
"@dnd-kit/sortable" "^7.0.2"
"@dnd-kit/utilities" "^3.2.1"
"@douyinfe/semi-animation" "2.96.0"
"@douyinfe/semi-animation-react" "2.96.0"
"@douyinfe/semi-foundation" "2.96.0"
"@douyinfe/semi-icons" "2.96.0"
"@douyinfe/semi-illustrations" "2.96.0"
"@douyinfe/semi-theme-default" "2.96.0"
"@douyinfe/semi-animation" "2.96.1"
"@douyinfe/semi-animation-react" "2.96.1"
"@douyinfe/semi-foundation" "2.96.1"
"@douyinfe/semi-icons" "2.96.1"
"@douyinfe/semi-illustrations" "2.96.1"
"@douyinfe/semi-theme-default" "2.96.1"
"@tiptap/core" "^3.10.7"
"@tiptap/extension-document" "^3.10.7"
"@tiptap/extension-hard-break" "^3.10.7"
@@ -1002,20 +1002,20 @@
scroll-into-view-if-needed "^2.2.24"
utility-types "^3.10.0"
"@douyinfe/semi-ui@2.96.0":
version "2.96.0"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.96.0.tgz#4f1e046f801866942cb053adddb7aabe3f79dc32"
integrity sha512-JHORLPOkaTiUoQIedoTX38rdJIiT0RNNlp3sqIqQRDeLODsZ6kHYFhBgRURTeT0HthPgfuilRWqWDULGJL+cIw==
"@douyinfe/semi-ui@2.96.1":
version "2.96.1"
resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.96.1.tgz#ad447fff5ae260c81e6b765994b171e8cb3ab627"
integrity sha512-kbe8pJJBpj/5t7VlswF4FEuiB+JW6GITtINem85sZSwFSU9JAWPlLEsnlOOhY8k5CHJtTQWx9+bmXdgPgpzg3Q==
dependencies:
"@dnd-kit/core" "^6.0.8"
"@dnd-kit/sortable" "^7.0.2"
"@dnd-kit/utilities" "^3.2.1"
"@douyinfe/semi-animation" "2.96.0"
"@douyinfe/semi-animation-react" "2.96.0"
"@douyinfe/semi-foundation" "2.96.0"
"@douyinfe/semi-icons" "2.96.0"
"@douyinfe/semi-illustrations" "2.96.0"
"@douyinfe/semi-theme-default" "2.96.0"
"@douyinfe/semi-animation" "2.96.1"
"@douyinfe/semi-animation-react" "2.96.1"
"@douyinfe/semi-foundation" "2.96.1"
"@douyinfe/semi-icons" "2.96.1"
"@douyinfe/semi-illustrations" "2.96.1"
"@douyinfe/semi-theme-default" "2.96.1"
"@tiptap/core" "^3.10.7"
"@tiptap/extension-document" "^3.10.7"
"@tiptap/extension-hard-break" "^3.10.7"
@@ -1516,20 +1516,20 @@
resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.122.0.tgz#2f4e77a3b183c87b2a326affd703ef71ba836601"
integrity sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==
"@oxc-project/types@=0.127.0":
version "0.127.0"
resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.127.0.tgz#8374fcdfb4a641861218daa5700c447c00b66663"
integrity sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==
"@oxc-project/types@=0.128.0":
version "0.128.0"
resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.128.0.tgz#efc7524f948ff9e8ab1404ecad1823849c6fe149"
integrity sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==
"@pinojs/redact@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6"
integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==
"@puppeteer/browsers@2.13.0":
version "2.13.0"
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.13.0.tgz#10f980c6d65efeff77f8a3cac6e1a7ac10604500"
integrity sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==
"@puppeteer/browsers@2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.13.1.tgz#be1a50cc550ad1c9a8e6af7fd9e336b2f071311f"
integrity sha512-zmS4RTK9fbrc++WlAJhxYbfz3IjDeOmkK/CwwbLmk7ydfS9e2CiEeRJHEPvjDVElO/bwXbidwGA37Bsm6LzCnQ==
dependencies:
debug "^4.4.3"
extract-zip "^2.0.1"
@@ -1549,120 +1549,120 @@
resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz#4e6af08b89da02596cc5da4b105082b68673ffec"
integrity sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==
"@rolldown/binding-android-arm64@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz#0a502a88c39d0ffa81aa30b561dade6f6217dcc5"
integrity sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==
"@rolldown/binding-android-arm64@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz#3af8b2242086125934a85c1915b76e0a6a2054c1"
integrity sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==
"@rolldown/binding-darwin-arm64@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz#a06890f4c9b48ff0fc97edbedfc762bef7cffd73"
integrity sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==
"@rolldown/binding-darwin-arm64@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz#8b7f05ac9000ab19161a79a0346b1b64a1bc7ba3"
integrity sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==
"@rolldown/binding-darwin-arm64@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.18.tgz#ae0b4467d24ecd6c6589f03d4d4699616ee9649c"
integrity sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==
"@rolldown/binding-darwin-x64@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz#eddf6aa3ed3509171fe21711f1e8ec8e0fd7ec49"
integrity sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==
"@rolldown/binding-darwin-x64@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz#f8b465b3a4e992053890b162f1ae19e4f1719a6a"
integrity sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==
"@rolldown/binding-darwin-x64@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.18.tgz#23cf24b0a7b96c8990bbdd8a91e7fd3ba82b00e7"
integrity sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==
"@rolldown/binding-freebsd-x64@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz#2102dfed19fd1f1b53435fcaaf0bc61129a266a3"
integrity sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==
"@rolldown/binding-freebsd-x64@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz#a8281e14fa9c243fe22dc2d0e54900e66b31935e"
integrity sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==
"@rolldown/binding-freebsd-x64@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.18.tgz#a047a770f94dc451c062b729e5d1cf82e5c6f9c4"
integrity sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==
"@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz#b2c13f40e990fd1e1935492850536c768c961a0f"
integrity sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==
"@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz#cd29cf869ddd4fac8d6929abf94b91ddb0494650"
integrity sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==
"@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.18.tgz#c0b7f346cbf50301cea669a4632bc63aabe6a72c"
integrity sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==
"@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz#32ca9f77c1e76b2913b3d53d2029dc171c0532d6"
integrity sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==
"@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz#91c331236ec3728366218d61a62f0bd226546c6c"
integrity sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==
"@rolldown/binding-linux-arm64-gnu@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.18.tgz#af56373c7996ebe6379207cd699c9f7f705e235d"
integrity sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==
"@rolldown/binding-linux-arm64-musl@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz#f4337ddd52f0ed3ada2105b59ee1b757a2c4858c"
integrity sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==
"@rolldown/binding-linux-arm64-musl@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz#80108957db752e7826836e22240e56b8140e9684"
integrity sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==
"@rolldown/binding-linux-arm64-musl@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.18.tgz#a8f5acd21fcffc8991aa84710e3ae603c4240ea4"
integrity sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==
"@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz#22fdd14cb00ee8208c28a39bab7f28860ec6705d"
integrity sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==
"@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz#1dce51148cbc6bab3c3f9157b5323d2a31aac924"
integrity sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==
"@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.18.tgz#1d4a89e040ff82141fc46e717cfab80b05f7c13f"
integrity sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==
"@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz#838215096d1de6d3d509e0410801cb7cda8161ff"
integrity sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==
"@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz#d4a0d2e01d8d441e4ac3af3fa68eec17a7d0e9cd"
integrity sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==
"@rolldown/binding-linux-s390x-gnu@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.18.tgz#97c21feeb2ed87d07820f0b2dcc5dd663e7a7f3b"
integrity sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==
"@rolldown/binding-linux-x64-gnu@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz#f7d71d97f6bd43198596b26dc2cb364586e12673"
integrity sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==
"@rolldown/binding-linux-x64-gnu@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz#0ac8b3139cefeea798ad147f30ea70572b133af1"
integrity sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==
"@rolldown/binding-linux-x64-gnu@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.18.tgz#06310d40fe139ccc3c433b361120d337c66ebec2"
integrity sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==
"@rolldown/binding-linux-x64-musl@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz#a2ca737f01b0ad620c4c404ca176ea3e3ad804c3"
integrity sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==
"@rolldown/binding-linux-x64-musl@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz#2af61bee087571728f58f1c47734bbbd41dd7050"
integrity sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==
"@rolldown/binding-linux-x64-musl@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.18.tgz#6a711258841f42609b238050cfcd5db13ac136d0"
integrity sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==
"@rolldown/binding-openharmony-arm64@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz#f66317e29eafcc300bed7af8dddac26ab3b1bf82"
integrity sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==
"@rolldown/binding-openharmony-arm64@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz#56c1afbf6c592819abf47b4a983987dc288b30c1"
integrity sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==
"@rolldown/binding-openharmony-arm64@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.18.tgz#15cb644beeafdbec930d79ed45c2a7c2573eac70"
integrity sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==
"@rolldown/binding-wasm32-wasi@1.0.0-rc.12":
version "1.0.0-rc.12"
@@ -1671,10 +1671,10 @@
dependencies:
"@napi-rs/wasm-runtime" "^1.1.1"
"@rolldown/binding-wasm32-wasi@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz#5d112ff4dd0d268a60fb4e0eb3077e3ea2531f0d"
integrity sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==
"@rolldown/binding-wasm32-wasi@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.18.tgz#ca3a56d11dfd533d743711141b3bb4c1ec10110e"
integrity sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==
dependencies:
"@emnapi/core" "1.10.0"
"@emnapi/runtime" "1.10.0"
@@ -1685,30 +1685,30 @@
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz#4f3a17e3d68a58309c27c0930b0f7986ccabef47"
integrity sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==
"@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz#5125a85222d64a543201d28e16a395cc45bf4d17"
integrity sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==
"@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.18.tgz#8c2117d68331d7de59d24631146d538fc203d27c"
integrity sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==
"@rolldown/binding-win32-x64-msvc@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz#d762765d5660598a96b570b513f535c151272985"
integrity sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==
"@rolldown/binding-win32-x64-msvc@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz#fc6b78e759a0bb2054b5c0a3489da12b2cae54b4"
integrity sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==
"@rolldown/binding-win32-x64-msvc@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.18.tgz#bb5c28df3095046778cc1b020ef52fc5ee7b7e70"
integrity sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==
"@rolldown/pluginutils@1.0.0-rc.12":
version "1.0.0-rc.12"
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz#74163aec62fa51cee18d62709483963dceb3f6dc"
integrity sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==
"@rolldown/pluginutils@1.0.0-rc.17":
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz#a89b30833fb628bc834fe2e89fea93a2da9fa69a"
integrity sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==
"@rolldown/pluginutils@1.0.0-rc.18":
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz#51cf2589596a179ebe8cbf313f1358c7b51a2fdc"
integrity sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==
"@rolldown/pluginutils@1.0.0-rc.7":
version "1.0.0-rc.7"
@@ -3269,10 +3269,10 @@ devlop@^1.0.0, devlop@^1.1.0:
dependencies:
dequal "^2.0.0"
devtools-protocol@0.0.1595872:
version "0.0.1595872"
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1595872.tgz#6f3f537a8518887d30d5181e41788f697f2a4ab2"
integrity sha512-kRfgp8vWVjBu/fbYCiVFiOqsCk3CrMKEo3WbgGT2NXK2dG7vawWPBljixajVgGK9II8rDO9G0oD0zLt3I1daRg==
devtools-protocol@0.0.1608973:
version "0.0.1608973"
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz#56e0a2a999b06d416ee928ca06aeba95a5880515"
integrity sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ==
doctrine@^2.1.0:
version "2.1.0"
@@ -6452,10 +6452,10 @@ postal-mime@2.7.4:
resolved "https://registry.yarnpkg.com/postal-mime/-/postal-mime-2.7.4.tgz#3718d1f188357ed86f906f1db8d4ca455efa4927"
integrity sha512-0WdnFQYUrPGGTFu1uOqD2s7omwua8xaeYGdO6rb88oD5yJ/4pPHDA4sdWqfD8wQVfCny563n/HQS7zTFft+f/g==
postcss@^8.5.10:
version "8.5.10"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356"
integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==
postcss@^8.5.14:
version "8.5.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.14.tgz#a66c2d7808fadf69ebb5b84a03f8bafd76c4919c"
integrity sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==
dependencies:
nanoid "^3.3.11"
picocolors "^1.1.1"
@@ -6751,18 +6751,18 @@ punycode@^2.1.0:
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
puppeteer-core@24.42.0:
version "24.42.0"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.42.0.tgz#85c1f6c73e6225be0d50fc6a4f2914690280e8cf"
integrity sha512-T4zXokk/izH01fYPhyyev1A4piWiOKrYq7CUFpdoYQxmOnXoV6YjUabmfIjCYkNspSoAXIxRid3Tw+Vg0fthYg==
puppeteer-core@24.43.0:
version "24.43.0"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.43.0.tgz#8a2fe71c3a02ac9b43d055b884f0906581707431"
integrity sha512-cCRNXsUlhyPoKDz6+TiSpfZpRS3mD6Y1YFKhkdr6ik6TMfuJb7fAtXq9ThUFc4sphxObDk3BuAvdxc1Y6YOnqQ==
dependencies:
"@puppeteer/browsers" "2.13.0"
"@puppeteer/browsers" "2.13.1"
chromium-bidi "14.0.0"
debug "^4.4.3"
devtools-protocol "0.0.1595872"
typed-query-selector "^2.12.1"
devtools-protocol "0.0.1608973"
typed-query-selector "^2.12.2"
webdriver-bidi-protocol "0.4.1"
ws "^8.19.0"
ws "^8.20.0"
puppeteer-extra-plugin-stealth@^2.11.2:
version "2.11.2"
@@ -6811,17 +6811,17 @@ puppeteer-extra@^3.3.6:
debug "^4.1.1"
deepmerge "^4.2.2"
puppeteer@^24.42.0:
version "24.42.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.42.0.tgz#2efe442c240ea44c05138a12a98aa0fdba1a6b83"
integrity sha512-94MoPfFp2eY3eYIMdINkez4IOP5TMHntlZbVx06fHlQTtiQiYgaY0L2Zzfod8PVUkPqP7m3Qlre2v8YS8cudPA==
puppeteer@^24.43.0:
version "24.43.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.43.0.tgz#98b4a0bc36bcc53c2c9d6afb80d0464b26d5cdf7"
integrity sha512-DRnMFz+J3s4lFUQcjqKl0/7h0jzlCZuUFU9lNjtKrnMl5WI1RwCaIItpHVu9empuPyUreYueN0sUW3/pnfdqsg==
dependencies:
"@puppeteer/browsers" "2.13.0"
"@puppeteer/browsers" "2.13.1"
chromium-bidi "14.0.0"
cosmiconfig "^9.0.0"
devtools-protocol "0.0.1595872"
puppeteer-core "24.42.0"
typed-query-selector "^2.12.1"
devtools-protocol "0.0.1608973"
puppeteer-core "24.43.0"
typed-query-selector "^2.12.2"
qs@^6.14.0:
version "6.15.0"
@@ -6886,10 +6886,10 @@ react-chartjs-2@^5.3.1:
resolved "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz"
integrity sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==
react-dom@19.2.5:
version "19.2.5"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.5.tgz#b8768b10837d0b8e9ca5b9e2d58dff3d880ea25e"
integrity sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==
react-dom@19.2.6:
version "19.2.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.6.tgz#44a81b0bcca22da814c00847d09d01c8615529b7"
integrity sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==
dependencies:
scheduler "^0.27.0"
@@ -6922,17 +6922,17 @@ react-resizable@^3.0.5:
prop-types "15.x"
react-draggable "^4.0.3"
react-router-dom@7.14.2:
version "7.14.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.14.2.tgz#0b043c1534fe58596771b82a318a7e4c2e5f1279"
integrity sha512-YZcM5ES8jJSM+KrJ9BdvHHqlnGTg5tH3sC5ChFRj4inosKctdyzBDhOyyHdGk597q2OT6NTrCA1OvB/YDwfekQ==
react-router-dom@7.15.0:
version "7.15.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.15.0.tgz#a4b95c4402d896c2ad437014aff9076b94673063"
integrity sha512-VcrVg64Fo8nwBvDscajG8gRTLIuTC6N50nb22l2HOOV4PTOHgoGp8mUjy9wLiHYoYTSYI36tUnXZgasSRFZorQ==
dependencies:
react-router "7.14.2"
react-router "7.15.0"
react-router@7.14.2:
version "7.14.2"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.14.2.tgz#d86e5b01049365b2c982363ebd2baa4928824603"
integrity sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==
react-router@7.15.0:
version "7.15.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.15.0.tgz#cb438ff254ab5a1e356ef5a23d7821d8f6fbe652"
integrity sha512-HW9vYwuM8f4yx66Izy8xfrzCM+SBJluoZcCbww9A1TySax11S5Vgw6fi3ZjMONw9J4gQwngL7PzkyIpJJpJ7RQ==
dependencies:
cookie "^1.0.1"
set-cookie-parser "^2.6.0"
@@ -6945,10 +6945,10 @@ react-window@^1.8.2:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"
react@19.2.5:
version "19.2.5"
resolved "https://registry.yarnpkg.com/react/-/react-19.2.5.tgz#c888ab8b8ef33e2597fae8bdb2d77edbdb42858b"
integrity sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==
react@19.2.6:
version "19.2.6"
resolved "https://registry.yarnpkg.com/react/-/react-19.2.6.tgz#3dadb8e12b2a7934c1d5317973e5dce1301f9a4d"
integrity sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==
readable-stream@^3.1.1, readable-stream@^3.4.0:
version "3.6.2"
@@ -7149,13 +7149,13 @@ require-from-string@^2.0.2:
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
resend@^6.12.2:
version "6.12.2"
resolved "https://registry.yarnpkg.com/resend/-/resend-6.12.2.tgz#4b9eb2e129c9369e25e19c8abd12913968e8c647"
integrity sha512-xwgmU4b0OqoabJsIoK/x0Whk0Fcs3bpbK4i/DEWPiE5hYJHyHl0TbB6QbI3gIr+bLdLUJ1GYm/fe41aVFuHXgw==
resend@^6.12.3:
version "6.12.3"
resolved "https://registry.yarnpkg.com/resend/-/resend-6.12.3.tgz#d4e180f21c9edb21db074d48766e84866551313c"
integrity sha512-FkEi6YPnVL96/LvH8+QP7NaeaBy5brYXwlRqUCqZZeNL0/iyKij18IPmyPXYauT/2ODn1JG04qKz+qlJfzqzTw==
dependencies:
postal-mime "2.7.4"
svix "1.90.0"
svix "1.92.2"
resolve-from@^4.0.0:
version "4.0.0"
@@ -7246,29 +7246,29 @@ rolldown@1.0.0-rc.12:
"@rolldown/binding-win32-arm64-msvc" "1.0.0-rc.12"
"@rolldown/binding-win32-x64-msvc" "1.0.0-rc.12"
rolldown@1.0.0-rc.17:
version "1.0.0-rc.17"
resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.0.0-rc.17.tgz#c524fc22f6bb37b5588aec862ab1ee11382610f3"
integrity sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==
rolldown@1.0.0-rc.18:
version "1.0.0-rc.18"
resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.0.0-rc.18.tgz#c597f89a4ce12e6fc918fa91e4f892b340aa92f0"
integrity sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==
dependencies:
"@oxc-project/types" "=0.127.0"
"@rolldown/pluginutils" "1.0.0-rc.17"
"@oxc-project/types" "=0.128.0"
"@rolldown/pluginutils" "1.0.0-rc.18"
optionalDependencies:
"@rolldown/binding-android-arm64" "1.0.0-rc.17"
"@rolldown/binding-darwin-arm64" "1.0.0-rc.17"
"@rolldown/binding-darwin-x64" "1.0.0-rc.17"
"@rolldown/binding-freebsd-x64" "1.0.0-rc.17"
"@rolldown/binding-linux-arm-gnueabihf" "1.0.0-rc.17"
"@rolldown/binding-linux-arm64-gnu" "1.0.0-rc.17"
"@rolldown/binding-linux-arm64-musl" "1.0.0-rc.17"
"@rolldown/binding-linux-ppc64-gnu" "1.0.0-rc.17"
"@rolldown/binding-linux-s390x-gnu" "1.0.0-rc.17"
"@rolldown/binding-linux-x64-gnu" "1.0.0-rc.17"
"@rolldown/binding-linux-x64-musl" "1.0.0-rc.17"
"@rolldown/binding-openharmony-arm64" "1.0.0-rc.17"
"@rolldown/binding-wasm32-wasi" "1.0.0-rc.17"
"@rolldown/binding-win32-arm64-msvc" "1.0.0-rc.17"
"@rolldown/binding-win32-x64-msvc" "1.0.0-rc.17"
"@rolldown/binding-android-arm64" "1.0.0-rc.18"
"@rolldown/binding-darwin-arm64" "1.0.0-rc.18"
"@rolldown/binding-darwin-x64" "1.0.0-rc.18"
"@rolldown/binding-freebsd-x64" "1.0.0-rc.18"
"@rolldown/binding-linux-arm-gnueabihf" "1.0.0-rc.18"
"@rolldown/binding-linux-arm64-gnu" "1.0.0-rc.18"
"@rolldown/binding-linux-arm64-musl" "1.0.0-rc.18"
"@rolldown/binding-linux-ppc64-gnu" "1.0.0-rc.18"
"@rolldown/binding-linux-s390x-gnu" "1.0.0-rc.18"
"@rolldown/binding-linux-x64-gnu" "1.0.0-rc.18"
"@rolldown/binding-linux-x64-musl" "1.0.0-rc.18"
"@rolldown/binding-openharmony-arm64" "1.0.0-rc.18"
"@rolldown/binding-wasm32-wasi" "1.0.0-rc.18"
"@rolldown/binding-win32-arm64-msvc" "1.0.0-rc.18"
"@rolldown/binding-win32-x64-msvc" "1.0.0-rc.18"
rope-sequence@^1.3.0:
version "1.3.4"
@@ -7846,13 +7846,12 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
svix@1.90.0:
version "1.90.0"
resolved "https://registry.yarnpkg.com/svix/-/svix-1.90.0.tgz#49c3a310745b05a26d322f17c0207d0c6da88dc6"
integrity sha512-ljkZuyy2+IBEoESkIpn8sLM+sxJHQcPxlZFxU+nVDhltNfUMisMBzWX/UR8SjEnzoI28ZjCzMbmYAPwSTucoMw==
svix@1.92.2:
version "1.92.2"
resolved "https://registry.yarnpkg.com/svix/-/svix-1.92.2.tgz#2982904b032e24347b701cab3d5219ea94d9e49c"
integrity sha512-ZmuA3UVvlnF9EgxlzmPtF7CKjQb64Z6OFlyfdDfU0sdcC7dJa+3aOYX5B9mA+RS6ch1AxBa4UP/l6KmqfGtWBQ==
dependencies:
standardwebhooks "1.0.0"
uuid "^10.0.0"
tar-fs@^2.0.0:
version "2.1.3"
@@ -8055,10 +8054,10 @@ typed-array-length@^1.0.7:
possible-typed-array-names "^1.0.0"
reflect.getprototypeof "^1.0.6"
typed-query-selector@^2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.1.tgz#04423bfb71b8f3aee3df1c29598ed6c7c8f55284"
integrity sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==
typed-query-selector@^2.12.2:
version "2.12.2"
resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.2.tgz#65e2462ac6b0aecfae1bfac1a4f3027070dbabaa"
integrity sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==
uc.micro@^2.0.0, uc.micro@^2.1.0:
version "2.1.0"
@@ -8221,11 +8220,6 @@ utility-types@^3.10.0:
resolved "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz"
integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==
uuid@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
vary@^1, vary@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -8247,15 +8241,15 @@ vfile@^6.0.0:
"@types/unist" "^3.0.0"
vfile-message "^4.0.0"
vite@8.0.10:
version "8.0.10"
resolved "https://registry.yarnpkg.com/vite/-/vite-8.0.10.tgz#fb31868526ec874101fac084172a2cdc6776319b"
integrity sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==
vite@8.0.11:
version "8.0.11"
resolved "https://registry.yarnpkg.com/vite/-/vite-8.0.11.tgz#d128fe82a0dd24da5127d20560735f1cd7ade0a6"
integrity sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==
dependencies:
lightningcss "^1.32.0"
picomatch "^4.0.4"
postcss "^8.5.10"
rolldown "1.0.0-rc.17"
postcss "^8.5.14"
rolldown "1.0.0-rc.18"
tinyglobby "^0.2.16"
optionalDependencies:
fsevents "~2.3.3"
@@ -8432,10 +8426,10 @@ wrappy@1:
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
ws@^8.19.0:
version "8.19.0"
resolved "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz"
integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==
ws@^8.20.0:
version "8.20.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8"
integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==
x-var@^3.0.1:
version "3.0.1"
@@ -8506,10 +8500,10 @@ zod@^3.24.1:
resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a"
integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==
zustand@^5.0.12:
version "5.0.12"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.12.tgz#ed36f647aa89965c4019b671dfc23ef6c6e3af8c"
integrity sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==
zustand@^5.0.13:
version "5.0.13"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.13.tgz#06995c126e8903cd27100af04da91c36ae3051ed"
integrity sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==
zwitch@^2.0.0:
version "2.0.4"