Browse Source

chore: 提交响应式适配准备内容

version/1.2.14
thatsfelix 4 days ago
parent
commit
6896a0477e
  1. 66
      CLAUDE.md
  2. 168
      docs/responsive-adaptation-plan.md
  3. 103
      package-lock.json

66
CLAUDE.md

@ -0,0 +1,66 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Popiart SkillHub 前端。技术栈:**React 18 + TypeScript + Vite 5**(非 Vue),UI 用 **Arco Design**(`@arco-design/web-react`)+ **Tailwind CSS v4** + SCSS,状态管理 **Zustand**,路由 **React Router 6**,请求 **Axios**,国际化 **i18next**
## 强制规则(改代码/UI/文档前必读)
`AGENTS.md` 将以下 `.cursor` 规则声明为 mandatory:
- `.cursor/skills/react-best-practices/SKILL.md`(始终生效)
- `.cursor/rules/changelog-writing.mdc`
- UI/样式设计参考 `.cursor/skills/frontend-design/SKILL.md`;Figma 像素还原参考 `.cursor/skills/figma-ui-implementation/SKILL.md`
核心硬约束:
- **禁止 `any`**:ESLint `strictTypeChecked` + `no-explicit-any: error`,lint 零 warning(`--max-warnings 0`)。
- **所有 UI 文案必须走 i18n,禁止硬编码。**
- 只用函数组件 + hooks;state 尽量本地化,少用 `useEffect`/`useMemo`/`useCallback`。
- SCSS 嵌套须跟随 DOM 结构、语义化 class、避免深层选择器。
- 提交须符合 **Conventional Commits**(commitlint + Husky/lint-staged 提交前校验)。
## 常用命令
包管理器 **npm**(仅 `package-lock.json`);无 Node 版本约束(无 `engines`/`.nvmrc`)。
- `npm run dev` — 开发服务器,端口 **5195**,`--host 0.0.0.0`。
- `npm run build` — 默认构建(先 `tsc -p tsconfig.app.json` 类型检查,再 `vite build`)。
- `npm run build:stage` / `npm run build:prod` — 预发 / 生产构建(用 `.env.stage` / `.env.prod`)。**注意:这两个不含 `tsc` 类型检查**,要查类型请单独跑 `npm run build``tsc`
- `npm run preview` — 预览构建产物。
- `npm run lint` / `npm run lint:fix` — ESLint。
- `npm run format` / `npm run format:check` — Prettier(`printWidth 280`、双引号、分号、`trailingComma all`)。
**无测试**:项目未配置任何测试框架/脚本。
## 架构大局(需读多文件才理解的部分)
**入口**:`src/main.tsx` 挂载 `RouterProvider` + `AliveScope`(KeepAlive)+ i18n,并 bootstrap 拉取 paramConfig / memberLevel。`src/App.tsx` 只做全局副作用(埋点、拖拽拦截等),**路由不在 App.tsx 渲染,而在 main.tsx 的 RouterProvider**。
**路由**(`src/router/index.tsx`):`createBrowserRouter` + 全量 `lazy()` 懒加载。路径统一走 `ROUTES` 常量(`src/constants/index.ts`)。布局分层:多数路由包在 `src/router/LayoutRoot.tsx` 下共享 `Layout`,首页 `/index` 独立于 Layout。**KeepAlive** 用 `react-activation`(`CachedLayoutOutlet.tsx` / `routeCache.ts`)。**权限守卫非 Vue 式 beforeEach**,而是 `src/router/routeGuard.ts`(集中的受保护路由表)+ `LayoutRoot``LayoutRouteGate`(`useEffect` 拦截,未登录弹 `openLoginDialog`)。
**状态**(`src/store/`):Zustand,每个 store 一个文件(`useXxxStore.ts`),**无中央 rootStore**。`useUserStore` 用 `persist` 中间件存 localStorage(key `user_info`)。bootstrap 类 store 暴露幂等 `ensureXxx()` 方法。store 内部直接调 `@/api/api` 拉数据。
**网络层**(`src/api/`):
- `request.ts` axios 实例,`baseURL: "/api_client/"` —— **固定相对路径,靠 Vite dev proxy 转发**,不直接读 `VITE_API_URL`
- 请求拦截注入 `Authorization: Bearer <localStorage.token>`
- 响应拦截按业务码约定:`status === "0000"` 为成功;`4001` 未登录→清 token 弹登录;`4005` 积分不足→弹充值;`4004` 支付轮询"处理中"放行;其他→`Message.error`。可传 `skipGlobalErrorHandler` 跳过全局处理。
- **所有接口集中在单文件 `src/api/api.ts`**(~127 个导出函数 + 类型),并非按模块拆目录。
**命令式弹窗**(`src/dialog/`):`src/dialog/index.tsx` 是 barrel,导出 `openLoginDialog`、`openInsufficientPointsDialog` 等命令式 API(含 history 栈管理)。登录等交互走这些函数而非页面组件。
**i18n**(`src/i18n/index.ts`):支持 `zh-CN`/`zh-TW`/`en-US`,默认 `zh-CN`,`keySeparator: false`(用完整字符串作 key)。文案在 `src/locales/*.json`
**目录约定**:`src/pages`(按路由,页面目录内 `index.tsx` + `index.scss`)、`src/components`(PascalCase 目录,`index.tsx` + `index.scss` 成对)、`src/layouts/Layout/Layout.tsx`(主框架,含侧栏/顶栏)、`src/hooks`、`src/utils`、`src/constants`。别名 `@``src`。`hooks`/`utils`/`dialog`/`constants` 均有 barrel `index` 统一 re-export。
## 环境与代理(易踩坑)
- Vite dev proxy(`vite.config.mts`):`/api_client`、`/media`、`/resource` → `http://192.168.77.111:8080/`(`devApiTarget`;注释中留有备用 target `wwwtest.popi.art` / `www.popi.art`)。改后端联调地址在这里改。
- 三套 `.env`:`.env`(默认/dev)、`.env.stage`、`.env.prod`,`VITE_` 前缀注入。`VITE_API_URL` / `VITE_SKILLHUB_URL` / `VITE_CANVAS_URL` 主要用于**跳转链接**,而非 axios baseURL。
- prod 构建:esbuild `drop console/debugger`、无 sourcemap;Rollup `manualChunks` 手动分包(react/arco/swiper/markdown/data vendor)。
## 响应式适配现状
本项目 README 定位为 **PC 端(≥1280px)网站**,移动端基本未做真正重排。当前"适配"策略是**等比缩放优先**而非重排:
- `src/hooks/useViewportScale.ts` 以 **1920px 设计稿**为基准,用 CSS `zoom`/`transform` 缩放整个 Layout 内容区(缩放下限 0.65;宽度 <900px 时关闭缩放交由页面自身响应式)。
- 媒体查询零散存在(约 40 个 scss 文件),但断点**极不统一**(出现过 1778/1680/1500/1280/960/900/768/480 等各种值),**无统一断点体系、无 rem 方案、无 amfe-flexible / postcss-px-to-viewport**。
做移动端响应式时需正视上述现状(缩放机制与页面自身响应式的边界在 900px)。

