Compare commits
2 Commits
d97955fdc1
...
4fbda2cfc8
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fbda2cfc8 | |||
| 2f75c1c8bb |
@ -13,6 +13,7 @@
|
|||||||
| **单用户-单容器** | `modules/user_container_manager.py` 会在登录时启动专属容器,并在退出或空闲超时后自动销毁。CLI/Web/Toolbox 复用同一容器,资源配额(默认 0.5 vCPU / 1GB RAM / 2GB 磁盘)由 `.env` 控制。 |
|
| **单用户-单容器** | `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` 等操作进行沙箱化处理,宿主机不再直写用户代码。 |
|
| **容器内文件代理** | `modules/container_file_proxy.py` 通过 `docker exec` 调用内置 Python 脚本,对 `create/read/search/write/modify` 等操作进行沙箱化处理,宿主机不再直写用户代码。 |
|
||||||
| **实时监控面板** | Web “用量统计”抽屉实时展示 Token 消耗、容器 CPU/内存、网络上下行速率(0.5s 刷新)以及项目存储占用(5s 刷新)。CLI `/status` 命令也会附带容器状态。 |
|
| **实时监控面板** | Web “用量统计”抽屉实时展示 Token 消耗、容器 CPU/内存、网络上下行速率(0.5s 刷新)以及项目存储占用(5s 刷新)。CLI `/status` 命令也会附带容器状态。 |
|
||||||
|
| **管理员监控面板** | 管理员身份可在「个人空间」中打开 `/admin/monitor`,集中查看用户用量、容器状态、项目存储与上传审计,支持一键刷新与自动轮询。 |
|
||||||
| **联网能力 + 最小工具集** | 终端镜像改为 `bridge` 网络并预装 `iputils-ping`,方便验证网络连通性;遇到受限环境可以随时在 `.env` 中切换网络模式。 |
|
| **联网能力 + 最小工具集** | 终端镜像改为 `bridge` 网络并预装 `iputils-ping`,方便验证网络连通性;遇到受限环境可以随时在 `.env` 中切换网络模式。 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -121,7 +122,7 @@ python web_server.py
|
|||||||
|
|
||||||
## 开发建议
|
## 开发建议
|
||||||
|
|
||||||
1. **安全**:新增模块前请优先考虑是否可以在容器中实现,避免回退宿主机;如需联网,务必评估外部依赖。
|
1. **安全**:新增模块前请优先考虑是否可以在容器中实现,避免回退宿主机;如需联网,务必评估外部依赖。上传检测现阶段默认关闭 ClamAV(`UPLOAD_CLAMAV_ENABLED=0`),以免 1GB+ 的常驻内存占用,必要时可以在环境变量中显式打开。
|
||||||
2. **日志**:尽量使用 `utils.logger.setup_logger`,便于统一收集。
|
2. **日志**:尽量使用 `utils.logger.setup_logger`,便于统一收集。
|
||||||
3. **测试**:`users/<username>/project/test_scripts/` 提供内存压测脚本,可验证容器限制是否生效;可在 `test/` 下添加更多集成测试。
|
3. **测试**:`users/<username>/project/test_scripts/` 提供内存压测脚本,可验证容器限制是否生效;可在 `test/` 下添加更多集成测试。
|
||||||
4. **文档**:第二阶段总结见 `doc/phases/phase2_summary.md`,安全基线更新见 `doc/security/security_review.md`。
|
4. **文档**:第二阶段总结见 `doc/phases/phase2_summary.md`,安全基线更新见 `doc/security/security_review.md`。
|
||||||
|
|||||||
@ -42,7 +42,8 @@ def _parse_bool(value: str, default: bool = True) -> bool:
|
|||||||
return str(value).strip().lower() not in {"0", "false", "no", "off"}
|
return str(value).strip().lower() not in {"0", "false", "no", "off"}
|
||||||
|
|
||||||
|
|
||||||
UPLOAD_CLAMAV_ENABLED = _parse_bool(os.environ.get("UPLOAD_CLAMAV_ENABLED", "1"), default=True)
|
# 默认关闭 ClamAV 扫描以降低常驻内存占用,可通过设置环境变量重新开启
|
||||||
|
UPLOAD_CLAMAV_ENABLED = _parse_bool(os.environ.get("UPLOAD_CLAMAV_ENABLED", "0"), default=False)
|
||||||
UPLOAD_CLAMAV_BIN = os.environ.get("UPLOAD_CLAMAV_BIN", "clamdscan")
|
UPLOAD_CLAMAV_BIN = os.environ.get("UPLOAD_CLAMAV_BIN", "clamdscan")
|
||||||
UPLOAD_CLAMAV_ARGS = tuple(
|
UPLOAD_CLAMAV_ARGS = tuple(
|
||||||
shlex.split(os.environ.get("UPLOAD_CLAMAV_ARGS", "--fdpass --no-summary --stdout"))
|
shlex.split(os.environ.get("UPLOAD_CLAMAV_ARGS", "--fdpass --no-summary --stdout"))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -336,7 +336,9 @@ class WebTerminal(MainTerminal):
|
|||||||
def broadcast(self, event_type: str, data: Dict):
|
def broadcast(self, event_type: str, data: Dict):
|
||||||
"""广播事件到WebSocket"""
|
"""广播事件到WebSocket"""
|
||||||
if self.message_callback:
|
if self.message_callback:
|
||||||
self.message_callback(event_type, data)
|
payload = dict(data or {})
|
||||||
|
payload.setdefault('conversation_id', self.context_manager.current_conversation_id)
|
||||||
|
self.message_callback(event_type, payload)
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# 覆盖父类方法,添加Web特有的广播功能
|
# 覆盖父类方法,添加Web特有的广播功能
|
||||||
@ -481,10 +483,16 @@ class WebTerminal(MainTerminal):
|
|||||||
|
|
||||||
# 特殊处理某些错误类型
|
# 特殊处理某些错误类型
|
||||||
if not success:
|
if not success:
|
||||||
error_msg = result_data.get('error', '执行失败')
|
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)
|
||||||
|
|
||||||
# 检查是否是参数预检查失败
|
# 检查是否是参数预检查失败
|
||||||
if '参数过大' in error_msg or '内容过长' in error_msg:
|
if error_msg and ('参数过大' in error_msg or '内容过长' in error_msg):
|
||||||
self.broadcast('tool_execution_end', {
|
self.broadcast('tool_execution_end', {
|
||||||
'tool': tool_name,
|
'tool': tool_name,
|
||||||
'success': False,
|
'success': False,
|
||||||
@ -493,7 +501,7 @@ class WebTerminal(MainTerminal):
|
|||||||
'error_type': 'parameter_too_long',
|
'error_type': 'parameter_too_long',
|
||||||
'suggestion': result_data.get('suggestion', '建议分块处理')
|
'suggestion': result_data.get('suggestion', '建议分块处理')
|
||||||
})
|
})
|
||||||
elif 'JSON解析' in error_msg or '参数解析失败' in error_msg:
|
elif error_msg and ('JSON解析' in error_msg or '参数解析失败' in error_msg):
|
||||||
self.broadcast('tool_execution_end', {
|
self.broadcast('tool_execution_end', {
|
||||||
'tool': tool_name,
|
'tool': tool_name,
|
||||||
'success': False,
|
'success': False,
|
||||||
|
|||||||
237
doc/write_file_diff_description.txt
Normal file
237
doc/write_file_diff_description.txt
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
使用统一 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,8 +20,15 @@ from config import (
|
|||||||
SUB_AGENT_TASKS_BASE_DIR,
|
SUB_AGENT_TASKS_BASE_DIR,
|
||||||
)
|
)
|
||||||
from utils.logger import setup_logger
|
from utils.logger import setup_logger
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 静音子智能体日志(交由前端提示/brief_log处理)
|
||||||
logger = setup_logger(__name__)
|
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"}
|
TERMINAL_STATUSES = {"completed", "failed", "timeout"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -152,6 +152,10 @@ class UserManager:
|
|||||||
def list_invite_codes(self):
|
def list_invite_codes(self):
|
||||||
return list(self._invites.values())
|
return list(self._invites.values())
|
||||||
|
|
||||||
|
def list_users(self) -> Dict[str, UserRecord]:
|
||||||
|
"""返回当前注册用户的浅拷贝字典,键为用户名。"""
|
||||||
|
return dict(self._users)
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Internal helpers
|
# Internal helpers
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|||||||
75
package-lock.json
generated
75
package-lock.json
generated
@ -8,6 +8,8 @@
|
|||||||
"name": "ai-agent-frontend",
|
"name": "ai-agent-frontend",
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/html2canvas": "^0.5.35",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"marked": "^11.1.0",
|
"marked": "^11.1.0",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
@ -1303,6 +1305,24 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@ -1327,6 +1347,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "6.21.0",
|
"version": "6.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
|
||||||
@ -1866,6 +1892,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/birpc": {
|
||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.8.0.tgz",
|
||||||
@ -2021,6 +2056,15 @@
|
|||||||
"node": ">= 8"
|
"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": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
@ -2747,6 +2791,19 @@
|
|||||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@ -3727,6 +3784,15 @@
|
|||||||
"url": "https://opencollective.com/synckit"
|
"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": {
|
"node_modules/text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
@ -3824,6 +3890,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.21",
|
"version": "5.4.21",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/html2canvas": "^0.5.35",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"marked": "^11.1.0",
|
"marked": "^11.1.0",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
|
|||||||
2
scratch_test/empty.txt
Normal file
2
scratch_test/empty.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
hello
|
||||||
|
world
|
||||||
100
scripts/kimi_cache_test.py
Normal file
100
scripts/kimi_cache_test.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
"""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()
|
||||||
68
scripts/kimi_official_raw.py
Normal file
68
scripts/kimi_official_raw.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
"""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))
|
||||||
54
scripts/kimi_usage_demo.py
Normal file
54
scripts/kimi_usage_demo.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""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()
|
||||||
21
scripts/liquid-glass-demo/.next/app-build-manifest.json
Normal file
21
scripts/liquid-glass-demo/.next/app-build-manifest.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
20
scripts/liquid-glass-demo/.next/build-manifest.json
Normal file
20
scripts/liquid-glass-demo/.next/build-manifest.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"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
scripts/liquid-glass-demo/.next/cache/.rscinfo
vendored
Normal file
1
scripts/liquid-glass-demo/.next/cache/.rscinfo
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"encryption.key":"nIrtn86Hm0WlHEfVtm35NcUkmbNTI0U+eXfpVfP5kSI=","encryption.expire_at":1765854859753}
|
||||||
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/0.pack.gz
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/0.pack.gz
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/1.pack.gz
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/1.pack.gz
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/index.pack.gz
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/index.pack.gz
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/index.pack.gz.old
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/client-development/index.pack.gz.old
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/0.pack.gz
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/0.pack.gz
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/index.pack.gz
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/index.pack.gz
vendored
Normal file
Binary file not shown.
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/index.pack.gz.old
vendored
Normal file
BIN
scripts/liquid-glass-demo/.next/cache/webpack/server-development/index.pack.gz.old
vendored
Normal file
Binary file not shown.
1
scripts/liquid-glass-demo/.next/package.json
Normal file
1
scripts/liquid-glass-demo/.next/package.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"type": "commonjs"}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"/_not-found/page": "app/_not-found/page.js",
|
||||||
|
"/page": "app/page.js"
|
||||||
|
}
|
||||||
175
scripts/liquid-glass-demo/.next/server/app/_not-found/page.js
Normal file
175
scripts/liquid-glass-demo/.next/server/app/_not-found/page.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
306
scripts/liquid-glass-demo/.next/server/app/page.js
Normal file
306
scripts/liquid-glass-demo/.next/server/app/page.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
|||||||
|
self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]"
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
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",
|
||||||
|
|
||||||
|
];
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"middleware": {},
|
||||||
|
"functions": {},
|
||||||
|
"sortedMiddleware": []
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
self.__REACT_LOADABLE_MANIFEST="{}"
|
||||||
@ -0,0 +1 @@
|
|||||||
|
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}"
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"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}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY\"\n}"
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"node": {},
|
||||||
|
"edge": {},
|
||||||
|
"encryptionKey": "nIrtn86Hm0WlHEfVtm35NcUkmbNTI0U+eXfpVfP5kSI="
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
75
scripts/liquid-glass-demo/.next/server/vendor-chunks/@swc.js
Normal file
75
scripts/liquid-glass-demo/.next/server/vendor-chunks/@swc.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"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
25
scripts/liquid-glass-demo/.next/server/vendor-chunks/clsx.js
Normal file
25
scripts/liquid-glass-demo/.next/server/vendor-chunks/clsx.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"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
1065
scripts/liquid-glass-demo/.next/server/vendor-chunks/motion-dom.js
Normal file
1065
scripts/liquid-glass-demo/.next/server/vendor-chunks/motion-dom.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4314
scripts/liquid-glass-demo/.next/server/vendor-chunks/next.js
Normal file
4314
scripts/liquid-glass-demo/.next/server/vendor-chunks/next.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
215
scripts/liquid-glass-demo/.next/server/webpack-runtime.js
Normal file
215
scripts/liquid-glass-demo/.next/server/webpack-runtime.js
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* 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
92
scripts/liquid-glass-demo/.next/static/chunks/app/layout.js
Normal file
92
scripts/liquid-glass-demo/.next/static/chunks/app/layout.js
Normal file
File diff suppressed because one or more lines are too long
3413
scripts/liquid-glass-demo/.next/static/chunks/app/page.js
Normal file
3413
scripts/liquid-glass-demo/.next/static/chunks/app/page.js
Normal file
File diff suppressed because one or more lines are too long
2796
scripts/liquid-glass-demo/.next/static/chunks/main-app.js
Normal file
2796
scripts/liquid-glass-demo/.next/static/chunks/main-app.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1411
scripts/liquid-glass-demo/.next/static/chunks/webpack.js
Normal file
1411
scripts/liquid-glass-demo/.next/static/chunks/webpack.js
Normal file
File diff suppressed because it is too large
Load Diff
3851
scripts/liquid-glass-demo/.next/static/css/app/layout.css
Normal file
3851
scripts/liquid-glass-demo/.next/static/css/app/layout.css
Normal file
File diff suppressed because it is too large
Load Diff
70
scripts/liquid-glass-demo/.next/static/css/app/page.css
Normal file
70
scripts/liquid-glass-demo/.next/static/css/app/page.css
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
|
||||||
|
!*** 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'
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
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()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
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.
@ -0,0 +1 @@
|
|||||||
|
{"c":[],"r":[],"m":[]}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
"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"));
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
});
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"c":["webpack"],"r":[],"m":[]}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
"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")
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/******/ }
|
||||||
|
);
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
"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")
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/******/ }
|
||||||
|
);
|
||||||
21
scripts/liquid-glass-demo/.next/trace
Normal file
21
scripts/liquid-glass-demo/.next/trace
Normal file
File diff suppressed because one or more lines are too long
84
scripts/liquid-glass-demo/.next/types/app/layout.ts
Normal file
84
scripts/liquid-glass-demo/.next/types/app/layout.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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__'
|
||||||
84
scripts/liquid-glass-demo/.next/types/app/page.ts
Normal file
84
scripts/liquid-glass-demo/.next/types/app/page.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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__'
|
||||||
141
scripts/liquid-glass-demo/.next/types/cache-life.d.ts
vendored
Normal file
141
scripts/liquid-glass-demo/.next/types/cache-life.d.ts
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// 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
scripts/liquid-glass-demo/.next/types/package.json
Normal file
1
scripts/liquid-glass-demo/.next/types/package.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"type": "module"}
|
||||||
11
scripts/liquid-glass-demo/app/custom-slider.css
Normal file
11
scripts/liquid-glass-demo/app/custom-slider.css
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.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;
|
||||||
|
}
|
||||||
21
scripts/liquid-glass-demo/app/fonts.ts
Normal file
21
scripts/liquid-glass-demo/app/fonts.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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 }
|
||||||
43
scripts/liquid-glass-demo/app/globals.css
Normal file
43
scripts/liquid-glass-demo/app/globals.css
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
scripts/liquid-glass-demo/app/layout.tsx
Normal file
25
scripts/liquid-glass-demo/app/layout.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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>
|
||||||
|
)
|
||||||
|
}
|
||||||
18
scripts/liquid-glass-demo/app/local-fonts.ts
Normal file
18
scripts/liquid-glass-demo/app/local-fonts.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
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",
|
||||||
|
})
|
||||||
83
scripts/liquid-glass-demo/app/page.tsx
Normal file
83
scripts/liquid-glass-demo/app/page.tsx
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
"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>
|
||||||
|
)
|
||||||
|
}
|
||||||
21
scripts/liquid-glass-demo/components.json
Normal file
21
scripts/liquid-glass-demo/components.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"$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"
|
||||||
|
}
|
||||||
322
scripts/liquid-glass-demo/components/DynamicFrameLayout.tsx
Normal file
322
scripts/liquid-glass-demo/components/DynamicFrameLayout.tsx
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
"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>
|
||||||
|
)
|
||||||
|
}
|
||||||
222
scripts/liquid-glass-demo/components/FrameComponent.tsx
Normal file
222
scripts/liquid-glass-demo/components/FrameComponent.tsx
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
"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>
|
||||||
|
)
|
||||||
|
}
|
||||||
11
scripts/liquid-glass-demo/components/theme-provider.tsx
Normal file
11
scripts/liquid-glass-demo/components/theme-provider.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
'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>
|
||||||
|
}
|
||||||
58
scripts/liquid-glass-demo/components/ui/accordion.tsx
Normal file
58
scripts/liquid-glass-demo/components/ui/accordion.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
'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 }
|
||||||
141
scripts/liquid-glass-demo/components/ui/alert-dialog.tsx
Normal file
141
scripts/liquid-glass-demo/components/ui/alert-dialog.tsx
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
'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,
|
||||||
|
}
|
||||||
59
scripts/liquid-glass-demo/components/ui/alert.tsx
Normal file
59
scripts/liquid-glass-demo/components/ui/alert.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
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 }
|
||||||
7
scripts/liquid-glass-demo/components/ui/aspect-ratio.tsx
Normal file
7
scripts/liquid-glass-demo/components/ui/aspect-ratio.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'
|
||||||
|
|
||||||
|
const AspectRatio = AspectRatioPrimitive.Root
|
||||||
|
|
||||||
|
export { AspectRatio }
|
||||||
50
scripts/liquid-glass-demo/components/ui/avatar.tsx
Normal file
50
scripts/liquid-glass-demo/components/ui/avatar.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
'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 }
|
||||||
36
scripts/liquid-glass-demo/components/ui/badge.tsx
Normal file
36
scripts/liquid-glass-demo/components/ui/badge.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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 }
|
||||||
115
scripts/liquid-glass-demo/components/ui/breadcrumb.tsx
Normal file
115
scripts/liquid-glass-demo/components/ui/breadcrumb.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
83
scripts/liquid-glass-demo/components/ui/button-group.tsx
Normal file
83
scripts/liquid-glass-demo/components/ui/button-group.tsx
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
56
scripts/liquid-glass-demo/components/ui/button.tsx
Normal file
56
scripts/liquid-glass-demo/components/ui/button.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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 }
|
||||||
213
scripts/liquid-glass-demo/components/ui/calendar.tsx
Normal file
213
scripts/liquid-glass-demo/components/ui/calendar.tsx
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
'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 }
|
||||||
79
scripts/liquid-glass-demo/components/ui/card.tsx
Normal file
79
scripts/liquid-glass-demo/components/ui/card.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
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 }
|
||||||
262
scripts/liquid-glass-demo/components/ui/carousel.tsx
Normal file
262
scripts/liquid-glass-demo/components/ui/carousel.tsx
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
'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