Compare commits
No commits in common. "4fbda2cfc8edbe202ee9d29d7f18962af13e0f68" and "d97955fdc11d8e52a6fb1b7732f294f3aa5f0fba" have entirely different histories.
4fbda2cfc8
...
d97955fdc1
@ -13,7 +13,6 @@
|
||||
| **单用户-单容器** | `modules/user_container_manager.py` 会在登录时启动专属容器,并在退出或空闲超时后自动销毁。CLI/Web/Toolbox 复用同一容器,资源配额(默认 0.5 vCPU / 1GB RAM / 2GB 磁盘)由 `.env` 控制。 |
|
||||
| **容器内文件代理** | `modules/container_file_proxy.py` 通过 `docker exec` 调用内置 Python 脚本,对 `create/read/search/write/modify` 等操作进行沙箱化处理,宿主机不再直写用户代码。 |
|
||||
| **实时监控面板** | Web “用量统计”抽屉实时展示 Token 消耗、容器 CPU/内存、网络上下行速率(0.5s 刷新)以及项目存储占用(5s 刷新)。CLI `/status` 命令也会附带容器状态。 |
|
||||
| **管理员监控面板** | 管理员身份可在「个人空间」中打开 `/admin/monitor`,集中查看用户用量、容器状态、项目存储与上传审计,支持一键刷新与自动轮询。 |
|
||||
| **联网能力 + 最小工具集** | 终端镜像改为 `bridge` 网络并预装 `iputils-ping`,方便验证网络连通性;遇到受限环境可以随时在 `.env` 中切换网络模式。 |
|
||||
|
||||
---
|
||||
@ -122,7 +121,7 @@ python web_server.py
|
||||
|
||||
## 开发建议
|
||||
|
||||
1. **安全**:新增模块前请优先考虑是否可以在容器中实现,避免回退宿主机;如需联网,务必评估外部依赖。上传检测现阶段默认关闭 ClamAV(`UPLOAD_CLAMAV_ENABLED=0`),以免 1GB+ 的常驻内存占用,必要时可以在环境变量中显式打开。
|
||||
1. **安全**:新增模块前请优先考虑是否可以在容器中实现,避免回退宿主机;如需联网,务必评估外部依赖。
|
||||
2. **日志**:尽量使用 `utils.logger.setup_logger`,便于统一收集。
|
||||
3. **测试**:`users/<username>/project/test_scripts/` 提供内存压测脚本,可验证容器限制是否生效;可在 `test/` 下添加更多集成测试。
|
||||
4. **文档**:第二阶段总结见 `doc/phases/phase2_summary.md`,安全基线更新见 `doc/security/security_review.md`。
|
||||
|
||||
@ -42,8 +42,7 @@ def _parse_bool(value: str, default: bool = True) -> bool:
|
||||
return str(value).strip().lower() not in {"0", "false", "no", "off"}
|
||||
|
||||
|
||||
# 默认关闭 ClamAV 扫描以降低常驻内存占用,可通过设置环境变量重新开启
|
||||
UPLOAD_CLAMAV_ENABLED = _parse_bool(os.environ.get("UPLOAD_CLAMAV_ENABLED", "0"), default=False)
|
||||
UPLOAD_CLAMAV_ENABLED = _parse_bool(os.environ.get("UPLOAD_CLAMAV_ENABLED", "1"), default=True)
|
||||
UPLOAD_CLAMAV_BIN = os.environ.get("UPLOAD_CLAMAV_BIN", "clamdscan")
|
||||
UPLOAD_CLAMAV_ARGS = tuple(
|
||||
shlex.split(os.environ.get("UPLOAD_CLAMAV_ARGS", "--fdpass --no-summary --stdout"))
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -336,9 +336,7 @@ class WebTerminal(MainTerminal):
|
||||
def broadcast(self, event_type: str, data: Dict):
|
||||
"""广播事件到WebSocket"""
|
||||
if self.message_callback:
|
||||
payload = dict(data or {})
|
||||
payload.setdefault('conversation_id', self.context_manager.current_conversation_id)
|
||||
self.message_callback(event_type, payload)
|
||||
self.message_callback(event_type, data)
|
||||
|
||||
# ===========================================
|
||||
# 覆盖父类方法,添加Web特有的广播功能
|
||||
@ -483,16 +481,10 @@ class WebTerminal(MainTerminal):
|
||||
|
||||
# 特殊处理某些错误类型
|
||||
if not success:
|
||||
error_msg = result_data.get('error')
|
||||
if not error_msg:
|
||||
error_msg = result_data.get('message')
|
||||
if not error_msg:
|
||||
error_msg = '执行失败'
|
||||
if not isinstance(error_msg, str):
|
||||
error_msg = str(error_msg)
|
||||
error_msg = result_data.get('error', '执行失败')
|
||||
|
||||
# 检查是否是参数预检查失败
|
||||
if error_msg and ('参数过大' in error_msg or '内容过长' in error_msg):
|
||||
if '参数过大' in error_msg or '内容过长' in error_msg:
|
||||
self.broadcast('tool_execution_end', {
|
||||
'tool': tool_name,
|
||||
'success': False,
|
||||
@ -501,7 +493,7 @@ class WebTerminal(MainTerminal):
|
||||
'error_type': 'parameter_too_long',
|
||||
'suggestion': result_data.get('suggestion', '建议分块处理')
|
||||
})
|
||||
elif error_msg and ('JSON解析' in error_msg or '参数解析失败' in error_msg):
|
||||
elif 'JSON解析' in error_msg or '参数解析失败' in error_msg:
|
||||
self.broadcast('tool_execution_end', {
|
||||
'tool': tool_name,
|
||||
'success': False,
|
||||
|
||||
@ -1,237 +0,0 @@
|
||||
使用统一 diff(`@@` 块、`-`/`+`/空格行)对单个文件做精确编辑:追加、插入、替换、删除都可以在一次调用里完成。
|
||||
硬性规则:
|
||||
|
||||
1) 补丁必须被 `*** Begin Patch` 与 `*** End Patch` 包裹。
|
||||
2) 每个修改块必须以 `@@ [id:数字]` 开头。
|
||||
3) 块内每一行只能是三类之一:
|
||||
- 上下文行:以空格开头(` ␠`),表示“文件里必须原样存在”的锚点;
|
||||
- 删除行:以 `-` 开头,表示要从文件中移除的原文;
|
||||
- 新增行:以 `+` 开头,表示要写入的新内容。
|
||||
4) 任何“想新增/想删除/想替换”的内容都必须逐行写 `+` 或 `-`;如果你把多行新内容直接贴上去却不加 `+`,它会被当成上下文锚点去匹配原文件,极易导致“未找到匹配的原文”。
|
||||
5) 重要语义:一个块里如果完全没有上下文行(空格开头)也没有删除行(`-`),那么它会被视为“仅追加(append-only)”,也就是把所有 `+` 行追加到文件末尾——这对“给空文件写正文”很合适,但对“插入到中间”是错误的。
|
||||
|
||||
正面案例(至少 5 个,且都包含多行原文/多处修改)
|
||||
|
||||
1) 给空文件写完整正文(追加到末尾;空文件=正确)
|
||||
目标:新建 README.md 后一次性写入标题、安装、用法、FAQ(多段落、多行)。
|
||||
要点:没有上下文/删除行 → 追加模式;空文件时最常用。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
+# 项目名称
|
||||
+
|
||||
+一个简短说明:这个项目用于……
|
||||
+
|
||||
+## 安装
|
||||
+
|
||||
+```bash
|
||||
+pip install -r requirements.txt
|
||||
+```
|
||||
+
|
||||
+## 快速开始
|
||||
+
|
||||
+```bash
|
||||
+python main.py
|
||||
+```
|
||||
+
|
||||
+## 常见问题
|
||||
+
|
||||
+- Q: 为什么会报 xxx?
|
||||
+ A: 先检查 yyy,再确认 zzz。
|
||||
+
|
||||
*** End Patch
|
||||
|
||||
2) “不删除,直接插入内容”到函数内部(必须用上下文锚定插入位置)
|
||||
目标:在 def build_prompt(...): 里插入日志与参数归一化,但不改动其它行。
|
||||
要点:插入发生在“两个上下文行之间”,上下文必须精确(包含缩进)。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
def build_prompt(user_text: str, system_text: str, tags: list):
|
||||
prompt_parts = []
|
||||
+ # 参数归一化:去掉首尾空白,避免模型误判
|
||||
+ user_text = (user_text or "").strip()
|
||||
+ system_text = (system_text or "").strip()
|
||||
+
|
||||
+ logger.debug("build_prompt: tags=%s, user_len=%d", tags, len(user_text))
|
||||
prompt_parts.append(system_text)
|
||||
prompt_parts.append(user_text)
|
||||
if tags:
|
||||
prompt_parts.append("TAGS: " + ",".join(tags))
|
||||
*** End Patch
|
||||
|
||||
3) 复杂替换:整段函数重构(多行 old/new + 保留稳定上下文)
|
||||
目标:把旧的 apply_patch()(弱校验)替换成新实现(多分支、异常信息更清晰)。
|
||||
要点:替换不是“改一行”,而是“删一段、加一段”,并用函数签名/相邻代码作锚点。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
class FilePatcher:
|
||||
def __init__(self, root: Path):
|
||||
self.root = root
|
||||
|
||||
def apply_patch(self, path: str, patch_text: str) -> dict:
|
||||
- # old: naive replace
|
||||
- content = (self.root / path).read_text(encoding="utf-8")
|
||||
- content = content.replace("foo", "bar")
|
||||
- (self.root / path).write_text(content, encoding="utf-8")
|
||||
- return {"success": True}
|
||||
+ full_path = (self.root / path).resolve()
|
||||
+ if self.root not in full_path.parents and full_path != self.root:
|
||||
+ return {"success": False, "error": "非法路径:越界访问"}
|
||||
+
|
||||
+ if "*** Begin Patch" not in patch_text or "*** End Patch" not in patch_text:
|
||||
+ return {"success": False, "error": "补丁格式错误:缺少 Begin/End 标记"}
|
||||
+
|
||||
+ try:
|
||||
+ original = full_path.read_text(encoding="utf-8")
|
||||
+ except Exception as e:
|
||||
+ return {"success": False, "error": f"读取失败: {e}"}
|
||||
+
|
||||
+ # 这里省略:解析 blocks、逐块应用、失败回滚等
|
||||
+ updated = original
|
||||
+ try:
|
||||
+ full_path.write_text(updated, encoding="utf-8")
|
||||
+ except Exception as e:
|
||||
+ return {"success": False, "error": f"写入失败: {e}"}
|
||||
+
|
||||
+ return {"success": True, "message": "已应用补丁"}
|
||||
*** End Patch
|
||||
|
||||
4) 复杂多块:同一文件里同时“加 import + 替换逻辑 + 插入新 helper + 删除旧函数”
|
||||
目标:一次调用完成 4 种操作,且每块都有足够上下文,避免误匹配。
|
||||
要点:不同区域用不同 @@ [id:n] 分块,互不干扰。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
-import json
|
||||
+import json
|
||||
+import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ [id:2]
|
||||
def normalize_user_input(text: str) -> str:
|
||||
- return text
|
||||
+ text = (text or "").strip()
|
||||
+ # 压缩多余空白,减少提示词抖动
|
||||
+ text = re.sub(r"\\s+", " ", text)
|
||||
+ return text
|
||||
|
||||
@@ [id:3]
|
||||
def load_config(path: str) -> dict:
|
||||
cfg_path = Path(path)
|
||||
if not cfg_path.exists():
|
||||
return {}
|
||||
data = cfg_path.read_text(encoding="utf-8")
|
||||
return json.loads(data)
|
||||
+
|
||||
+def safe_get(cfg: dict, key: str, default=None):
|
||||
+ if not isinstance(cfg, dict):
|
||||
+ return default
|
||||
+ return cfg.get(key, default)
|
||||
|
||||
@@ [id:4]
|
||||
-def legacy_parse_flags(argv):
|
||||
- # deprecated, kept for compatibility
|
||||
- flags = {}
|
||||
- for item in argv:
|
||||
- if item.startswith("--"):
|
||||
- k, _, v = item[2:].partition("=")
|
||||
- flags[k] = v or True
|
||||
- return flags
|
||||
-
|
||||
def main():
|
||||
cfg = load_config("config.json")
|
||||
# ...
|
||||
*** End Patch
|
||||
|
||||
5) 删除示例:删除一整段“废弃配置块”,并顺手修正周围空行(多行删除 + 上下文)
|
||||
目标:删掉 DEPRECATED_* 配置和旧注释,确保删除位置精确。
|
||||
要点:删除行必须逐行 `-`;保留上下文行确保定位。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
# ==============================
|
||||
# Runtime Config
|
||||
# ==============================
|
||||
-DEPRECATED_TIMEOUT = 5
|
||||
-DEPRECATED_RETRIES = 1
|
||||
-# 注意:这些字段将在下个版本移除
|
||||
-# 请迁移到 NEW_TIMEOUT / NEW_RETRIES
|
||||
NEW_TIMEOUT = 30
|
||||
NEW_RETRIES = 3
|
||||
*** End Patch
|
||||
|
||||
如何写“带上下文”的正确姿势(要点)
|
||||
|
||||
- 上下文要选“稳定锚点”:函数签名、类名、关键注释、紧邻的两三行缩进代码。
|
||||
- 不要用“容易变的行”当唯一锚点:时间戳、日志序号、随机 id、生成内容片段。
|
||||
- 上下文必须字节级一致(空格/Tab/大小写/标点都算),否则会匹配失败。
|
||||
|
||||
反面案例(至少 3 个,且都是“真实会踩坑”的类型)
|
||||
|
||||
反例 A(来自一次常见错误):空文件时只有第一行加了 `+`,后面直接贴正文
|
||||
这会让后面的正文变成“上下文锚点”,工具会去空文件里找这些原文,必然失败(常见报错:未找到匹配的原文)。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
+
|
||||
仰望U9X·电驭苍穹
|
||||
银箭破空电光闪
|
||||
三千马力云中藏
|
||||
*** End Patch
|
||||
|
||||
正确做法:正文每一行都要写 `+`(包括空行也写 `+`)。
|
||||
|
||||
(对应的正确 patch 示例:向空文件追加多行)
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
+
|
||||
+仰望U9X·电驭苍穹
|
||||
+银箭破空电光闪
|
||||
+三千马力云中藏
|
||||
*** End Patch
|
||||
|
||||
反例 B:想“插入到中间”,却只写 `+`(没有任何上下文/删除行)
|
||||
这种块会被当成“追加到文件末尾”,结果内容跑到文件最后,不会插入到你以为的位置。
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
+# 我以为会插到某个函数上面
|
||||
+print("hello")
|
||||
*** End Patch
|
||||
|
||||
正确做法:用上下文锚定插入点(见正面案例 2)。
|
||||
|
||||
(对应的正确 patch 示例:用上下文把内容插入到函数内部,而不是追加到文件末尾)
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
def main():
|
||||
config = load_config("config.json")
|
||||
+ # 这里插入:启动提示(不会移动到文件末尾)
|
||||
+ print("hello")
|
||||
run(config)
|
||||
*** End Patch
|
||||
|
||||
反例 C:补丁在第一个 `@@` 之前出现内容 / 或漏掉 Begin/End 标记
|
||||
解析会直接报格式错误(例如:“在检测到第一个 @@ 块之前出现内容”、“缺少 Begin/End 标记”)。
|
||||
|
||||
(错误形态示意)
|
||||
这里先写了一段说明文字(没有 @@)
|
||||
@@ [id:1]
|
||||
+...
|
||||
|
||||
正确做法:确保第一段非空内容必须从 `@@ [id:n]` 开始,并且整体有 Begin/End。
|
||||
|
||||
(对应的正确 patch 示例:完整结构、第一段内容从 @@ 块开始)
|
||||
|
||||
*** Begin Patch
|
||||
@@ [id:1]
|
||||
# ==============================
|
||||
# Runtime Config
|
||||
# ==============================
|
||||
+# 说明:此处新增一行注释作为示例
|
||||
NEW_TIMEOUT = 30
|
||||
*** End Patch
|
||||
@ -20,15 +20,8 @@ from config import (
|
||||
SUB_AGENT_TASKS_BASE_DIR,
|
||||
)
|
||||
from utils.logger import setup_logger
|
||||
import logging
|
||||
|
||||
# 静音子智能体日志(交由前端提示/brief_log处理)
|
||||
logger = setup_logger(__name__)
|
||||
logger.setLevel(logging.CRITICAL)
|
||||
logger.disabled = True
|
||||
logger.propagate = False
|
||||
for h in list(logger.handlers):
|
||||
logger.removeHandler(h)
|
||||
TERMINAL_STATUSES = {"completed", "failed", "timeout"}
|
||||
|
||||
|
||||
|
||||
@ -152,10 +152,6 @@ class UserManager:
|
||||
def list_invite_codes(self):
|
||||
return list(self._invites.values())
|
||||
|
||||
def list_users(self) -> Dict[str, UserRecord]:
|
||||
"""返回当前注册用户的浅拷贝字典,键为用户名。"""
|
||||
return dict(self._users)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Internal helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
75
package-lock.json
generated
75
package-lock.json
generated
@ -8,8 +8,6 @@
|
||||
"name": "ai-agent-frontend",
|
||||
"version": "4.1.0",
|
||||
"dependencies": {
|
||||
"@types/html2canvas": "^0.5.35",
|
||||
"html2canvas": "^1.4.1",
|
||||
"katex": "^0.16.9",
|
||||
"marked": "^11.1.0",
|
||||
"pinia": "^3.0.4",
|
||||
@ -1305,24 +1303,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/html2canvas": {
|
||||
"version": "0.5.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/html2canvas/-/html2canvas-0.5.35.tgz",
|
||||
"integrity": "sha512-1A2dtWZbOIZ+rUK8jmAx1We/EiNV+5vScpphU3AF14Vby6COIazi/9StosrvlVCqlQegRhsEgZf7QYOuWbwuuA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/jquery": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jquery": {
|
||||
"version": "3.5.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz",
|
||||
"integrity": "sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/sizzle": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@ -1347,12 +1327,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/sizzle": {
|
||||
"version": "2.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz",
|
||||
"integrity": "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
|
||||
@ -1892,15 +1866,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-arraybuffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/birpc": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.8.0.tgz",
|
||||
@ -2056,15 +2021,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/css-line-break": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
|
||||
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@ -2791,19 +2747,6 @@
|
||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-line-break": "^2.1.0",
|
||||
"text-segmentation": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@ -3784,15 +3727,6 @@
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"node_modules/text-segmentation": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
||||
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
@ -3890,15 +3824,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/utrie": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
|
||||
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-arraybuffer": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.21",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/html2canvas": "^0.5.35",
|
||||
"html2canvas": "^1.4.1",
|
||||
"katex": "^0.16.9",
|
||||
"marked": "^11.1.0",
|
||||
"pinia": "^3.0.4",
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
hello
|
||||
world
|
||||
@ -1,100 +0,0 @@
|
||||
"""Moonshot Kimi 缓存命中测试脚本。
|
||||
|
||||
This script replays the three-turn conversation described in the QA instructions
|
||||
to inspect whether the `cached_tokens` field grows across requests. 结果会被写入
|
||||
`logs/kimi_cache_usage.json`,方便后续排查缓存命中情况。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
SYSTEM_PROMPT = (
|
||||
"你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。"
|
||||
"你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,"
|
||||
"种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
|
||||
)
|
||||
|
||||
QUERIES = ["你好!", "地球的自转周期是多少?", "月球呢?"]
|
||||
ENV_PATH = Path(".env")
|
||||
OUTPUT_PATH = Path("logs/kimi_cache_usage.json")
|
||||
|
||||
|
||||
def load_env_values(path: Path) -> Dict[str, str]:
|
||||
"""Load simple KEY=VALUE pairs from `.env`."""
|
||||
data: Dict[str, str] = {}
|
||||
for line in path.read_text(encoding="utf-8").splitlines():
|
||||
stripped = line.strip()
|
||||
if not stripped or stripped.startswith("#") or "=" not in stripped:
|
||||
continue
|
||||
key, value = stripped.split("=", 1)
|
||||
data[key.strip()] = value.strip()
|
||||
return data
|
||||
|
||||
|
||||
def ensure_required(keys: List[str], env: Dict[str, str]) -> None:
|
||||
"""Guard that required env variables exist."""
|
||||
missing = [key for key in keys if not env.get(key)]
|
||||
if missing:
|
||||
raise RuntimeError(f"Missing required env vars: {', '.join(missing)}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
env = load_env_values(ENV_PATH)
|
||||
ensure_required(["AGENT_API_KEY", "AGENT_API_BASE_URL", "AGENT_MODEL_ID"], env)
|
||||
client = OpenAI(api_key=env["AGENT_API_KEY"], base_url=env["AGENT_API_BASE_URL"])
|
||||
model = env["AGENT_MODEL_ID"]
|
||||
|
||||
history: List[Dict[str, str]] = [{"role": "system", "content": SYSTEM_PROMPT}]
|
||||
records: List[Dict[str, Any]] = []
|
||||
|
||||
for idx, query in enumerate(QUERIES, start=1):
|
||||
history.append({"role": "user", "content": query})
|
||||
completion = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=history,
|
||||
temperature=0.6,
|
||||
)
|
||||
answer = completion.choices[0].message.content
|
||||
history.append({"role": "assistant", "content": answer})
|
||||
payload = completion.model_dump()
|
||||
usage_dict = payload.get("usage", {})
|
||||
records.append(
|
||||
{
|
||||
"round": idx,
|
||||
"query": query,
|
||||
"response": answer,
|
||||
"usage": usage_dict,
|
||||
}
|
||||
)
|
||||
|
||||
usage_round1 = records[0]["usage"]
|
||||
usage_round2 = records[1]["usage"]
|
||||
usage_round3 = records[2]["usage"]
|
||||
|
||||
analysis = {
|
||||
"round2_cached_equals_round1_total": usage_round2.get("cached_tokens")
|
||||
== usage_round1.get("total_tokens"),
|
||||
"round3_cached_equals_round2_total": usage_round3.get("cached_tokens")
|
||||
== usage_round2.get("total_tokens"),
|
||||
"cached_tokens_sequence": [
|
||||
usage_round1.get("cached_tokens"),
|
||||
usage_round2.get("cached_tokens"),
|
||||
usage_round3.get("cached_tokens"),
|
||||
],
|
||||
}
|
||||
|
||||
OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUTPUT_PATH.write_text(
|
||||
json.dumps({"details": records, "analysis": analysis}, ensure_ascii=False, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(f"Wrote results to {OUTPUT_PATH}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,68 +0,0 @@
|
||||
"""Official Moonshot sample adapted to print raw JSON responses."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
|
||||
def resolve_env_value(keys: tuple[str, ...], *, default: str | None = None) -> str:
|
||||
"""Try process env first, then fall back to `.env` file."""
|
||||
for key in keys:
|
||||
value = os.environ.get(key)
|
||||
if value:
|
||||
return value
|
||||
env_path = Path(".env")
|
||||
if env_path.exists():
|
||||
for line in env_path.read_text(encoding="utf-8").splitlines():
|
||||
stripped = line.strip()
|
||||
if not stripped or stripped.startswith("#") or "=" not in stripped:
|
||||
continue
|
||||
env_key, env_value = stripped.split("=", 1)
|
||||
if env_key in keys and env_value.strip():
|
||||
return env_value.strip()
|
||||
if default is not None:
|
||||
return default
|
||||
raise RuntimeError(f"Missing required environment variable from {keys}.")
|
||||
|
||||
|
||||
client = OpenAI(
|
||||
api_key=resolve_env_value(("MOONSHOT_API_KEY", "AGENT_API_KEY")),
|
||||
base_url=resolve_env_value(
|
||||
("MOONSHOT_BASE_URL", "AGENT_API_BASE_URL"), default="https://api.moonshot.cn/v1"
|
||||
),
|
||||
)
|
||||
|
||||
history = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": (
|
||||
"你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。"
|
||||
"你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,"
|
||||
"种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
|
||||
),
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def chat(query: str, history_list: list[Dict[str, str]]) -> Dict[str, Any]:
|
||||
history_list.append({"role": "user", "content": query})
|
||||
completion = client.chat.completions.create(
|
||||
model="kimi-k2-turbo-preview",
|
||||
messages=history_list,
|
||||
temperature=0.6,
|
||||
)
|
||||
result_content = completion.choices[0].message.content
|
||||
history_list.append({"role": "assistant", "content": result_content})
|
||||
return completion.model_dump()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
earth = chat("地球的自转周期是多少?", history)
|
||||
moon = chat("月球呢?", history)
|
||||
print(json.dumps(earth, ensure_ascii=False, indent=2))
|
||||
print(json.dumps(moon, ensure_ascii=False, indent=2))
|
||||
@ -1,54 +0,0 @@
|
||||
"""Minimal Moonshot sample that also prints the usage payload."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
|
||||
client = OpenAI(
|
||||
api_key="sk-xW0xjfQM6Mp9ZCWMLlnHiRJcpEOIZPTkXcN0dQ15xpZSuw2y",
|
||||
base_url="https://api.moonshot.cn/v1",
|
||||
)
|
||||
|
||||
history: List[Dict[str, str]] = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": (
|
||||
"你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。"
|
||||
"你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,"
|
||||
"种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
|
||||
),
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def chat(query: str, history_list: List[Dict[str, str]]) -> Tuple[str, Dict[str, int]]:
|
||||
history_list.append({"role": "user", "content": query})
|
||||
completion = client.chat.completions.create(
|
||||
model="kimi-k2-0905-preview",
|
||||
messages=history_list,
|
||||
temperature=0.6,
|
||||
)
|
||||
result = completion.choices[0].message.content
|
||||
history_list.append({"role": "assistant", "content": result})
|
||||
usage_dict: Dict[str, int] = (
|
||||
completion.usage.model_dump() if completion.usage else {}
|
||||
)
|
||||
return result, usage_dict
|
||||
|
||||
|
||||
def main() -> None:
|
||||
earth_answer, earth_usage = chat("地球的自转周期是多少?", history)
|
||||
moon_answer, moon_usage = chat("月球呢?", history)
|
||||
|
||||
print(earth_answer)
|
||||
print(json.dumps(earth_usage, ensure_ascii=False, indent=2))
|
||||
print(moon_answer)
|
||||
print(json.dumps(moon_usage, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"pages": {
|
||||
"/layout": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js",
|
||||
"static/css/app/layout.css",
|
||||
"static/chunks/app/layout.js"
|
||||
],
|
||||
"/page": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js",
|
||||
"static/css/app/page.css",
|
||||
"static/chunks/app/page.js"
|
||||
],
|
||||
"/_not-found/page": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js",
|
||||
"static/chunks/app/_not-found/page.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"polyfillFiles": [
|
||||
"static/chunks/polyfills.js"
|
||||
],
|
||||
"devFiles": [],
|
||||
"ampDevFiles": [],
|
||||
"lowPriorityFiles": [
|
||||
"static/development/_buildManifest.js",
|
||||
"static/development/_ssgManifest.js"
|
||||
],
|
||||
"rootMainFiles": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js"
|
||||
],
|
||||
"rootMainFilesTree": {},
|
||||
"pages": {
|
||||
"/_app": []
|
||||
},
|
||||
"ampFirstPages": []
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
{"encryption.key":"nIrtn86Hm0WlHEfVtm35NcUkmbNTI0U+eXfpVfP5kSI=","encryption.expire_at":1765854859753}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
{"type": "commonjs"}
|
||||
@ -1 +0,0 @@
|
||||
{}
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"/_not-found/page": "app/_not-found/page.js",
|
||||
"/page": "app/page.js"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]"
|
||||
@ -1,22 +0,0 @@
|
||||
globalThis.__BUILD_MANIFEST = {
|
||||
"polyfillFiles": [
|
||||
"static/chunks/polyfills.js"
|
||||
],
|
||||
"devFiles": [],
|
||||
"ampDevFiles": [],
|
||||
"lowPriorityFiles": [],
|
||||
"rootMainFiles": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js"
|
||||
],
|
||||
"rootMainFilesTree": {},
|
||||
"pages": {
|
||||
"/_app": []
|
||||
},
|
||||
"ampFirstPages": []
|
||||
};
|
||||
globalThis.__BUILD_MANIFEST.lowPriorityFiles = [
|
||||
"/static/" + process.env.__NEXT_BUILD_ID + "/_buildManifest.js",
|
||||
,"/static/" + process.env.__NEXT_BUILD_ID + "/_ssgManifest.js",
|
||||
|
||||
];
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"middleware": {},
|
||||
"functions": {},
|
||||
"sortedMiddleware": []
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
self.__REACT_LOADABLE_MANIFEST="{}"
|
||||
@ -1 +0,0 @@
|
||||
self.__NEXT_FONT_MANIFEST="{\"pages\":{},\"app\":{\"/Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/layout\":[\"static/media/e4af272ccee01ff0-s.p.woff2\"],\"/Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/page\":[\"static/media/e4af272ccee01ff0-s.p.woff2\"]},\"appUsingSizeAdjust\":true,\"pagesUsingSizeAdjust\":false}"
|
||||
@ -1 +0,0 @@
|
||||
{"pages":{},"app":{"/Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/layout":["static/media/e4af272ccee01ff0-s.p.woff2"],"/Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/page":["static/media/e4af272ccee01ff0-s.p.woff2"]},"appUsingSizeAdjust":true,"pagesUsingSizeAdjust":false}
|
||||
@ -1 +0,0 @@
|
||||
{}
|
||||
@ -1 +0,0 @@
|
||||
self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY\"\n}"
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"node": {},
|
||||
"edge": {},
|
||||
"encryptionKey": "nIrtn86Hm0WlHEfVtm35NcUkmbNTI0U+eXfpVfP5kSI="
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,75 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
exports.id = "vendor-chunks/@swc";
|
||||
exports.ids = ["vendor-chunks/@swc"];
|
||||
exports.modules = {
|
||||
|
||||
/***/ "(rsc)/./node_modules/@swc/helpers/esm/_interop_require_default.js":
|
||||
/*!*******************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_interop_require_default.js ***!
|
||||
\*******************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _interop_require_default)\n/* harmony export */ });\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9faW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQuanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ3lDIiwic291cmNlcyI6WyIvVXNlcnMvam9qby9EZXNrdG9wL2FnZW50cy/mraPlnKjkv67lpI3kuK0vYWdlbnRzL3NjcmlwdHMvbGlxdWlkLWdsYXNzLWRlbW8vbm9kZV9tb2R1bGVzL0Bzd2MvaGVscGVycy9lc20vX2ludGVyb3BfcmVxdWlyZV9kZWZhdWx0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdChvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTtcbn1cbmV4cG9ydCB7IF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdCBhcyBfIH07XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(rsc)/./node_modules/@swc/helpers/esm/_interop_require_default.js\n");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "(ssr)/./node_modules/@swc/helpers/esm/_class_private_field_loose_base.js":
|
||||
/*!**************************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_class_private_field_loose_base.js ***!
|
||||
\**************************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _class_private_field_loose_base)\n/* harmony export */ });\nfunction _class_private_field_loose_base(receiver, privateKey) {\n if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {\n throw new TypeError(\"attempted to use private field on non-instance\");\n }\n\n return receiver;\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9fY2xhc3NfcHJpdmF0ZV9maWVsZF9sb29zZV9iYXNlLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ2dEIiwic291cmNlcyI6WyIvVXNlcnMvam9qby9EZXNrdG9wL2FnZW50cy/mraPlnKjkv67lpI3kuK0vYWdlbnRzL3NjcmlwdHMvbGlxdWlkLWdsYXNzLWRlbW8vbm9kZV9tb2R1bGVzL0Bzd2MvaGVscGVycy9lc20vX2NsYXNzX3ByaXZhdGVfZmllbGRfbG9vc2VfYmFzZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfY2xhc3NfcHJpdmF0ZV9maWVsZF9sb29zZV9iYXNlKHJlY2VpdmVyLCBwcml2YXRlS2V5KSB7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVjZWl2ZXIsIHByaXZhdGVLZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhdHRlbXB0ZWQgdG8gdXNlIHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlXCIpO1xuICAgIH1cblxuICAgIHJldHVybiByZWNlaXZlcjtcbn1cbmV4cG9ydCB7IF9jbGFzc19wcml2YXRlX2ZpZWxkX2xvb3NlX2Jhc2UgYXMgXyB9O1xuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6WzBdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/@swc/helpers/esm/_class_private_field_loose_base.js\n");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "(ssr)/./node_modules/@swc/helpers/esm/_class_private_field_loose_key.js":
|
||||
/*!*************************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_class_private_field_loose_key.js ***!
|
||||
\*************************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _class_private_field_loose_key)\n/* harmony export */ });\nvar id = 0;\n\nfunction _class_private_field_loose_key(name) {\n return \"__private_\" + id++ + \"_\" + name;\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9fY2xhc3NfcHJpdmF0ZV9maWVsZF9sb29zZV9rZXkuanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUMrQyIsInNvdXJjZXMiOlsiL1VzZXJzL2pvam8vRGVza3RvcC9hZ2VudHMv5q2j5Zyo5L+u5aSN5LitL2FnZW50cy9zY3JpcHRzL2xpcXVpZC1nbGFzcy1kZW1vL25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvZXNtL19jbGFzc19wcml2YXRlX2ZpZWxkX2xvb3NlX2tleS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgaWQgPSAwO1xuXG5mdW5jdGlvbiBfY2xhc3NfcHJpdmF0ZV9maWVsZF9sb29zZV9rZXkobmFtZSkge1xuICAgIHJldHVybiBcIl9fcHJpdmF0ZV9cIiArIGlkKysgKyBcIl9cIiArIG5hbWU7XG59XG5leHBvcnQgeyBfY2xhc3NfcHJpdmF0ZV9maWVsZF9sb29zZV9rZXkgYXMgXyB9O1xuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6WzBdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/@swc/helpers/esm/_class_private_field_loose_key.js\n");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "(ssr)/./node_modules/@swc/helpers/esm/_interop_require_default.js":
|
||||
/*!*******************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_interop_require_default.js ***!
|
||||
\*******************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _interop_require_default)\n/* harmony export */ });\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9faW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQuanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ3lDIiwic291cmNlcyI6WyIvVXNlcnMvam9qby9EZXNrdG9wL2FnZW50cy/mraPlnKjkv67lpI3kuK0vYWdlbnRzL3NjcmlwdHMvbGlxdWlkLWdsYXNzLWRlbW8vbm9kZV9tb2R1bGVzL0Bzd2MvaGVscGVycy9lc20vX2ludGVyb3BfcmVxdWlyZV9kZWZhdWx0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdChvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTtcbn1cbmV4cG9ydCB7IF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdCBhcyBfIH07XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/@swc/helpers/esm/_interop_require_default.js\n");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "(ssr)/./node_modules/@swc/helpers/esm/_interop_require_wildcard.js":
|
||||
/*!********************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_interop_require_wildcard.js ***!
|
||||
\********************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _interop_require_wildcard)\n/* harmony export */ });\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n\n return (_getRequireWildcardCache = function(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interop_require_wildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) return obj;\n if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") return { default: obj };\n\n var cache = _getRequireWildcardCache(nodeInterop);\n\n if (cache && cache.has(obj)) return cache.get(obj);\n\n var newObj = { __proto__: null };\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);\n else newObj[key] = obj[key];\n }\n }\n\n newObj.default = obj;\n\n if (cache) cache.set(obj, newObj);\n\n return newObj;\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9faW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSx1RkFBdUY7O0FBRXZGOztBQUVBOztBQUVBLG1CQUFtQjtBQUNuQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQzBDIiwic291cmNlcyI6WyIvVXNlcnMvam9qby9EZXNrdG9wL2FnZW50cy/mraPlnKjkv67lpI3kuK0vYWdlbnRzL3NjcmlwdHMvbGlxdWlkLWdsYXNzLWRlbW8vbm9kZV9tb2R1bGVzL0Bzd2MvaGVscGVycy9lc20vX2ludGVyb3BfcmVxdWlyZV93aWxkY2FyZC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUobm9kZUludGVyb3ApIHtcbiAgICBpZiAodHlwZW9mIFdlYWtNYXAgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgY2FjaGVCYWJlbEludGVyb3AgPSBuZXcgV2Vha01hcCgpO1xuICAgIHZhciBjYWNoZU5vZGVJbnRlcm9wID0gbmV3IFdlYWtNYXAoKTtcblxuICAgIHJldHVybiAoX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlID0gZnVuY3Rpb24obm9kZUludGVyb3ApIHtcbiAgICAgICAgcmV0dXJuIG5vZGVJbnRlcm9wID8gY2FjaGVOb2RlSW50ZXJvcCA6IGNhY2hlQmFiZWxJbnRlcm9wO1xuICAgIH0pKG5vZGVJbnRlcm9wKTtcbn1cbmZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQob2JqLCBub2RlSW50ZXJvcCkge1xuICAgIGlmICghbm9kZUludGVyb3AgJiYgb2JqICYmIG9iai5fX2VzTW9kdWxlKSByZXR1cm4gb2JqO1xuICAgIGlmIChvYmogPT09IG51bGwgfHwgdHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2Ygb2JqICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiB7IGRlZmF1bHQ6IG9iaiB9O1xuXG4gICAgdmFyIGNhY2hlID0gX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlKG5vZGVJbnRlcm9wKTtcblxuICAgIGlmIChjYWNoZSAmJiBjYWNoZS5oYXMob2JqKSkgcmV0dXJuIGNhY2hlLmdldChvYmopO1xuXG4gICAgdmFyIG5ld09iaiA9IHsgX19wcm90b19fOiBudWxsIH07XG4gICAgdmFyIGhhc1Byb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICBpZiAoa2V5ICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICAgICAgICB2YXIgZGVzYyA9IGhhc1Byb3BlcnR5RGVzY3JpcHRvciA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBrZXkpIDogbnVsbDtcbiAgICAgICAgICAgIGlmIChkZXNjICYmIChkZXNjLmdldCB8fCBkZXNjLnNldCkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuZXdPYmosIGtleSwgZGVzYyk7XG4gICAgICAgICAgICBlbHNlIG5ld09ialtrZXldID0gb2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZXdPYmouZGVmYXVsdCA9IG9iajtcblxuICAgIGlmIChjYWNoZSkgY2FjaGUuc2V0KG9iaiwgbmV3T2JqKTtcblxuICAgIHJldHVybiBuZXdPYmo7XG59XG5leHBvcnQgeyBfaW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkIGFzIF8gfTtcbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/@swc/helpers/esm/_interop_require_wildcard.js\n");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "(ssr)/./node_modules/@swc/helpers/esm/_tagged_template_literal_loose.js":
|
||||
/*!*************************************************************************!*\
|
||||
!*** ./node_modules/@swc/helpers/esm/_tagged_template_literal_loose.js ***!
|
||||
\*************************************************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _tagged_template_literal_loose)\n/* harmony export */ });\nfunction _tagged_template_literal_loose(strings, raw) {\n if (!raw) raw = strings.slice(0);\n\n strings.raw = raw;\n\n return strings;\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9fdGFnZ2VkX3RlbXBsYXRlX2xpdGVyYWxfbG9vc2UuanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUMrQyIsInNvdXJjZXMiOlsiL1VzZXJzL2pvam8vRGVza3RvcC9hZ2VudHMv5q2j5Zyo5L+u5aSN5LitL2FnZW50cy9zY3JpcHRzL2xpcXVpZC1nbGFzcy1kZW1vL25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvZXNtL190YWdnZWRfdGVtcGxhdGVfbGl0ZXJhbF9sb29zZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfdGFnZ2VkX3RlbXBsYXRlX2xpdGVyYWxfbG9vc2Uoc3RyaW5ncywgcmF3KSB7XG4gICAgaWYgKCFyYXcpIHJhdyA9IHN0cmluZ3Muc2xpY2UoMCk7XG5cbiAgICBzdHJpbmdzLnJhdyA9IHJhdztcblxuICAgIHJldHVybiBzdHJpbmdzO1xufVxuZXhwb3J0IHsgX3RhZ2dlZF90ZW1wbGF0ZV9saXRlcmFsX2xvb3NlIGFzIF8gfTtcbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/@swc/helpers/esm/_tagged_template_literal_loose.js\n");
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
exports.id = "vendor-chunks/clsx";
|
||||
exports.ids = ["vendor-chunks/clsx"];
|
||||
exports.modules = {
|
||||
|
||||
/***/ "(ssr)/./node_modules/clsx/dist/clsx.mjs":
|
||||
/*!*****************************************!*\
|
||||
!*** ./node_modules/clsx/dist/clsx.mjs ***!
|
||||
\*****************************************/
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ clsx: () => (/* binding */ clsx),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (clsx);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvY2xzeC9kaXN0L2Nsc3gubWpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsY0FBYyxhQUFhLCtDQUErQyxnREFBZ0QsZUFBZSxRQUFRLElBQUksMENBQTBDLHlDQUF5QyxTQUFnQixnQkFBZ0Isd0NBQXdDLElBQUksbURBQW1ELFNBQVMsaUVBQWUsSUFBSSIsInNvdXJjZXMiOlsiL1VzZXJzL2pvam8vRGVza3RvcC9hZ2VudHMv5q2j5Zyo5L+u5aSN5LitL2FnZW50cy9zY3JpcHRzL2xpcXVpZC1nbGFzcy1kZW1vL25vZGVfbW9kdWxlcy9jbHN4L2Rpc3QvY2xzeC5tanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gcihlKXt2YXIgdCxmLG49XCJcIjtpZihcInN0cmluZ1wiPT10eXBlb2YgZXx8XCJudW1iZXJcIj09dHlwZW9mIGUpbis9ZTtlbHNlIGlmKFwib2JqZWN0XCI9PXR5cGVvZiBlKWlmKEFycmF5LmlzQXJyYXkoZSkpe3ZhciBvPWUubGVuZ3RoO2Zvcih0PTA7dDxvO3QrKyllW3RdJiYoZj1yKGVbdF0pKSYmKG4mJihuKz1cIiBcIiksbis9Zil9ZWxzZSBmb3IoZiBpbiBlKWVbZl0mJihuJiYobis9XCIgXCIpLG4rPWYpO3JldHVybiBufWV4cG9ydCBmdW5jdGlvbiBjbHN4KCl7Zm9yKHZhciBlLHQsZj0wLG49XCJcIixvPWFyZ3VtZW50cy5sZW5ndGg7ZjxvO2YrKykoZT1hcmd1bWVudHNbZl0pJiYodD1yKGUpKSYmKG4mJihuKz1cIiBcIiksbis9dCk7cmV0dXJuIG59ZXhwb3J0IGRlZmF1bHQgY2xzeDsiXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/clsx/dist/clsx.mjs\n");
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,215 +0,0 @@
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({});
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ var threw = true;
|
||||
/******/ try {
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/ threw = false;
|
||||
/******/ } finally {
|
||||
/******/ if(threw) delete __webpack_module_cache__[moduleId];
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = __webpack_modules__;
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ (() => {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = (module) => {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ () => (module['default']) :
|
||||
/******/ () => (module);
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/create fake namespace object */
|
||||
/******/ (() => {
|
||||
/******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
|
||||
/******/ var leafPrototypes;
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 16: return value when it's Promise-like
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = this(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if(typeof value === 'object' && value) {
|
||||
/******/ if((mode & 4) && value.__esModule) return value;
|
||||
/******/ if((mode & 16) && typeof value.then === 'function') return value;
|
||||
/******/ }
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ var def = {};
|
||||
/******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
|
||||
/******/ for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
|
||||
/******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
|
||||
/******/ }
|
||||
/******/ def['default'] = () => (value);
|
||||
/******/ __webpack_require__.d(ns, def);
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ (() => {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = (exports, definition) => {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/ensure chunk */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.f = {};
|
||||
/******/ // This file contains only the entry chunk.
|
||||
/******/ // The chunk loading function for additional chunks
|
||||
/******/ __webpack_require__.e = (chunkId) => {
|
||||
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
|
||||
/******/ __webpack_require__.f[key](chunkId, promises);
|
||||
/******/ return promises;
|
||||
/******/ }, []));
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/get javascript chunk filename */
|
||||
/******/ (() => {
|
||||
/******/ // This function allow to reference async chunks and sibling chunks for the entrypoint
|
||||
/******/ __webpack_require__.u = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "" + chunkId + ".js";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.h = () => ("54c87fec7e7388bb")
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/make namespace object */
|
||||
/******/ (() => {
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = (exports) => {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/node module decorator */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.nmd = (module) => {
|
||||
/******/ module.paths = [];
|
||||
/******/ if (!module.children) module.children = [];
|
||||
/******/ return module;
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/startup entrypoint */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.X = (result, chunkIds, fn) => {
|
||||
/******/ // arguments: chunkIds, moduleId are deprecated
|
||||
/******/ var moduleId = chunkIds;
|
||||
/******/ if(!fn) chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId));
|
||||
/******/ chunkIds.map(__webpack_require__.e, __webpack_require__)
|
||||
/******/ var r = fn();
|
||||
/******/ return r === undefined ? result : r;
|
||||
/******/ }
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/require chunk loading */
|
||||
/******/ (() => {
|
||||
/******/ // no baseURI
|
||||
/******/
|
||||
/******/ // object to store loaded chunks
|
||||
/******/ // "1" means "loaded", otherwise not loaded yet
|
||||
/******/ var installedChunks = {
|
||||
/******/ "webpack-runtime": 1
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // no on chunks loaded
|
||||
/******/
|
||||
/******/ var installChunk = (chunk) => {
|
||||
/******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;
|
||||
/******/ for(var moduleId in moreModules) {
|
||||
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
||||
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(runtime) runtime(__webpack_require__);
|
||||
/******/ for(var i = 0; i < chunkIds.length; i++)
|
||||
/******/ installedChunks[chunkIds[i]] = 1;
|
||||
/******/
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // require() chunk loading for javascript
|
||||
/******/ __webpack_require__.f.require = (chunkId, promises) => {
|
||||
/******/ // "1" is the signal for "already loaded"
|
||||
/******/ if(!installedChunks[chunkId]) {
|
||||
/******/ if("webpack-runtime" != chunkId) {
|
||||
/******/ installChunk(require("./" + __webpack_require__.u(chunkId)));
|
||||
/******/ } else installedChunks[chunkId] = 1;
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ module.exports = __webpack_require__;
|
||||
/******/ __webpack_require__.C = installChunk;
|
||||
/******/
|
||||
/******/ // no HMR
|
||||
/******/
|
||||
/******/ // no HMR manifest
|
||||
/******/ })();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/
|
||||
/******/ })()
|
||||
;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,70 +0,0 @@
|
||||
/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
|
||||
!*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[13].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[13].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/fonts.ts","import":"Inter","arguments":[{"subsets":["latin"],"display":"swap","variable":"--font-inter"}],"variableName":"inter"} ***!
|
||||
\*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/ba9851c3c22cd980-s.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/21350d82a1f187e9-s.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/c5fe6dc8356a8c31-s.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/19cfc7226ec3afaa-s.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/df0a9ae256c0569c-s.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/8e9860b6e62d6359-s.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url(/_next/static/media/e4af272ccee01ff0-s.p.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}@font-face {font-family: 'Inter Fallback';src: local("Arial");ascent-override: 90.44%;descent-override: 22.52%;line-gap-override: 0.00%;size-adjust: 107.12%
|
||||
}.__className_f367f3 {font-family: 'Inter', 'Inter Fallback';font-style: normal
|
||||
}.__variable_f367f3 {--font-inter: 'Inter', 'Inter Fallback'
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
self.__BUILD_MANIFEST = (function(a){return {__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:a,__routerFilterDynamic:a,sortedPages:["\u002F_app"]}}(void 0));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
|
||||
@ -1 +0,0 @@
|
||||
self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
{"c":[],"r":[],"m":[]}
|
||||
@ -1 +0,0 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./app/globals.css":
|
||||
/*!*************************!*\
|
||||
!*** ./app/globals.css ***!
|
||||
\*************************/
|
||||
/***/ ((module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"cb68c59db2ce\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qb2pvL0Rlc2t0b3AvYWdlbnRzL+ato+WcqOS/ruWkjeS4rS9hZ2VudHMvc2NyaXB0cy9saXF1aWQtZ2xhc3MtZGVtby9hcHAvZ2xvYmFscy5jc3MiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgXCJjYjY4YzU5ZGIyY2VcIlxuaWYgKG1vZHVsZS5ob3QpIHsgbW9kdWxlLmhvdC5hY2NlcHQoKSB9XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@ -1 +0,0 @@
|
||||
{"c":["webpack"],"r":[],"m":[]}
|
||||
@ -1,18 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.h = () => ("d9fe63931496764a")
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@ -1,18 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.h = () => ("da9c7a21bb145999")
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
File diff suppressed because one or more lines are too long
@ -1,84 +0,0 @@
|
||||
// File: /Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/layout.tsx
|
||||
import * as entry from '../../../app/layout.js'
|
||||
import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
|
||||
|
||||
type TEntry = typeof import('../../../app/layout.js')
|
||||
|
||||
type SegmentParams<T extends Object = any> = T extends Record<string, any>
|
||||
? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never }
|
||||
: T
|
||||
|
||||
// Check that the entry is a valid entry
|
||||
checkFields<Diff<{
|
||||
default: Function
|
||||
config?: {}
|
||||
generateStaticParams?: Function
|
||||
revalidate?: RevalidateRange<TEntry> | false
|
||||
dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
|
||||
dynamicParams?: boolean
|
||||
fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
|
||||
preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
|
||||
runtime?: 'nodejs' | 'experimental-edge' | 'edge'
|
||||
maxDuration?: number
|
||||
|
||||
metadata?: any
|
||||
generateMetadata?: Function
|
||||
viewport?: any
|
||||
generateViewport?: Function
|
||||
experimental_ppr?: boolean
|
||||
|
||||
}, TEntry, ''>>()
|
||||
|
||||
|
||||
// Check the prop type of the entry function
|
||||
checkFields<Diff<LayoutProps, FirstArg<TEntry['default']>, 'default'>>()
|
||||
|
||||
// Check the arguments and return type of the generateMetadata function
|
||||
if ('generateMetadata' in entry) {
|
||||
checkFields<Diff<LayoutProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateViewport function
|
||||
if ('generateViewport' in entry) {
|
||||
checkFields<Diff<LayoutProps, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateStaticParams function
|
||||
if ('generateStaticParams' in entry) {
|
||||
checkFields<Diff<{ params: SegmentParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
|
||||
checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
|
||||
}
|
||||
|
||||
export interface PageProps {
|
||||
params?: Promise<SegmentParams>
|
||||
searchParams?: Promise<any>
|
||||
}
|
||||
export interface LayoutProps {
|
||||
children?: React.ReactNode
|
||||
|
||||
params?: Promise<SegmentParams>
|
||||
}
|
||||
|
||||
// =============
|
||||
// Utility types
|
||||
type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
|
||||
|
||||
// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
|
||||
type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
|
||||
type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
|
||||
|
||||
type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
|
||||
type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
|
||||
type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
|
||||
|
||||
|
||||
|
||||
function checkFields<_ extends { [k in keyof any]: never }>() {}
|
||||
|
||||
// https://github.com/sindresorhus/type-fest
|
||||
type Numeric = number | bigint
|
||||
type Zero = 0 | 0n
|
||||
type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
|
||||
type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
|
||||
@ -1,84 +0,0 @@
|
||||
// File: /Users/jojo/Desktop/agents/正在修复中/agents/scripts/liquid-glass-demo/app/page.tsx
|
||||
import * as entry from '../../../app/page.js'
|
||||
import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
|
||||
|
||||
type TEntry = typeof import('../../../app/page.js')
|
||||
|
||||
type SegmentParams<T extends Object = any> = T extends Record<string, any>
|
||||
? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never }
|
||||
: T
|
||||
|
||||
// Check that the entry is a valid entry
|
||||
checkFields<Diff<{
|
||||
default: Function
|
||||
config?: {}
|
||||
generateStaticParams?: Function
|
||||
revalidate?: RevalidateRange<TEntry> | false
|
||||
dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
|
||||
dynamicParams?: boolean
|
||||
fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
|
||||
preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
|
||||
runtime?: 'nodejs' | 'experimental-edge' | 'edge'
|
||||
maxDuration?: number
|
||||
|
||||
metadata?: any
|
||||
generateMetadata?: Function
|
||||
viewport?: any
|
||||
generateViewport?: Function
|
||||
experimental_ppr?: boolean
|
||||
|
||||
}, TEntry, ''>>()
|
||||
|
||||
|
||||
// Check the prop type of the entry function
|
||||
checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>()
|
||||
|
||||
// Check the arguments and return type of the generateMetadata function
|
||||
if ('generateMetadata' in entry) {
|
||||
checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateViewport function
|
||||
if ('generateViewport' in entry) {
|
||||
checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateStaticParams function
|
||||
if ('generateStaticParams' in entry) {
|
||||
checkFields<Diff<{ params: SegmentParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
|
||||
checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
|
||||
}
|
||||
|
||||
export interface PageProps {
|
||||
params?: Promise<SegmentParams>
|
||||
searchParams?: Promise<any>
|
||||
}
|
||||
export interface LayoutProps {
|
||||
children?: React.ReactNode
|
||||
|
||||
params?: Promise<SegmentParams>
|
||||
}
|
||||
|
||||
// =============
|
||||
// Utility types
|
||||
type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
|
||||
|
||||
// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
|
||||
type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
|
||||
type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
|
||||
|
||||
type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
|
||||
type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
|
||||
type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
|
||||
|
||||
|
||||
|
||||
function checkFields<_ extends { [k in keyof any]: never }>() {}
|
||||
|
||||
// https://github.com/sindresorhus/type-fest
|
||||
type Numeric = number | bigint
|
||||
type Zero = 0 | 0n
|
||||
type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
|
||||
type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
|
||||
@ -1,141 +0,0 @@
|
||||
// Type definitions for Next.js cacheLife configs
|
||||
|
||||
declare module 'next/cache' {
|
||||
export { unstable_cache } from 'next/dist/server/web/spec-extension/unstable-cache'
|
||||
export {
|
||||
revalidateTag,
|
||||
revalidatePath,
|
||||
unstable_expireTag,
|
||||
unstable_expirePath,
|
||||
} from 'next/dist/server/web/spec-extension/revalidate'
|
||||
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
|
||||
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"default"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 900 seconds (15 minutes)
|
||||
* expire: never
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 15 minutes, start revalidating new values in the background.
|
||||
* It lives for the maximum age of the server cache. If this entry has no traffic for a while, it may serve an old value the next request.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "default"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"seconds"` profile.
|
||||
* ```
|
||||
* stale: 0 seconds
|
||||
* revalidate: 1 seconds
|
||||
* expire: 60 seconds (1 minute)
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 0 seconds before checking with the server.
|
||||
* If the server receives a new request after 1 seconds, start revalidating new values in the background.
|
||||
* If this entry has no traffic for 1 minute it will expire. The next request will recompute it.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "seconds"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"minutes"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 60 seconds (1 minute)
|
||||
* expire: 3600 seconds (1 hour)
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 1 minute, start revalidating new values in the background.
|
||||
* If this entry has no traffic for 1 hour it will expire. The next request will recompute it.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "minutes"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"hours"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 3600 seconds (1 hour)
|
||||
* expire: 86400 seconds (1 day)
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 1 hour, start revalidating new values in the background.
|
||||
* If this entry has no traffic for 1 day it will expire. The next request will recompute it.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "hours"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"days"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 86400 seconds (1 day)
|
||||
* expire: 604800 seconds (1 week)
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 1 day, start revalidating new values in the background.
|
||||
* If this entry has no traffic for 1 week it will expire. The next request will recompute it.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "days"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"weeks"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 604800 seconds (1 week)
|
||||
* expire: 2592000 seconds (30 days)
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 1 week, start revalidating new values in the background.
|
||||
* If this entry has no traffic for 30 days it will expire. The next request will recompute it.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "weeks"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` for a timespan defined by the `"max"` profile.
|
||||
* ```
|
||||
* stale: 300 seconds (5 minutes)
|
||||
* revalidate: 2592000 seconds (30 days)
|
||||
* expire: never
|
||||
* ```
|
||||
*
|
||||
* This cache may be stale on clients for 5 minutes before checking with the server.
|
||||
* If the server receives a new request after 30 days, start revalidating new values in the background.
|
||||
* It lives for the maximum age of the server cache. If this entry has no traffic for a while, it may serve an old value the next request.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: "max"): void
|
||||
|
||||
/**
|
||||
* Cache this `"use cache"` using a custom timespan.
|
||||
* ```
|
||||
* stale: ... // seconds
|
||||
* revalidate: ... // seconds
|
||||
* expire: ... // seconds
|
||||
* ```
|
||||
*
|
||||
* This is similar to Cache-Control: max-age=`stale`,s-max-age=`revalidate`,stale-while-revalidate=`expire-revalidate`
|
||||
*
|
||||
* If a value is left out, the lowest of other cacheLife() calls or the default, is used instead.
|
||||
*/
|
||||
export function unstable_cacheLife(profile: {
|
||||
/**
|
||||
* This cache may be stale on clients for ... seconds before checking with the server.
|
||||
*/
|
||||
stale?: number,
|
||||
/**
|
||||
* If the server receives a new request after ... seconds, start revalidating new values in the background.
|
||||
*/
|
||||
revalidate?: number,
|
||||
/**
|
||||
* If this entry has no traffic for ... seconds it will expire. The next request will recompute it.
|
||||
*/
|
||||
expire?: number
|
||||
}): void
|
||||
|
||||
|
||||
export { cacheTag as unstable_cacheTag } from 'next/dist/server/use-cache/cache-tag'
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
{"type": "module"}
|
||||
@ -1,11 +0,0 @@
|
||||
.custom-slider {
|
||||
@apply w-full h-1 bg-white/20;
|
||||
}
|
||||
|
||||
.custom-slider .custom-slider-thumb {
|
||||
@apply w-0.5 h-4 bg-white/50;
|
||||
}
|
||||
|
||||
.custom-slider .custom-slider-track {
|
||||
@apply h-full bg-white/50;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { Inter } from "next/font/google"
|
||||
import type { NextFontWithVariable } from "next/dist/compiled/@next/font"
|
||||
import type { NextFont } from "next/font"
|
||||
|
||||
const ppEditorialNewUltralightItalic: NextFontWithVariable & NextFont = {
|
||||
className: "font-pp-editorial",
|
||||
style: {
|
||||
fontFamily: "PPEditorialNew-UltralightItalic",
|
||||
fontWeight: "200",
|
||||
fontStyle: "italic",
|
||||
},
|
||||
variable: "--font-pp-editorial",
|
||||
}
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
variable: "--font-inter",
|
||||
})
|
||||
|
||||
export { ppEditorialNewUltralightItalic, inter }
|
||||
@ -1,43 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@font-face {
|
||||
font-family: "PPEditorialNew-UltralightItalic";
|
||||
src: url("https://raw.githubusercontent.com/oeneco/file-thing/9f9223f211387b3764942fcff87f57523870916d/PPEditorialNew-UltralightItalic.ttf")
|
||||
format("truetype");
|
||||
font-weight: 200;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "PPEditorialNew-UltralightItalic", sans-serif;
|
||||
font-weight: 200;
|
||||
font-style: italic;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font-inter);
|
||||
font-weight: 300;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
import "./globals.css"
|
||||
import { ppEditorialNewUltralightItalic, inter } from "./fonts"
|
||||
import type React from "react"
|
||||
import Script from "next/script"
|
||||
|
||||
export const metadata = {
|
||||
title: "Dynamic Frame Layout",
|
||||
description: "A dynamic frame layout with custom fonts",
|
||||
generator: 'v0.app'
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className={`${ppEditorialNewUltralightItalic.variable} ${inter.variable}`}>
|
||||
<body className={inter.className}>
|
||||
{children}
|
||||
<Script src="/liquid-glass.js" strategy="afterInteractive" />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import localFont from "next/font/local"
|
||||
|
||||
export const customFont = localFont({
|
||||
src: [
|
||||
{
|
||||
path: "../public/fonts/your-font-regular.woff2",
|
||||
weight: "300",
|
||||
style: "normal",
|
||||
},
|
||||
{
|
||||
path: "../public/fonts/your-font-italic.woff2",
|
||||
weight: "400",
|
||||
style: "italic",
|
||||
},
|
||||
// Add more variations as needed
|
||||
],
|
||||
display: "swap",
|
||||
})
|
||||
@ -1,83 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import DynamicFrameLayout from "../components/DynamicFrameLayout"
|
||||
import { ppEditorialNewUltralightItalic, inter } from "./fonts"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
|
||||
export default function Home() {
|
||||
const [headerSize] = useState(1.2) // 120% is the default size
|
||||
const [textSize] = useState(0.8) // 80% is the default size
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`min-h-screen bg-[#141414] flex items-center justify-center p-8 ${ppEditorialNewUltralightItalic.variable} ${inter.variable}`}
|
||||
>
|
||||
<div className="w-full h-full flex flex-col md:flex-row items-start gap-8 md:gap-8">
|
||||
{/* Left Content */}
|
||||
<div className="w-full md:w-[260px] flex-shrink-0 flex flex-col justify-between h-full">
|
||||
<div className="flex flex-col gap-16">
|
||||
<h1
|
||||
className={`${ppEditorialNewUltralightItalic.className} text-4xl md:text-6xl font-light italic text-white/80 tracking-tighter leading-[130%]`}
|
||||
style={{ fontSize: `${4 * headerSize}rem` }}
|
||||
>
|
||||
Brand
|
||||
<br />
|
||||
Designer
|
||||
<br />
|
||||
at Luma?
|
||||
</h1>
|
||||
<div
|
||||
className={`${inter.className} flex flex-col gap-12 text-white/50 text-sm font-light max-w-[300px]`}
|
||||
style={{ fontSize: `${0.875 * textSize}rem` }}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="h-px bg-white/10 w-full" />
|
||||
<p>
|
||||
Luma is looking to hire a multi-disciplinary Brand Designer to develop and maintain the brand identity
|
||||
and communicate the story of Luma to the world. Alongside members of the design team using product and
|
||||
research insights, you will help shape and define Luma's brand across product surfaces, social media,
|
||||
merchandise, marketing website, launch campaigns as well as other new channels.
|
||||
</p>
|
||||
<p>
|
||||
You will use a combination of graphic design, motion design, web design and video production/editing
|
||||
skills across traditional and innovative tools to communicate in visually compelling and impactful
|
||||
ways.
|
||||
</p>
|
||||
<p>Here are some of our favorite works so far.</p>
|
||||
<div className="h-px bg-white/10 w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href="https://lumalabs.ai"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-8 h-8 relative opacity-80 hover:opacity-100 transition-opacity"
|
||||
>
|
||||
<Image
|
||||
src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/LumaLogo%201-MA3upjPymxFHKoHJgpdAUfZMeKGq3i.png"
|
||||
alt="Luma Logo"
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<a
|
||||
href="https://lumalabs.ai/join?role=5d274587-f8fd-4f53-a5b6-8f85d586e1aa"
|
||||
className="inline-block px-6 py-3 text-white/70 border border-white/20 rounded-full font-medium hover:bg-white/5 transition-colors text-center w-full max-w-[260px] text-sm mt-16"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Apply
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Right Content */}
|
||||
<div className="w-full md:flex-grow h-[60vh] md:h-[80vh]">
|
||||
<DynamicFrameLayout />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "app/globals.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
@ -1,322 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { motion } from "framer-motion"
|
||||
import { FrameComponent } from "./FrameComponent"
|
||||
import { Slider } from "@/components/ui/slider"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
|
||||
const GRID_SIZE = 12
|
||||
const CELL_SIZE = 60 // pixels per grid cell
|
||||
|
||||
interface Frame {
|
||||
id: number
|
||||
video: string
|
||||
defaultPos: { x: number; y: number; w: number; h: number }
|
||||
corner: string
|
||||
edgeHorizontal: string
|
||||
edgeVertical: string
|
||||
mediaSize: number
|
||||
borderThickness: number
|
||||
borderSize: number
|
||||
autoplayMode: "all" | "hover"
|
||||
isHovered: boolean
|
||||
}
|
||||
|
||||
const initialFrames: Frame[] = [
|
||||
{
|
||||
id: 1,
|
||||
video: "https://static.cdn-luma.com/files/981e483f71aa764b/Company%20Thing%20Exported.mp4",
|
||||
defaultPos: { x: 0, y: 0, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/bcf576df9c38b05f/1_corner_update.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/bcf576df9c38b05f/1_vert_update.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/bcf576df9c38b05f/1_hori_update.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/WebGL%20Exported%20(1).mp4",
|
||||
defaultPos: { x: 4, y: 0, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/bcf576df9c38b05f/2_corner_update.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/bcf576df9c38b05f/2_vert_update.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/bcf576df9c38b05f/2_hori_update.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Jitter%20Exported%20Poster.mp4",
|
||||
defaultPos: { x: 8, y: 0, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/3d36d1e0dba2476c/3_Corner_update.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/3d36d1e0dba2476c/3_hori_update.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/3d36d1e0dba2476c/3_Vert_update.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Exported%20Web%20Video.mp4",
|
||||
defaultPos: { x: 0, y: 4, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/9e67e05f37e52522/4_corner_update.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/9e67e05f37e52522/4_hori_update.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/9e67e05f37e52522/4_vert_update.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Logo%20Exported.mp4",
|
||||
defaultPos: { x: 4, y: 4, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/9e67e05f37e52522/5_corner_update.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/9e67e05f37e52522/5_hori_update.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/9e67e05f37e52522/5_verti_update.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Animation%20Exported%20(4).mp4",
|
||||
defaultPos: { x: 8, y: 4, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/1199340587e8da1d/6_corner.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/1199340587e8da1d/6_corner-1.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/1199340587e8da1d/6_vert.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Illustration%20Exported%20(1).mp4",
|
||||
defaultPos: { x: 0, y: 8, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/b80b5aa00ccc33bd/7_corner.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/b80b5aa00ccc33bd/7_hori.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/b80b5aa00ccc33bd/7_vert.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Art%20Direction%20Exported.mp4",
|
||||
defaultPos: { x: 4, y: 8, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/981e483f71aa764b/8_corner.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/981e483f71aa764b/8_hori.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/981e483f71aa764b/8_verticle.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
video: "https://static.cdn-luma.com/files/58ab7363888153e3/Product%20Video.mp4",
|
||||
defaultPos: { x: 8, y: 8, w: 4, h: 4 },
|
||||
corner: "https://static.cdn-luma.com/files/981e483f71aa764b/9_corner.png",
|
||||
edgeHorizontal: "https://static.cdn-luma.com/files/981e483f71aa764b/9_hori.png",
|
||||
edgeVertical: "https://static.cdn-luma.com/files/981e483f71aa764b/9_vert.png",
|
||||
mediaSize: 1,
|
||||
borderThickness: 0,
|
||||
borderSize: 80,
|
||||
autoplayMode: "all",
|
||||
isHovered: false,
|
||||
},
|
||||
]
|
||||
|
||||
export default function DynamicFrameLayout() {
|
||||
const [frames, setFrames] = useState<Frame[]>(initialFrames)
|
||||
const [hovered, setHovered] = useState<{ row: number; col: number } | null>(null)
|
||||
const [hoverSize, setHoverSize] = useState(6)
|
||||
const [gapSize, setGapSize] = useState(4)
|
||||
const [showControls, setShowControls] = useState(false)
|
||||
const [cleanInterface, setCleanInterface] = useState(true)
|
||||
const [showFrames, setShowFrames] = useState(false) // Update: showFrames starts as false
|
||||
const [autoplayMode, setAutoplayMode] = useState<"all" | "hover">("all")
|
||||
|
||||
const getRowSizes = () => {
|
||||
if (hovered === null) {
|
||||
return "4fr 4fr 4fr"
|
||||
}
|
||||
const { row } = hovered
|
||||
const nonHoveredSize = (12 - hoverSize) / 2
|
||||
return [0, 1, 2].map((r) => (r === row ? `${hoverSize}fr` : `${nonHoveredSize}fr`)).join(" ")
|
||||
}
|
||||
|
||||
const getColSizes = () => {
|
||||
if (hovered === null) {
|
||||
return "4fr 4fr 4fr"
|
||||
}
|
||||
const { col } = hovered
|
||||
const nonHoveredSize = (12 - hoverSize) / 2
|
||||
return [0, 1, 2].map((c) => (c === col ? `${hoverSize}fr` : `${nonHoveredSize}fr`)).join(" ")
|
||||
}
|
||||
|
||||
const getTransformOrigin = (x: number, y: number) => {
|
||||
const vertical = y === 0 ? "top" : y === 4 ? "center" : "bottom"
|
||||
const horizontal = x === 0 ? "left" : x === 4 ? "center" : "right"
|
||||
return `${vertical} ${horizontal}`
|
||||
}
|
||||
|
||||
const updateFrameProperty = (id: number, property: keyof Frame, value: number) => {
|
||||
setFrames(frames.map((frame) => (frame.id === id ? { ...frame, [property]: value } : frame)))
|
||||
}
|
||||
|
||||
const toggleControls = () => {
|
||||
setShowControls(!showControls)
|
||||
}
|
||||
|
||||
const toggleCleanInterface = () => {
|
||||
setCleanInterface(!cleanInterface)
|
||||
if (!cleanInterface) {
|
||||
setShowControls(false)
|
||||
}
|
||||
}
|
||||
|
||||
const updateCodebase = () => {
|
||||
console.log("Updating codebase with current values:")
|
||||
console.log("Hover Size:", hoverSize)
|
||||
console.log("Gap Size:", gapSize)
|
||||
console.log("Frames:", frames)
|
||||
// Here you would typically make an API call to update the codebase
|
||||
// For now, we'll just log the values
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4 w-full h-full">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch id="frame-toggle" checked={showFrames} onCheckedChange={setShowFrames} />
|
||||
<label htmlFor="frame-toggle" className="text-sm text-white/70">
|
||||
{showFrames ? "Hide Frames" : "Show Frames"}
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="autoplay-toggle"
|
||||
checked={autoplayMode === "all"}
|
||||
onCheckedChange={(checked) => setAutoplayMode(checked ? "all" : "hover")}
|
||||
/>
|
||||
<label htmlFor="autoplay-toggle" className="text-sm text-white/70">
|
||||
{autoplayMode === "all" ? "Autoplay All" : "Hover Autoplay"}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!cleanInterface && (
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold text-white">Dynamic Frame Layout</h2>
|
||||
<div className="space-x-2">
|
||||
<Button onClick={toggleControls}>{showControls ? "Hide Controls" : "Show Controls"}</Button>
|
||||
<Button onClick={updateCodebase}>Update Codebase</Button>
|
||||
<Button onClick={toggleCleanInterface}>{cleanInterface ? "Show UI" : "Hide UI"}</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!cleanInterface && showControls && (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="hover-size" className="block text-sm font-medium text-gray-200">
|
||||
Hover Size: {hoverSize}
|
||||
</label>
|
||||
<Slider
|
||||
id="hover-size"
|
||||
min={4}
|
||||
max={8}
|
||||
step={0.1}
|
||||
value={[hoverSize]}
|
||||
onValueChange={(value) => setHoverSize(value[0])}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="gap-size" className="block text-sm font-medium text-gray-200">
|
||||
Gap Size: {gapSize}px
|
||||
</label>
|
||||
<Slider
|
||||
id="gap-size"
|
||||
min={0}
|
||||
max={20}
|
||||
step={1}
|
||||
value={[gapSize]}
|
||||
onValueChange={(value) => setGapSize(value[0])}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className="relative w-full h-full"
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateRows: getRowSizes(),
|
||||
gridTemplateColumns: getColSizes(),
|
||||
gap: `${gapSize}px`,
|
||||
transition: "grid-template-rows 0.4s ease, grid-template-columns 0.4s ease",
|
||||
}}
|
||||
>
|
||||
{frames.map((frame) => {
|
||||
const row = Math.floor(frame.defaultPos.y / 4)
|
||||
const col = Math.floor(frame.defaultPos.x / 4)
|
||||
const transformOrigin = getTransformOrigin(frame.defaultPos.x, frame.defaultPos.y)
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
key={frame.id}
|
||||
className="relative"
|
||||
style={{
|
||||
transformOrigin,
|
||||
transition: "transform 0.4s ease",
|
||||
}}
|
||||
onMouseEnter={() => setHovered({ row, col })}
|
||||
onMouseLeave={() => setHovered(null)}
|
||||
>
|
||||
<FrameComponent
|
||||
video={frame.video}
|
||||
width="100%"
|
||||
height="100%"
|
||||
className="absolute inset-0"
|
||||
corner={frame.corner}
|
||||
edgeHorizontal={frame.edgeHorizontal}
|
||||
edgeVertical={frame.edgeVertical}
|
||||
mediaSize={frame.mediaSize}
|
||||
borderThickness={frame.borderThickness}
|
||||
borderSize={frame.borderSize}
|
||||
onMediaSizeChange={(value) => updateFrameProperty(frame.id, "mediaSize", value)}
|
||||
onBorderThicknessChange={(value) => updateFrameProperty(frame.id, "borderThickness", value)}
|
||||
onBorderSizeChange={(value) => updateFrameProperty(frame.id, "borderSize", value)}
|
||||
showControls={showControls && !cleanInterface}
|
||||
label={`Frame ${frame.id}`}
|
||||
showFrame={showFrames}
|
||||
autoplayMode={autoplayMode}
|
||||
isHovered={
|
||||
hovered?.row === Math.floor(frame.defaultPos.y / 4) &&
|
||||
hovered?.col === Math.floor(frame.defaultPos.x / 4)
|
||||
}
|
||||
/>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,222 +0,0 @@
|
||||
"use client"
|
||||
import { Slider } from "@/components/ui/slider"
|
||||
import { useEffect, useRef } from "react"
|
||||
|
||||
interface FrameComponentProps {
|
||||
video: string
|
||||
width: number | string
|
||||
height: number | string
|
||||
className?: string
|
||||
corner: string
|
||||
edgeHorizontal: string
|
||||
edgeVertical: string
|
||||
mediaSize: number
|
||||
borderThickness: number
|
||||
borderSize: number
|
||||
onMediaSizeChange: (value: number) => void
|
||||
onBorderThicknessChange: (value: number) => void
|
||||
onBorderSizeChange: (value: number) => void
|
||||
showControls: boolean
|
||||
label: string
|
||||
showFrame: boolean
|
||||
autoplayMode: "all" | "hover"
|
||||
isHovered: boolean
|
||||
}
|
||||
|
||||
export function FrameComponent({
|
||||
video,
|
||||
width,
|
||||
height,
|
||||
className = "",
|
||||
corner,
|
||||
edgeHorizontal,
|
||||
edgeVertical,
|
||||
mediaSize,
|
||||
borderThickness,
|
||||
borderSize,
|
||||
onMediaSizeChange,
|
||||
onBorderThicknessChange,
|
||||
onBorderSizeChange,
|
||||
showControls,
|
||||
label,
|
||||
showFrame,
|
||||
autoplayMode,
|
||||
isHovered,
|
||||
}: FrameComponentProps) {
|
||||
const videoRef = useRef<HTMLVideoElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (autoplayMode === "all") {
|
||||
videoRef.current?.play()
|
||||
} else if (autoplayMode === "hover") {
|
||||
if (isHovered) {
|
||||
videoRef.current?.play()
|
||||
} else {
|
||||
videoRef.current?.pause()
|
||||
}
|
||||
}
|
||||
}, [isHovered, autoplayMode])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative ${className}`}
|
||||
style={{
|
||||
width,
|
||||
height,
|
||||
transition: "width 0.3s ease-in-out, height 0.3s ease-in-out",
|
||||
}}
|
||||
>
|
||||
<div className="relative w-full h-full overflow-hidden">
|
||||
{/* Video with Border */}
|
||||
<div
|
||||
className="absolute inset-0 flex items-center justify-center"
|
||||
style={{
|
||||
zIndex: 1,
|
||||
transition: "all 0.3s ease-in-out",
|
||||
padding: showFrame ? `${borderThickness}px` : "0",
|
||||
width: showFrame ? `${borderSize}%` : "100%",
|
||||
height: showFrame ? `${borderSize}%` : "100%",
|
||||
left: showFrame ? `${(100 - borderSize) / 2}%` : "0",
|
||||
top: showFrame ? `${(100 - borderSize) / 2}%` : "0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="w-full h-full overflow-hidden"
|
||||
style={{
|
||||
transform: `scale(${mediaSize})`,
|
||||
transformOrigin: "center",
|
||||
transition: "transform 0.3s ease-in-out",
|
||||
}}
|
||||
>
|
||||
<video
|
||||
className="w-full h-full object-cover"
|
||||
src={video}
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
autoPlay={autoplayMode === "all" || (autoplayMode === "hover" && isHovered)}
|
||||
ref={videoRef}
|
||||
onMouseEnter={(e) => {
|
||||
if (autoplayMode === "hover") {
|
||||
e.currentTarget.play()
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (autoplayMode === "hover") {
|
||||
e.currentTarget.pause()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Frame Elements (Higher z-index) */}
|
||||
{showFrame && (
|
||||
<div className="absolute inset-0" style={{ zIndex: 2 }}>
|
||||
{/* Corners */}
|
||||
<div
|
||||
className="absolute top-0 left-0 w-16 h-16 bg-contain bg-no-repeat"
|
||||
style={{ backgroundImage: `url(${corner})` }}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-0 right-0 w-16 h-16 bg-contain bg-no-repeat"
|
||||
style={{ backgroundImage: `url(${corner})`, transform: "scaleX(-1)" }}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-0 left-0 w-16 h-16 bg-contain bg-no-repeat"
|
||||
style={{ backgroundImage: `url(${corner})`, transform: "scaleY(-1)" }}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-0 right-0 w-16 h-16 bg-contain bg-no-repeat"
|
||||
style={{ backgroundImage: `url(${corner})`, transform: "scale(-1, -1)" }}
|
||||
/>
|
||||
|
||||
{/* Edges */}
|
||||
<div
|
||||
className="absolute top-0 left-16 right-16 h-16"
|
||||
style={{
|
||||
backgroundImage: `url(${edgeHorizontal})`,
|
||||
backgroundSize: "auto 64px",
|
||||
backgroundRepeat: "repeat-x",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-0 left-16 right-16 h-16"
|
||||
style={{
|
||||
backgroundImage: `url(${edgeHorizontal})`,
|
||||
backgroundSize: "auto 64px",
|
||||
backgroundRepeat: "repeat-x",
|
||||
transform: "rotate(180deg)",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute left-0 top-16 bottom-16 w-16"
|
||||
style={{
|
||||
backgroundImage: `url(${edgeVertical})`,
|
||||
backgroundSize: "64px auto",
|
||||
backgroundRepeat: "repeat-y",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute right-0 top-16 bottom-16 w-16"
|
||||
style={{
|
||||
backgroundImage: `url(${edgeVertical})`,
|
||||
backgroundSize: "64px auto",
|
||||
backgroundRepeat: "repeat-y",
|
||||
transform: "scaleX(-1)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Controls */}
|
||||
{showControls && (
|
||||
<div className="absolute bottom-0 left-0 right-0 p-2 bg-black bg-opacity-50 z-10">
|
||||
<div className="text-white font-bold mb-2">{label}</div>
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<label htmlFor={`media-size-${label}`} className="block text-sm font-medium text-white">
|
||||
Media Size: {mediaSize.toFixed(2)}
|
||||
</label>
|
||||
<Slider
|
||||
id={`media-size-${label}`}
|
||||
min={0.5}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={[mediaSize]}
|
||||
onValueChange={(value) => onMediaSizeChange(value[0])}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor={`border-thickness-${label}`} className="block text-sm font-medium text-white">
|
||||
Border Thickness: {borderThickness}px
|
||||
</label>
|
||||
<Slider
|
||||
id={`border-thickness-${label}`}
|
||||
min={0}
|
||||
max={20}
|
||||
step={1}
|
||||
value={[borderThickness]}
|
||||
onValueChange={(value) => onBorderThicknessChange(value[0])}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor={`border-size-${label}`} className="block text-sm font-medium text-white">
|
||||
Border Size: {borderSize}%
|
||||
</label>
|
||||
<Slider
|
||||
id={`border-size-${label}`}
|
||||
min={50}
|
||||
max={100}
|
||||
step={1}
|
||||
value={[borderSize]}
|
||||
onValueChange={(value) => onBorderSizeChange(value[0])}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import {
|
||||
ThemeProvider as NextThemesProvider,
|
||||
type ThemeProviderProps,
|
||||
} from 'next-themes'
|
||||
|
||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as AccordionPrimitive from '@radix-ui/react-accordion'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Accordion = AccordionPrimitive.Root
|
||||
|
||||
const AccordionItem = React.forwardRef<
|
||||
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AccordionPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn('border-b', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AccordionItem.displayName = 'AccordionItem'
|
||||
|
||||
const AccordionTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<AccordionPrimitive.Header className="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
))
|
||||
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
||||
|
||||
const AccordionContent = React.forwardRef<
|
||||
React.ElementRef<typeof AccordionPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<AccordionPrimitive.Content
|
||||
ref={ref}
|
||||
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
||||
{...props}
|
||||
>
|
||||
<div className={cn('pb-4 pt-0', className)}>{children}</div>
|
||||
</AccordionPrimitive.Content>
|
||||
))
|
||||
|
||||
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
||||
|
||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
||||
@ -1,141 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
|
||||
const AlertDialog = AlertDialogPrimitive.Root
|
||||
|
||||
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
||||
|
||||
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
||||
|
||||
const AlertDialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Overlay
|
||||
className={cn(
|
||||
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
))
|
||||
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
|
||||
|
||||
const AlertDialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay />
|
||||
<AlertDialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</AlertDialogPortal>
|
||||
))
|
||||
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
|
||||
|
||||
const AlertDialogHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col space-y-2 text-center sm:text-left',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
AlertDialogHeader.displayName = 'AlertDialogHeader'
|
||||
|
||||
const AlertDialogFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
AlertDialogFooter.displayName = 'AlertDialogFooter'
|
||||
|
||||
const AlertDialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn('text-lg font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
|
||||
|
||||
const AlertDialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn('text-sm text-muted-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDialogDescription.displayName =
|
||||
AlertDialogPrimitive.Description.displayName
|
||||
|
||||
const AlertDialogAction = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Action
|
||||
ref={ref}
|
||||
className={cn(buttonVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
|
||||
|
||||
const AlertDialogCancel = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
||||
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Cancel
|
||||
ref={ref}
|
||||
className={cn(
|
||||
buttonVariants({ variant: 'outline' }),
|
||||
'mt-2 sm:mt-0',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
|
||||
|
||||
export {
|
||||
AlertDialog,
|
||||
AlertDialogPortal,
|
||||
AlertDialogOverlay,
|
||||
AlertDialogTrigger,
|
||||
AlertDialogContent,
|
||||
AlertDialogHeader,
|
||||
AlertDialogFooter,
|
||||
AlertDialogTitle,
|
||||
AlertDialogDescription,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const alertVariants = cva(
|
||||
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-background text-foreground',
|
||||
destructive:
|
||||
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const Alert = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
||||
>(({ className, variant, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
role="alert"
|
||||
className={cn(alertVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Alert.displayName = 'Alert'
|
||||
|
||||
const AlertTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h5
|
||||
ref={ref}
|
||||
className={cn('mb-1 font-medium leading-none tracking-tight', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertTitle.displayName = 'AlertTitle'
|
||||
|
||||
const AlertDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('text-sm [&_p]:leading-relaxed', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDescription.displayName = 'AlertDescription'
|
||||
|
||||
export { Alert, AlertTitle, AlertDescription }
|
||||
@ -1,7 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'
|
||||
|
||||
const AspectRatio = AspectRatioPrimitive.Root
|
||||
|
||||
export { AspectRatio }
|
||||
@ -1,50 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as AvatarPrimitive from '@radix-ui/react-avatar'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Avatar = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Avatar.displayName = AvatarPrimitive.Root.displayName
|
||||
|
||||
const AvatarImage = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Image>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Image
|
||||
ref={ref}
|
||||
className={cn('aspect-square h-full w-full', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
||||
|
||||
const AvatarFallback = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Fallback
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex h-full w-full items-center justify-center rounded-full bg-muted',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
||||
|
||||
export { Avatar, AvatarImage, AvatarFallback }
|
||||
@ -1,36 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const badgeVariants = cva(
|
||||
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
||||
secondary:
|
||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
||||
outline: 'text-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
||||
@ -1,115 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { ChevronRight, MoreHorizontal } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Breadcrumb = React.forwardRef<
|
||||
HTMLElement,
|
||||
React.ComponentPropsWithoutRef<'nav'> & {
|
||||
separator?: React.ReactNode
|
||||
}
|
||||
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
|
||||
Breadcrumb.displayName = 'Breadcrumb'
|
||||
|
||||
const BreadcrumbList = React.forwardRef<
|
||||
HTMLOListElement,
|
||||
React.ComponentPropsWithoutRef<'ol'>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ol
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
BreadcrumbList.displayName = 'BreadcrumbList'
|
||||
|
||||
const BreadcrumbItem = React.forwardRef<
|
||||
HTMLLIElement,
|
||||
React.ComponentPropsWithoutRef<'li'>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<li
|
||||
ref={ref}
|
||||
className={cn('inline-flex items-center gap-1.5', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
BreadcrumbItem.displayName = 'BreadcrumbItem'
|
||||
|
||||
const BreadcrumbLink = React.forwardRef<
|
||||
HTMLAnchorElement,
|
||||
React.ComponentPropsWithoutRef<'a'> & {
|
||||
asChild?: boolean
|
||||
}
|
||||
>(({ asChild, className, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : 'a'
|
||||
|
||||
return (
|
||||
<Comp
|
||||
ref={ref}
|
||||
className={cn('transition-colors hover:text-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
BreadcrumbLink.displayName = 'BreadcrumbLink'
|
||||
|
||||
const BreadcrumbPage = React.forwardRef<
|
||||
HTMLSpanElement,
|
||||
React.ComponentPropsWithoutRef<'span'>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<span
|
||||
ref={ref}
|
||||
role="link"
|
||||
aria-disabled="true"
|
||||
aria-current="page"
|
||||
className={cn('font-normal text-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
BreadcrumbPage.displayName = 'BreadcrumbPage'
|
||||
|
||||
const BreadcrumbSeparator = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'li'>) => (
|
||||
<li
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
className={cn('[&>svg]:w-3.5 [&>svg]:h-3.5', className)}
|
||||
{...props}
|
||||
>
|
||||
{children ?? <ChevronRight />}
|
||||
</li>
|
||||
)
|
||||
BreadcrumbSeparator.displayName = 'BreadcrumbSeparator'
|
||||
|
||||
const BreadcrumbEllipsis = ({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'span'>) => (
|
||||
<span
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
className={cn('flex h-9 w-9 items-center justify-center', className)}
|
||||
{...props}
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">More</span>
|
||||
</span>
|
||||
)
|
||||
BreadcrumbEllipsis.displayName = 'BreadcrumbElipssis'
|
||||
|
||||
export {
|
||||
Breadcrumb,
|
||||
BreadcrumbList,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
BreadcrumbEllipsis,
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
|
||||
const buttonGroupVariants = cva(
|
||||
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
||||
{
|
||||
variants: {
|
||||
orientation: {
|
||||
horizontal:
|
||||
'[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none',
|
||||
vertical:
|
||||
'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
orientation: 'horizontal',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
function ButtonGroup({
|
||||
className,
|
||||
orientation,
|
||||
...props
|
||||
}: React.ComponentProps<'div'> & VariantProps<typeof buttonGroupVariants>) {
|
||||
return (
|
||||
<div
|
||||
role="group"
|
||||
data-slot="button-group"
|
||||
data-orientation={orientation}
|
||||
className={cn(buttonGroupVariants({ orientation }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ButtonGroupText({
|
||||
className,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<'div'> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot : 'div'
|
||||
|
||||
return (
|
||||
<Comp
|
||||
className={cn(
|
||||
"bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ButtonGroupSeparator({
|
||||
className,
|
||||
orientation = 'vertical',
|
||||
...props
|
||||
}: React.ComponentProps<typeof Separator>) {
|
||||
return (
|
||||
<Separator
|
||||
data-slot="button-group-separator"
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
'bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
ButtonGroup,
|
||||
ButtonGroupSeparator,
|
||||
ButtonGroupText,
|
||||
buttonGroupVariants,
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const buttonVariants = cva(
|
||||
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||
destructive:
|
||||
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||
outline:
|
||||
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
default: 'h-10 px-4 py-2',
|
||||
sm: 'h-9 rounded-md px-3',
|
||||
lg: 'h-11 rounded-md px-8',
|
||||
icon: 'h-10 w-10',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : 'button'
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
)
|
||||
Button.displayName = 'Button'
|
||||
|
||||
export { Button, buttonVariants }
|
||||
@ -1,213 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
} from 'lucide-react'
|
||||
import { DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button, buttonVariants } from '@/components/ui/button'
|
||||
|
||||
function Calendar({
|
||||
className,
|
||||
classNames,
|
||||
showOutsideDays = true,
|
||||
captionLayout = 'label',
|
||||
buttonVariant = 'ghost',
|
||||
formatters,
|
||||
components,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DayPicker> & {
|
||||
buttonVariant?: React.ComponentProps<typeof Button>['variant']
|
||||
}) {
|
||||
const defaultClassNames = getDefaultClassNames()
|
||||
|
||||
return (
|
||||
<DayPicker
|
||||
showOutsideDays={showOutsideDays}
|
||||
className={cn(
|
||||
'bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',
|
||||
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
||||
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
||||
className,
|
||||
)}
|
||||
captionLayout={captionLayout}
|
||||
formatters={{
|
||||
formatMonthDropdown: (date) =>
|
||||
date.toLocaleString('default', { month: 'short' }),
|
||||
...formatters,
|
||||
}}
|
||||
classNames={{
|
||||
root: cn('w-fit', defaultClassNames.root),
|
||||
months: cn(
|
||||
'flex gap-4 flex-col md:flex-row relative',
|
||||
defaultClassNames.months,
|
||||
),
|
||||
month: cn('flex flex-col w-full gap-4', defaultClassNames.month),
|
||||
nav: cn(
|
||||
'flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between',
|
||||
defaultClassNames.nav,
|
||||
),
|
||||
button_previous: cn(
|
||||
buttonVariants({ variant: buttonVariant }),
|
||||
'size-[--cell-size] aria-disabled:opacity-50 p-0 select-none',
|
||||
defaultClassNames.button_previous,
|
||||
),
|
||||
button_next: cn(
|
||||
buttonVariants({ variant: buttonVariant }),
|
||||
'size-[--cell-size] aria-disabled:opacity-50 p-0 select-none',
|
||||
defaultClassNames.button_next,
|
||||
),
|
||||
month_caption: cn(
|
||||
'flex items-center justify-center h-[--cell-size] w-full px-[--cell-size]',
|
||||
defaultClassNames.month_caption,
|
||||
),
|
||||
dropdowns: cn(
|
||||
'w-full flex items-center text-sm font-medium justify-center h-[--cell-size] gap-1.5',
|
||||
defaultClassNames.dropdowns,
|
||||
),
|
||||
dropdown_root: cn(
|
||||
'relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md',
|
||||
defaultClassNames.dropdown_root,
|
||||
),
|
||||
dropdown: cn(
|
||||
'absolute bg-popover inset-0 opacity-0',
|
||||
defaultClassNames.dropdown,
|
||||
),
|
||||
caption_label: cn(
|
||||
'select-none font-medium',
|
||||
captionLayout === 'label'
|
||||
? 'text-sm'
|
||||
: 'rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5',
|
||||
defaultClassNames.caption_label,
|
||||
),
|
||||
table: 'w-full border-collapse',
|
||||
weekdays: cn('flex', defaultClassNames.weekdays),
|
||||
weekday: cn(
|
||||
'text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none',
|
||||
defaultClassNames.weekday,
|
||||
),
|
||||
week: cn('flex w-full mt-2', defaultClassNames.week),
|
||||
week_number_header: cn(
|
||||
'select-none w-[--cell-size]',
|
||||
defaultClassNames.week_number_header,
|
||||
),
|
||||
week_number: cn(
|
||||
'text-[0.8rem] select-none text-muted-foreground',
|
||||
defaultClassNames.week_number,
|
||||
),
|
||||
day: cn(
|
||||
'relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none',
|
||||
defaultClassNames.day,
|
||||
),
|
||||
range_start: cn(
|
||||
'rounded-l-md bg-accent',
|
||||
defaultClassNames.range_start,
|
||||
),
|
||||
range_middle: cn('rounded-none', defaultClassNames.range_middle),
|
||||
range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end),
|
||||
today: cn(
|
||||
'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',
|
||||
defaultClassNames.today,
|
||||
),
|
||||
outside: cn(
|
||||
'text-muted-foreground aria-selected:text-muted-foreground',
|
||||
defaultClassNames.outside,
|
||||
),
|
||||
disabled: cn(
|
||||
'text-muted-foreground opacity-50',
|
||||
defaultClassNames.disabled,
|
||||
),
|
||||
hidden: cn('invisible', defaultClassNames.hidden),
|
||||
...classNames,
|
||||
}}
|
||||
components={{
|
||||
Root: ({ className, rootRef, ...props }) => {
|
||||
return (
|
||||
<div
|
||||
data-slot="calendar"
|
||||
ref={rootRef}
|
||||
className={cn(className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
Chevron: ({ className, orientation, ...props }) => {
|
||||
if (orientation === 'left') {
|
||||
return (
|
||||
<ChevronLeftIcon className={cn('size-4', className)} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
if (orientation === 'right') {
|
||||
return (
|
||||
<ChevronRightIcon
|
||||
className={cn('size-4', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChevronDownIcon className={cn('size-4', className)} {...props} />
|
||||
)
|
||||
},
|
||||
DayButton: CalendarDayButton,
|
||||
WeekNumber: ({ children, ...props }) => {
|
||||
return (
|
||||
<td {...props}>
|
||||
<div className="flex size-[--cell-size] items-center justify-center text-center">
|
||||
{children}
|
||||
</div>
|
||||
</td>
|
||||
)
|
||||
},
|
||||
...components,
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CalendarDayButton({
|
||||
className,
|
||||
day,
|
||||
modifiers,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DayButton>) {
|
||||
const defaultClassNames = getDefaultClassNames()
|
||||
|
||||
const ref = React.useRef<HTMLButtonElement>(null)
|
||||
React.useEffect(() => {
|
||||
if (modifiers.focused) ref.current?.focus()
|
||||
}, [modifiers.focused])
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
data-day={day.date.toLocaleDateString()}
|
||||
data-selected-single={
|
||||
modifiers.selected &&
|
||||
!modifiers.range_start &&
|
||||
!modifiers.range_end &&
|
||||
!modifiers.range_middle
|
||||
}
|
||||
data-range-start={modifiers.range_start}
|
||||
data-range-end={modifiers.range_end}
|
||||
data-range-middle={modifiers.range_middle}
|
||||
className={cn(
|
||||
'data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70',
|
||||
defaultClassNames.day,
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Calendar, CalendarDayButton }
|
||||
@ -1,79 +0,0 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'rounded-lg border bg-card text-card-foreground shadow-sm',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = 'Card'
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('flex flex-col space-y-1.5 p-6', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = 'CardHeader'
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'text-2xl font-semibold leading-none tracking-tight',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = 'CardTitle'
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('text-sm text-muted-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = 'CardDescription'
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = 'CardContent'
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('flex items-center p-6 pt-0', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = 'CardFooter'
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
@ -1,262 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import useEmblaCarousel, {
|
||||
type UseEmblaCarouselType,
|
||||
} from 'embla-carousel-react'
|
||||
import { ArrowLeft, ArrowRight } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
type CarouselApi = UseEmblaCarouselType[1]
|
||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
||||
type CarouselOptions = UseCarouselParameters[0]
|
||||
type CarouselPlugin = UseCarouselParameters[1]
|
||||
|
||||
type CarouselProps = {
|
||||
opts?: CarouselOptions
|
||||
plugins?: CarouselPlugin
|
||||
orientation?: 'horizontal' | 'vertical'
|
||||
setApi?: (api: CarouselApi) => void
|
||||
}
|
||||
|
||||
type CarouselContextProps = {
|
||||
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
||||
api: ReturnType<typeof useEmblaCarousel>[1]
|
||||
scrollPrev: () => void
|
||||
scrollNext: () => void
|
||||
canScrollPrev: boolean
|
||||
canScrollNext: boolean
|
||||
} & CarouselProps
|
||||
|
||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
|
||||
|
||||
function useCarousel() {
|
||||
const context = React.useContext(CarouselContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('useCarousel must be used within a <Carousel />')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
const Carousel = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & CarouselProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
orientation = 'horizontal',
|
||||
opts,
|
||||
setApi,
|
||||
plugins,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [carouselRef, api] = useEmblaCarousel(
|
||||
{
|
||||
...opts,
|
||||
axis: orientation === 'horizontal' ? 'x' : 'y',
|
||||
},
|
||||
plugins,
|
||||
)
|
||||
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
||||
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
||||
|
||||
const onSelect = React.useCallback((api: CarouselApi) => {
|
||||
if (!api) {
|
||||
return
|
||||
}
|
||||
|
||||
setCanScrollPrev(api.canScrollPrev())
|
||||
setCanScrollNext(api.canScrollNext())
|
||||
}, [])
|
||||
|
||||
const scrollPrev = React.useCallback(() => {
|
||||
api?.scrollPrev()
|
||||
}, [api])
|
||||
|
||||
const scrollNext = React.useCallback(() => {
|
||||
api?.scrollNext()
|
||||
}, [api])
|
||||
|
||||
const handleKeyDown = React.useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key === 'ArrowLeft') {
|
||||
event.preventDefault()
|
||||
scrollPrev()
|
||||
} else if (event.key === 'ArrowRight') {
|
||||
event.preventDefault()
|
||||
scrollNext()
|
||||
}
|
||||
},
|
||||
[scrollPrev, scrollNext],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api || !setApi) {
|
||||
return
|
||||
}
|
||||
|
||||
setApi(api)
|
||||
}, [api, setApi])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return
|
||||
}
|
||||
|
||||
onSelect(api)
|
||||
api.on('reInit', onSelect)
|
||||
api.on('select', onSelect)
|
||||
|
||||
return () => {
|
||||
api?.off('select', onSelect)
|
||||
}
|
||||
}, [api, onSelect])
|
||||
|
||||
return (
|
||||
<CarouselContext.Provider
|
||||
value={{
|
||||
carouselRef,
|
||||
api: api,
|
||||
opts,
|
||||
orientation:
|
||||
orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),
|
||||
scrollPrev,
|
||||
scrollNext,
|
||||
canScrollPrev,
|
||||
canScrollNext,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
onKeyDownCapture={handleKeyDown}
|
||||
className={cn('relative', className)}
|
||||
role="region"
|
||||
aria-roledescription="carousel"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</CarouselContext.Provider>
|
||||
)
|
||||
},
|
||||
)
|
||||
Carousel.displayName = 'Carousel'
|
||||
|
||||
const CarouselContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { carouselRef, orientation } = useCarousel()
|
||||
|
||||
return (
|
||||
<div ref={carouselRef} className="overflow-hidden">
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex',
|
||||
orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
CarouselContent.displayName = 'CarouselContent'
|
||||
|
||||
const CarouselItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { orientation } = useCarousel()
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
role="group"
|
||||
aria-roledescription="slide"
|
||||
className={cn(
|
||||
'min-w-0 shrink-0 grow-0 basis-full',
|
||||
orientation === 'horizontal' ? 'pl-4' : 'pt-4',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
CarouselItem.displayName = 'CarouselItem'
|
||||
|
||||
const CarouselPrevious = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ComponentProps<typeof Button>
|
||||
>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
|
||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
'absolute h-8 w-8 rounded-full',
|
||||
orientation === 'horizontal'
|
||||
? '-left-12 top-1/2 -translate-y-1/2'
|
||||
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||
className,
|
||||
)}
|
||||
disabled={!canScrollPrev}
|
||||
onClick={scrollPrev}
|
||||
{...props}
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
<span className="sr-only">Previous slide</span>
|
||||
</Button>
|
||||
)
|
||||
})
|
||||
CarouselPrevious.displayName = 'CarouselPrevious'
|
||||
|
||||
const CarouselNext = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ComponentProps<typeof Button>
|
||||
>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
|
||||
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
'absolute h-8 w-8 rounded-full',
|
||||
orientation === 'horizontal'
|
||||
? '-right-12 top-1/2 -translate-y-1/2'
|
||||
: '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||
className,
|
||||
)}
|
||||
disabled={!canScrollNext}
|
||||
onClick={scrollNext}
|
||||
{...props}
|
||||
>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
<span className="sr-only">Next slide</span>
|
||||
</Button>
|
||||
)
|
||||
})
|
||||
CarouselNext.displayName = 'CarouselNext'
|
||||
|
||||
export {
|
||||
type CarouselApi,
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselPrevious,
|
||||
CarouselNext,
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user