168
docs/responsive-adaptation-plan.md

@ -0,0 +1,168 @@
# 响应式适配计划(Popiart SkillHub 前端)
> 本文档为移动端响应式适配的执行计划,按阶段推进。分支:`responsive`(切自 `version/1.2.14`)。
## Context(背景与目标)
本项目 README 定位为 **PC 端(≥1280px)网站**,移动端基本未做真正重排。当前"适配"靠 `src/hooks/useViewportScale.ts` 以 1920 设计稿等比缩放,窄屏体验差、弹窗溢出、侧栏挤占。现需**让整站在移动端可用**。
**硬约束:只做 UI 适配,不修改任何业务逻辑 / 数据流 / 接口。**
**三项决策:**
1. 移动端导航 = **底部 Tab 栏,纯 CSS 实现**(侧栏在窄屏 reflow 到底部,不做抽屉、不加开合 state)。
2. 断点范围 = **手机 + 平板**(多档断点)。
3. 改动边界 = **允许最小"启用型"改动**:修 viewport meta、新增 `useIsMobile`(matchMedia 封装)。不碰任何业务逻辑。
**三个关键前提(决定方案骨架):**
- **viewport 被锁死**:`index.html:17` 的 `<meta name="viewport" content="width=1280, user-scalable=no">` 覆盖了第 7 行的 `width=device-width`,真机被强制按 1280 宽渲染。**不修此行,一切响应式在真机失效** —— 第 0 步必做。
- **900px 是天然主断点**:`useViewportScale.ts:17` 的 `LAYOUT_SCALE_DISABLE_BELOW = 900`,窗口 <900px 时自动关闭等比缩放交给媒体查询。**所有"重排型"断点必须 900px**,否则与缩放坐标系打架。≥900px含平板横屏 1024仍在缩放系统内只做轻量微调不做重排
- **样式几乎全在 SCSS,Tailwind 基本空转**:2724 处 className 绝大多数是 SCSS 语义化 BEM 类;Tailwind 响应式变体 `sm:/md:/lg:` 用了 **0 处**,原子类仅 ~19 处。**Tailwind 的断点/栅格只在 className 生效,无法作用于 `.scss` 里的 `@media`**,而本次要改的 77 处 `@media` 全在 SCSS。→ 结论:主战场是手写 SCSS `@media`,不重写 JSX 为原子类,也不自建平行 token 系统。
- **Arco 用得极少(仅 7 个组件)**:Message(35)/Dropdown(14)/Modal(8)/Input(6)/Tooltip(6)/Button(3)/Spin(2)。**未用栅格 Row/Col、未用 Table、未用 Form**——布局 100% 原生 SCSS,Arco 帮不上布局响应式。唯一痛点是 **Modal 固定宽度**,且散在约 9 处(见阶段 2)。无 `ConfigProvider`
---
## 断点体系(对齐 Tailwind 默认,不自建平行系统)
数值**直接沿用 Tailwind v4 默认口径**,仅保留一个自定义主断点 900(与缩放开关硬耦合):
| 名称 | 范围 | 对应 Tailwind | 处理策略 |
|---|---|---|---|
| desktop | ≥1024px | ≥lg | 现状 + 等比缩放,基本不动 |
| tablet-landscape | 900–1024px | lg 区间 | 仍在缩放系统内,仅轻量微调,**不重排** |
| **mobile-main(主断点)** | **≤900px** | 自定义 | 缩放已自动关闭,**重排主战场**:侧栏→底部 Tab、多列→单/双列、弹窗→全屏 |
| tablet-portrait | ≤768px | md | 进一步收敛单列、隐藏次要信息 |
| small-phone | ≤640px | sm | 最小尺寸微调:字号、间距、图标化、按钮全宽 |
> 统一用 `max-width` 媒体查询(与现有方向一致)。**现有 77 处 `@media` 不重构**;新增的直接写 `@media (max-width: 900/768/640px)`,数值口径与 Tailwind 一致,将来若在新 JSX 用 `md:/lg:` 亦不冲突。是否加 SCSS `@mixin respond-to` 属可选糖,非必需。
---
## 阶段 0 · 全局基建(先做,是后续所有改造的抓手)
> 基建刻意做薄:**不引入平行 token 系统、不重构现有 @media、不把 JSX 改写成 Tailwind 原子类**。
| # | 事项 | 文件/位置 | 说明 |
|---|---|---|---|
| 0.1 | **修 viewport** | `index.html:17` | 删除/改为 `width=device-width, initial-scale=1`(保留第 7 行即可)。这是一切前提 |
| 0.2 | **约定断点数值** | 无需新文件;沿用 Tailwind 默认口径 | 统一用 900(主)/768(md)/640(sm)/1024(lg)。新增 @media 直接写数值;如需 SCSS mixin 仅加一个轻量 `@mixin respond-to`(可选)。若个别新 JSX 要响应式类,直接用 Tailwind 自带 `md:/lg:`,不自建 |
| 0.3 | **`useIsMobile` hook** | 新增 `src/hooks/useIsMobile.ts` + 挂 `src/hooks/index.ts` barrel | `matchMedia("(max-width: 900px)")` 封装,与 `useViewportScale` 的 900 对齐;仅供少数"隐藏 PC 专属 UI"的条件渲染(不改业务逻辑)。底部 Tab 为纯 CSS,不依赖它 |
| 0.4 | **全局兜底** | `src/index.css` | 全局 `*{min-width:0}` 防 flex/grid 溢出、`img/video{max-width:100%}`、`overflow-x:hidden` 兜底、移动端 `body` 字号基准 |
---
## 阶段 1 · 应用外壳 Layout → 底部 Tab 栏(纯 CSS)
核心文件:`src/layouts/Layout/Layout.tsx`、`src/layouts/Layout/Layout.scss`
**改造锚点(均在 `Layout.scss`):**
- `--layout-sidebar-width: 90px`(`:50-51`)、`grid-template-columns`(`:61`)、`grid-template-rows`、`.layoutShell__sidebar`(`:840`)、`.layoutShell__topbar`(`:159`)、`.layoutShell__contentFrame`(`:1069`)。
**≤900px 的 CSS 重排(不动 TSX 结构、不加 state):**
1. `.layoutShell` 网格从"左栏 + 右内容"改为**纵向三行**:顶栏 / 内容区(1fr) / 底部导航。`grid-template-columns: 1fr`,`grid-template-rows: auto 1fr auto`。
2. `.layoutShell__sidebar`:`grid-row` 改为最后一行、`grid-column:1`;`flex-direction: row`、横向排布、`position: sticky/fixed; bottom:0`、高度约 56–64px、`overflow-x:auto`(导航项多时横滑)、加 `env(safe-area-inset-bottom)` 安全区。品牌 logo(`__brand`) 在窄屏隐藏。主导航 `__sideNav` 与底部 `__footer`(subscribe/profile)合并为一条底部 Tab(复用现有 `LAYOUT_SIDE_NAV_ITEMS`(`Layout.tsx:93`) / `LAYOUT_FOOTER_NAV_ITEMS`(`Layout.tsx:286`) 渲染出的 DOM,纯 CSS 重排,不改数据)。
3. `.layoutShell__topbar`:精简——保留登录/头像/积分,隐藏次要项(教程、客服二维码可收进头像菜单,纯 CSS 隐藏);`grid-column:1`。
4. `.layoutShell__contentFrame` / `__contentScroll`:单列,底部留出 Tab 栏高度的 `padding-bottom`
5. **与缩放系统协调**:≤900px `useViewportScale` 已返回 1(不缩放),故 `.layoutShellScaleInner`(`Layout.scss:32-45`)在窄屏 `zoom/transform` 自动为 1,无需改 hook;仅需确认 spacer 占位在 scale=1 时不产生多余留白(`Layout.scss` 内 `layoutShellScaleSpacer` 窄屏归零)。
---
## 阶段 2 · 弹窗统一改造(抓手:`src/dialog/index.tsx`)
**主注入点**:`openDialogWithHistory()`(`src/dialog/index.tsx` ~L96-190)内 barrel 弹窗汇聚到同一个 `Modal.confirm({...config})`。**在此对 `config.style` 做窄屏降级可一处覆盖多数 barrel 弹窗**:≤900px 统一 `width:100%`、`maxWidth:100vw`、近全屏(复用已有 `layoutFullscreenDetailModalShellStyle`(`:57-67`)作窄屏 shell)。
**⚠️ Modal 非单点收口,另有约 9 个散点需单独覆盖:**
- 直接调 `Modal.confirm` 的(3 文件):`src/dialog/pay-subscribe/index.tsx`、`src/pages/Create/panels/FolderPanel/index.tsx`、`src/pages/Profile/index.tsx`。
- 直接写 `<Modal>` JSX 的(5 文件):`src/dialog/LoginRegisterModal/index.tsx`、`src/dialog/asset-details/index.tsx` 及其子 `AssetExpandImageModal`/`AssetDetailRepairModal`、`src/components/DeleteConfirmModal/index.tsx`。
- 每处按同一窄屏 shell 规则给 `style`/`className`。可考虑抽一个共享的窄屏 modal style 常量(放 `src/dialog/index.tsx` 导出)复用,避免重复。
**不走 barrel 的自定义 overlay:** `src/dialog/alice-live-class/`(`--dialog-layout-scale` 缩放)、`src/dialog/app-download-mac/`。
**弹窗逐个(≤900px 目标 = 全屏/单列,内部并排→堆叠):**
| 弹窗目录 | 现状宽度 | 窄屏风险 | 适配要点 |
|---|---|---|---|
| `character-picker` | **1699px/80vw** | 极高 | 重灾区:固定 1699 画布 → 全屏、卡片网格降为 2/1 列 |
| `material-picker` | **1699px/80vw** | 极高 | 同上,全屏 + 单列 |
| `voice-audio-upload` | 1042px/92vw | 高 | 全屏,波形/表单纵向堆叠 |
| `points-detail-modal` | fit/100vw-32 | 高 | 大表格:改卡片式列表或横向滚动容器 |
| `pay-subscribe` | fit/100vw-32 | 高 | 套餐并排→纵向堆叠(配合组件 `subscribe-plan-list`)|
| `character-detail` | 全屏 shell | 中(内容级) | 宽度 OK,内部"预览+信息"双栏→单列纵向 |
| `asset-details` | 全屏 shell | 中(内容级) | 同上;子弹窗 `AssetExpandImageModal`/`AssetDetailRepairModal` 已有 @media,补齐 |
| `folders-asset-details` | 全屏 shell | 中 | 内部双栏→单列 |
| `LoginRegisterModal` | fit/100vw-32 | 中 | 已有 @media540,补到 480;表单全宽 |
| `points-recharge` | fit/100vw-32 | 中 | 已有 @media720/480,校验网格 `repeat(4,87px)` |
| `user-edit` | fit/100vw-32 | 中 | 表单单列全宽 |
| `gateway-apikey` | fit/100vw-32 | 中 | 已有 @media768,补齐 |
| `copyright-deposit` | 885px | 中 | 全屏/单列 |
| `voice-library-picker` | 833px | 中 | 全屏;依赖组件 `VoiceLibraryPicker`(见阶段 4)|
| `contact-service` | 454px/80vw | 低 | 微调 |
| `insufficient-points` | fit | 低 | 微调 |
| `alice-live-class` | 自定义缩放 | 中 | 单独:窄屏改真实全屏布局,脱离 `--dialog-layout-scale` |
| `app-download-mac` | overlay | 低 | 单独:已有 @media720,补齐 |
> 清理:`src/dialog/Untitled`(21 字节杂散文件)随手删除。
---
## 阶段 3 · 页面逐个适配(≤900px 为主,≤768/≤480 收敛)
统一原则:多列网格降列(→2→1)、并排双栏→纵向、定宽 `min-width/固定px`→`min-width:0`+流式、`overflow-x` 区域改可控横滑或换行、按钮/输入窄屏全宽。**均只改 `.scss` 与必要 `className`,不动组件逻辑。**
**优先级 A — 无/弱响应式,窄屏高风险(重点投入)**
| 页面 | 文件 | 适配要点 |
|---|---|---|
| **CharactersCreate** | `src/pages/CharactersCreate/index.{tsx,scss}`(最大 scss 1833 行)+ 子 `CreateRoleModal` | 画布型编辑器,多处 `min-width:720/660/494/430`。窄屏:画布区改纵向流、工具/结果面板堆叠、去定宽。**工作量最大** |
| **Voice** | `src/pages/Voice/index.scss`(4055 行)+ `components/music/*`、`components/speech/VoiceSpeechPanel.tsx`(3226 行)| 左表单/右画廊/播放器/歌词/波形裁剪。窄屏:`repeat(2,…)`→1、`min-width:280/160/125`去定宽、播放器 bar 贴底、裁剪/歌词编辑纵向 |
| **Profile** | `src/pages/Profile/index.{tsx,scss}` | 仅有 @media900:补 768/480;用户信息头行重排、画廊网格降列、批量选择栏适配 |
| **Create/InspirationLibraryPanel** | `panels/InspirationLibraryPanel/*`、`BackgroundAssets/*` | 无断点:新增网格降列 |
**优先级 B — 已有较完整响应式(补齐 + 校验)**
| 页面 | 文件 | 适配要点 |
|---|---|---|
| index(首页)| `src/pages/index/index.scss`(1709 行)| 营销页多处三栏定宽栅格(`150px 1fr 150px` 等);已有 1320/1100/860/640,补 480、去定宽段 |
| Explore(+子 feed)| `src/pages/Explore/*` | 响应式最完整(6→1 列);仅校验 Hero `minmax(420px,633px)` 定宽段 ≤480 |
| Teaching | `src/pages/Teaching/index.scss` | 已 5→1 列;校验 hero 双栏与 `minmax(160px,192fr)` |
| TeachingDocument | `src/pages/TeachingDocument/*` | 402px 定宽侧栏已有单列降级;校验富文本多列 `--rich-column-count` |
| Characters | `src/pages/Characters/*` | 卡片墙 + 横滑区,已有 1280/900/560;补 480 |
| Create 容器 + 其余面板 | `src/pages/Create/*`(`MyCreationsPanel`/`FolderPanel`/`MyFavoritePanel`/`TemplateAssets`/`CharacterAssetsPanel`)| 多含 `overflow-x``repeat(auto-fill,168px)` 定宽单元格;FolderPanel(1687 行 scss)为重点,补断点 |
| subscribe | `src/pages/subscribe/*` + Swiper | 已 820 降单列;校验 `repeat(4,87px)` 积分网格、Swiper 窄屏 slidesPerView |
| content/page | `src/pages/content/page/*` | 已 @media768,基本 OK |
| NotFound | `src/pages/NotFound/index.tsx` | 纯 Tailwind,天然自适应,无需改 |
---
## 阶段 4 · 公共组件适配(`src/components/`)
| 组件 | 适配要点 |
|---|---|
| `subscribe-plan-list` | 重:并排套餐卡(已 @media820)→ 窄屏纵向堆叠/横滑 |
| `VoiceLibraryPicker` | 重:列表+试听并排 → 纵向 |
| `AvatarCropModal` | 重:图片裁剪画布,校验触摸手势与固定尺寸(已 @media768/520)|
| `UserAvatarMenu` | 下拉菜单定宽(已 @media860),窄屏防越界 |
| `AssetGalleryTile` / `PreviewImageThumb` | 网格瓦片:流式宽度、`min-width:0` |
| `AssetAudioPlayer` | 固定宽 → 流式全宽 |
| `UserGuide` | 新手引导覆盖层:定位随窄屏元素校准 |
| `CategoryDropdown` / `FolderMoveSubmenu` / `DeleteConfirmModal` | 固定宽 → `max-width:calc(100vw-32px)` |
| `subscribe-qa-section`(已768)、`TabPill`/`SectionPill`、`HorizontalWheelScroll`、`ErrorBoundary`、`UploadPendingIndicator`、`RouteLoading` | 小改或无需改,逐个校验不溢出 |
---
## 执行顺序建议
阶段 0(基建)→ 阶段 1(外壳 Tab 栏,先让整体骨架能用)→ 阶段 2(弹窗统一注入,一处覆盖多数)→ 阶段 3A(重灾页面)→ 阶段 3B(补齐页面)→ 阶段 4(组件)。每阶段独立可提交(Conventional Commits,如 `style(layout): 移动端底部导航栏`)。
## 验证
- 本地 `npm run dev`(端口 5195,`--host 0.0.0.0` 可真机同网访问)。
- 用 Chrome DevTools 设备模拟逐屏核对:**390px(手机)/ 768px(平板竖)/ 900px(主断点临界)/ 1024px(平板横)/ 1280px(桌面回归)**。
- 重点验证清单:① 首屏无横向滚动条(各断点);② 底部 Tab 可点、内容不被遮挡(safe-area);③ 全部弹窗窄屏不溢出、可关闭;④ 重灾区页面(CharactersCreate/Voice)无内容被裁切;⑤ ≥900px 桌面视觉零回归(缩放系统未被破坏)。
- 收尾 `npm run lint`(零 warning)+ `npm run build`(tsc 类型检查通过)。
- 提示:≤900 与 ≥900 两侧要交叉验证,因为 900 是缩放开关的临界点。
## 注意事项 / 不做
- 不改任何 `src/api/*`、`src/store/*` 业务逻辑与数据流。
- 不新增业务组件;`useIsMobile` 仅为条件渲染纯 UI(如隐藏/切换展示),非业务分支。
- 遵循 `.cursor/skills/react-best-practices`:SCSS 嵌套跟随 DOM、语义化 class;如需新增任何可见文案须走 i18n(本次应尽量零新增文案)。

103
package-lock.json

@ -125,6 +125,7 @@
"integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.7",
"@babel/generator": "^7.29.7",
@ -679,6 +680,7 @@
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@ -1301,6 +1303,7 @@
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@floating-ui/core": "^1.7.5",
"@floating-ui/utils": "^0.2.11"
@ -1557,9 +1560,6 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1581,9 +1581,6 @@
"arm"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1605,9 +1602,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1629,9 +1623,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1653,9 +1644,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1677,9 +1665,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1878,9 +1863,6 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1895,9 +1877,6 @@
"arm"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1912,9 +1891,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1929,9 +1905,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1946,9 +1919,6 @@
"loong64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1963,9 +1933,6 @@
"loong64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -1980,9 +1947,6 @@
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -1997,9 +1961,6 @@
"ppc64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -2014,9 +1975,6 @@
"riscv64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -2031,9 +1989,6 @@
"riscv64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -2048,9 +2003,6 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -2065,9 +2017,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -2082,9 +2031,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -2308,9 +2254,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -2328,9 +2271,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -2348,9 +2288,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@ -2368,9 +2305,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@ -2491,6 +2425,7 @@
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.27.1.tgz",
"integrity": "sha512-rV6Qn4wmC6BxfF+4mu6bqGWj9vA4oXXhsrpXaJL2uhjxeHAGofjwcHof2X84VYzeyXgdlsGmqKie4TAppVXZUQ==",
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@ -2713,6 +2648,7 @@
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.27.1.tgz",
"integrity": "sha512-c2Upru7lj0/ZV/Ibww6cNz6sUS8m6Dp/9uygFhYcZOd3X8M0xBIEk42c6m6SQehkPziVA8QOgNJz7sMqsbz1OQ==",
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@ -2831,6 +2767,7 @@
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.27.1.tgz",
"integrity": "sha512-1Tdx9faw8k0/83V6X+xCDVhV8yElGt95JxeW3YMkKQJI56QdlPz0xOdJPlMiSGJKinPyVier+x9LJD/YZUZIaw==",
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@ -2845,6 +2782,7 @@
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.27.1.tgz",
"integrity": "sha512-Ffjx+vimmBU7zH/KrpXzJid3+pziCe/VL2aexSTP63cyQwKQ65LkFkCKaIsSpFdQQuakVZBGWjCA5RoBV852pw==",
"license": "MIT",
"peer": true,
"dependencies": {
"prosemirror-changeset": "^2.3.0",
"prosemirror-commands": "^1.6.2",
@ -3059,6 +2997,7 @@
"integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@ -3074,6 +3013,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz",
"integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
@ -3084,6 +3024,7 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^18.0.0"
}
@ -3145,6 +3086,7 @@
"integrity": "sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.62.0",
"@typescript-eslint/types": "8.62.0",
@ -3415,6 +3357,7 @@
"integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -3704,6 +3647,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.38",
"caniuse-lite": "^1.0.30001799",
@ -4194,6 +4138,7 @@
"integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
@ -4769,6 +4714,7 @@
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@ -5821,6 +5767,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.29.2"
},
@ -6756,9 +6703,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@ -6780,9 +6724,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@ -6804,9 +6745,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@ -6828,9 +6766,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@ -8733,6 +8668,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@ -8771,6 +8707,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@ -9292,6 +9229,7 @@
"integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"chokidar": "^5.0.0",
"immutable": "^5.1.5",
@ -9880,6 +9818,7 @@
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -10032,6 +9971,7 @@
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -10322,6 +10262,7 @@
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",

Loading…
Cancel
Save