Spaces:
Running
Running
Surf Studio commited on
Commit ·
ddddd0f
1
Parent(s): 1cba7be
ETH blueprint: plan (README)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +9 -0
- README.md +8 -0
- eth-blueprint/README.md +93 -0
- eth-blueprint/tools/push.sh +17 -0
- eth-blueprint/web/package.json +83 -0
- eth-blueprint/web/src/App.tsx +24 -0
- eth-blueprint/web/src/ErrorBoundary.tsx +106 -0
- eth-blueprint/web/src/components/ui/accordion.tsx +55 -0
- eth-blueprint/web/src/components/ui/alert.tsx +59 -0
- eth-blueprint/web/src/components/ui/aspect-ratio.tsx +5 -0
- eth-blueprint/web/src/components/ui/avatar.tsx +48 -0
- eth-blueprint/web/src/components/ui/badge.tsx +36 -0
- eth-blueprint/web/src/components/ui/breadcrumb.tsx +115 -0
- eth-blueprint/web/src/components/ui/button.tsx +57 -0
- eth-blueprint/web/src/components/ui/calendar.tsx +211 -0
- eth-blueprint/web/src/components/ui/card.tsx +76 -0
- eth-blueprint/web/src/components/ui/carousel.tsx +262 -0
- eth-blueprint/web/src/components/ui/checkbox.tsx +30 -0
- eth-blueprint/web/src/components/ui/collapsible.tsx +9 -0
- eth-blueprint/web/src/components/ui/command.tsx +153 -0
- eth-blueprint/web/src/components/ui/context-menu.tsx +200 -0
- eth-blueprint/web/src/components/ui/dialog.tsx +120 -0
- eth-blueprint/web/src/components/ui/drawer.tsx +118 -0
- eth-blueprint/web/src/components/ui/dropdown-menu.tsx +201 -0
- eth-blueprint/web/src/components/ui/form.tsx +176 -0
- eth-blueprint/web/src/components/ui/hover-card.tsx +29 -0
- eth-blueprint/web/src/components/ui/input.tsx +22 -0
- eth-blueprint/web/src/components/ui/label.tsx +26 -0
- eth-blueprint/web/src/components/ui/menubar.tsx +256 -0
- eth-blueprint/web/src/components/ui/navigation-menu.tsx +128 -0
- eth-blueprint/web/src/components/ui/popover.tsx +33 -0
- eth-blueprint/web/src/components/ui/progress.tsx +26 -0
- eth-blueprint/web/src/components/ui/radio-group.tsx +42 -0
- eth-blueprint/web/src/components/ui/resizable.tsx +43 -0
- eth-blueprint/web/src/components/ui/scroll-area.tsx +46 -0
- eth-blueprint/web/src/components/ui/select.tsx +157 -0
- eth-blueprint/web/src/components/ui/separator.tsx +31 -0
- eth-blueprint/web/src/components/ui/sheet.tsx +140 -0
- eth-blueprint/web/src/components/ui/skeleton.tsx +15 -0
- eth-blueprint/web/src/components/ui/slider.tsx +26 -0
- eth-blueprint/web/src/components/ui/sonner.tsx +29 -0
- eth-blueprint/web/src/components/ui/switch.tsx +29 -0
- eth-blueprint/web/src/components/ui/table.tsx +120 -0
- eth-blueprint/web/src/components/ui/tabs.tsx +53 -0
- eth-blueprint/web/src/components/ui/textarea.tsx +22 -0
- eth-blueprint/web/src/components/ui/toast.tsx +129 -0
- eth-blueprint/web/src/components/ui/toaster.tsx +35 -0
- eth-blueprint/web/src/components/ui/toggle-group.tsx +59 -0
- eth-blueprint/web/src/components/ui/toggle.tsx +43 -0
- eth-blueprint/web/src/components/ui/tooltip.tsx +30 -0
.gitattributes
CHANGED
|
@@ -40,3 +40,12 @@ earth-online-sun/web/public/swiss/live/04-scout.jpg filter=lfs diff=lfs merge=lf
|
|
| 40 |
earth-online-sun/web/public/swiss/live/05-small-ego.jpg filter=lfs diff=lfs merge=lfs -text
|
| 41 |
earth-online-sun/web/public/swiss/live/06-off-grid.jpg filter=lfs diff=lfs merge=lfs -text
|
| 42 |
earth-online-sun/web/public/swiss/livephotos.zip filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
earth-online-sun/web/public/swiss/live/05-small-ego.jpg filter=lfs diff=lfs merge=lfs -text
|
| 41 |
earth-online-sun/web/public/swiss/live/06-off-grid.jpg filter=lfs diff=lfs merge=lfs -text
|
| 42 |
earth-online-sun/web/public/swiss/livephotos.zip filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
eth-blueprint/**/*.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
eth-blueprint/**/*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
eth-blueprint/**/*.png filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
eth-blueprint/**/*.mov filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
eth-blueprint/**/*.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
eth-blueprint/**/*.zip filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
eth-blueprint/**/*.woff2 filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
eth-blueprint/**/*.ttf filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
eth-blueprint/**/*.wav filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -10,6 +10,14 @@ app_port: 7860
|
|
| 10 |
|
| 11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
---
|
| 14 |
|
| 15 |
# 《地球 Online · 2026 版本更新公告》—— 孙宇晨最新访谈像素解说片
|
|
|
|
| 10 |
|
| 11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
| 12 |
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# 🆕 最新项目:《世界计算机施工图》—— 以太坊 2013→2026 发展史(蓝图风格)
|
| 16 |
+
|
| 17 |
+
> 目录:[`eth-blueprint/`](eth-blueprint/README.md) | 完整计划与进度日志见 **`eth-blueprint/README.md`**。
|
| 18 |
+
> 本仓库原有项目全部保留;Space 首页切换为新项目,原项目仍可在 `/earth-online-sun/` 访问。
|
| 19 |
+
|
| 20 |
+
|
| 21 |
---
|
| 22 |
|
| 23 |
# 《地球 Online · 2026 版本更新公告》—— 孙宇晨最新访谈像素解说片
|
eth-blueprint/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 《世界计算机施工图》—— 以太坊 2013→2026 发展史 · 蓝图风格解说片
|
| 2 |
+
|
| 3 |
+
> 新增项目目录:`eth-blueprint/`(本仓库原有内容一律保留,只做新增)。
|
| 4 |
+
> 本文件是**施工计划 + 进度日志**:先写计划,再动手;每完成一个大动作就推送一次到本 Space。
|
| 5 |
+
|
| 6 |
+
## 0. 一句话
|
| 7 |
+
|
| 8 |
+
把以太坊 13 年的发展史画成**一张会自己画图的工程蓝图**:
|
| 9 |
+
2013 年一个 19 岁的年轻人在纸上画了一台不存在的机器——"世界计算机"。之后每一次升级,
|
| 10 |
+
都是这张图纸上的一次**修订(REV)**:创世、分叉、发币标准、DeFi、销毁、合并(空中换引擎)、
|
| 11 |
+
Blob、PeerDAS……直到今天仍是"施工中"的 Glamsterdam。
|
| 12 |
+
|
| 13 |
+
## 1. 风格选择(lemo-opuscar)
|
| 14 |
+
|
| 15 |
+
从 lemo-opuscar 的 43 种风格中选用 **`styles/blueprint`(蓝图 / 工程制图)**,理由:
|
| 16 |
+
|
| 17 |
+
- 以太坊本身就是一台"被设计出来的机器",路线图天然就是一份不断修订的工程图纸;
|
| 18 |
+
- 风格自带的"修订栏(title block)讲故事""FIG. 编号即转场""起草顺序""实时标注"几种原生手法,
|
| 19 |
+
正好对应"版本升级""时间线""数据变化";
|
| 20 |
+
- 风格规定:蓝白两色 + **全片只用一次的红色印章**——留给 2022 年"合并"这个情绪顶点。
|
| 21 |
+
|
| 22 |
+
只学风格语法(STYLE.md / DIRECTOR.md / TECHNIQUE.md),**不看、不抄 demo 代码与资产**;
|
| 23 |
+
也**不参考本仓库已有项目的代码与文案**,渲染引擎、场景、音乐、旁白全部从零编写。
|
| 24 |
+
|
| 25 |
+
## 2. 需求逐条对应
|
| 26 |
+
|
| 27 |
+
| # | 要求 | 实现方式 |
|
| 28 |
+
|---|---|---|
|
| 29 |
+
| 1 | lemo-opuscar 合适风格做 ETH 发展史 | Blueprint 蓝图风格,13 个 FIG.,时间线 2013→2026 |
|
| 30 |
+
| 2 | 音效 + 音乐 + 旁白 | 旁白:edge-tts 中文神经语音逐句合成;音乐:Python 原创合成(拨弦羽管键琴 / 拨奏低音 / 八音盒 / 巴松管式簧音,复调"齿轮动机");音效:笔尖划纸、纸张拍落、齿轮擒纵、硬币、裂纹、印章、引擎轰鸣等程序合成;三层混音、旁白闪避、两遍 loudnorm −14 LUFS |
|
| 31 |
+
| 3 | 网页看视频,不直接交 MP4 | Canvas 2D 确定性 `render(t)` 逐帧绘制 + 预混音轨同步播放 |
|
| 32 |
+
| 4 | 浏览器本地导出 MP4 | WebCodecs(H.264 + AAC,不支持 AAC 时自动回退 Opus)+ MP4 封装,全程在访问者浏览器里完成 |
|
| 33 |
+
| 5 | 手机竖屏 | 引擎与分辨率无关:横屏 1920×1080 / 竖屏 1080×1920;镜头按画幅自动取景,注释框按画幅重新排版;手机访问自动切竖屏 |
|
| 34 |
+
| 6 | 导出 24 / 30 / 60 帧可选 | 导出面板单选,按所选帧率逐帧编码 |
|
| 35 |
+
| 7 | 可复制标题/描述/标签 | 小红书 ≤20 字 ≤10 话题;抖音 ≤30 字 ≤5 话题;B站 ≤80 字 ≤10 话题;视频号 ≤16 字 不限话题;页面实时字数校验 + 一键复制 |
|
| 36 |
+
| 8 | 平台封面 | 小红书 4:3 + 3:4;抖音 4:3 + 3:4;B站 4:3 + 个人空间 16:9;视频号 主页卡片 3:4 + 分享卡片 4:3;同一蓝图引擎绘制,单张下载 + 全部打包 |
|
| 37 |
+
| 9 | livecanvas 实况图(jpg + mov) | 同一引擎在 Node(@napi-rs/canvas)离线渲染 1080×1440、30fps、3 秒动效卡 → ffmpeg 编 H.264 → livecanvas 的 `pair_live_photo.py` 写入 Apple Live Photo 元数据(content identifier + still-image-time)→ ZIP,网页提供下载 |
|
| 38 |
+
| 10 | 进度可监督 | 本 README 先写计划;每个大动作完成后推送到 HF Space `Ethscriptions/tz` |
|
| 39 |
+
|
| 40 |
+
## 3. 故事大纲(TREATMENT 摘要,详见 `TREATMENT.md`)
|
| 41 |
+
|
| 42 |
+
结构:**一张图纸的 REV.0 → REV.12**。镜头像眼睛在一张大图纸上移动,从 FIG.1 横移到 FIG.13,
|
| 43 |
+
右下角修订栏(title block)随剧情一行行填满日期——片尾拉远看到整张图纸,就是以太坊 13 年。
|
| 44 |
+
|
| 45 |
+
| FIG. | 年份 | 画面(起草顺序画出) | 原生手法 |
|
| 46 |
+
|---|---|---|---|
|
| 47 |
+
| 0 | 2013 | 空白图纸,一条中心线划过,折成以太坊菱形 | 起草顺序 |
|
| 48 |
+
| 1 | 2013 | 白皮书:计算器(只会记账)vs 计算机(可编程) | 对比图 Fig.1a / 1b |
|
| 49 |
+
| 2 | 2014 | 众售 42 天,约 3.1 万枚 BTC 落入料斗 | 实时尺寸标注 |
|
| 50 |
+
| 3 | 2015.07.30 | 创世区块,齿轮擒纵开始一格一格转动 | 机构按节拍步进 |
|
| 51 |
+
| 4 | 2016 | The DAO 金库被剖开,约 360 万 ETH 流出;区块 1,920,000 处轨道一分为二 | 剖切线 + 真静默 |
|
| 52 |
+
| 5 | 2017 | ERC-20 冲压机批量冲出代币,ICO 狂潮、管道拥堵 | 生成式堆积 |
|
| 53 |
+
| 6 | 2020–21 | DeFi 积木拼接(x·y=k 曲线实时绘出)、NFT 画框、信标链并行启动 | 爆炸视图拼装 |
|
| 54 |
+
| 7 | 2021.08.05 | 伦敦升级 EIP-1559:基础费进入销毁室 | 斜投影获得厚度 |
|
| 55 |
+
| 8 | 2022.09.15 | **合并**:飞行中更换引擎,PoW 引擎脱离、PoS 引擎对接;能耗 −99.95%;**全片唯一的红色印章** | 静默 → 印章 |
|
| 56 |
+
| 9 | 2023–24 | 上海升级开放提取;坎昆 Blob 侧挂集装箱;二层网络卫星机 | 横移 Fig.→Fig. |
|
| 57 |
+
| 10 | 2025 | Pectra 智能账户;Fusaka PeerDAS 抽样验证(只取一部分数据格) | 数据格点亮 |
|
| 58 |
+
| 11 | 2015–2026 | 真实 ETH 日收盘价曲线(Surf 数据)画在坐标纸上,标注历史高点 | 实时标注 |
|
| 59 |
+
| 12 | 2026 | Glamsterdam:虚线(幻影线)画出尚未施工的零件,状态 PENDING | 修订栏讲故事 |
|
| 60 |
+
| 13 | 尾声 | 拉远整张图纸,灯熄,白线微光;菱形成为"唯一真实之物" | 符号变真实 |
|
| 61 |
+
|
| 62 |
+
## 4. 技术方案
|
| 63 |
+
|
| 64 |
+
```
|
| 65 |
+
script.ts(唯一时间线:场景、旁白、音效节拍)
|
| 66 |
+
├─► tools/tts.py edge-tts 逐句合成 → vo/*.mp3 + 时长 vo.json
|
| 67 |
+
├─► timeline.ts 按 96 BPM 小节网格排布场景(切换落在强拍)
|
| 68 |
+
├─► dump-events.ts 导出 events.json(场景、旁白、音效时间)
|
| 69 |
+
├─► tools/mix.py 音乐 + 音效 + 旁白 → 闪避/压缩 → loudnorm −14 LUFS → soundtrack.mp3
|
| 70 |
+
├─► engine/*.ts Canvas 2D 蓝图引擎:氰版纸、四级线宽、虚线规范、起草动画、笔尖光、阴影线、尺寸线、零件气泡、注释框、修订栏
|
| 71 |
+
├─► 网页播放器 音频为主时钟,requestAnimationFrame 调 render(t)
|
| 72 |
+
├─► 浏览器导出 WebCodecs + MP4 封装,24/30/60 fps,横/竖屏
|
| 73 |
+
├─► 封面 同一引擎绘制 8 张平台封面
|
| 74 |
+
└─► tools/live.ts Node 渲染实况动效卡 → ffmpeg → pair_live_photo.py → ZIP
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
数据:ETH 价格来自 Surf 数据 API(日收盘,2015-08-07 → 2026-10-10 快照);
|
| 78 |
+
史实经联网核对(以太坊基金会博客等),来源列在 `TREATMENT.md`。
|
| 79 |
+
|
| 80 |
+
## 5. 步骤与推送节点
|
| 81 |
+
|
| 82 |
+
1. [x] 写本计划 → **推送 #1**
|
| 83 |
+
2. [ ] 字体子集、数据快照、TREATMENT.md → 推送 #2
|
| 84 |
+
3. [ ] 蓝图引擎 + 13 个场景(横竖屏)→ 推送 #3
|
| 85 |
+
4. [ ] 旁白 + 音乐 + 音效 + 混音 → 推送 #4
|
| 86 |
+
5. [ ] 播放器 + 浏览器 MP4 导出(24/30/60)→ 推送 #5
|
| 87 |
+
6. [ ] 平台封面 + 文案 → 推送 #6
|
| 88 |
+
7. [ ] 实况图 jpg+mov + ZIP → 推送 #7
|
| 89 |
+
8. [ ] 构建静态站、Dockerfile 部署、验收 → 推送 #8
|
| 90 |
+
|
| 91 |
+
## 6. 进度日志
|
| 92 |
+
|
| 93 |
+
- 计划已写好,开始施工。
|
eth-blueprint/tools/push.sh
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
# Sync this project into the HF Space clone and push. Usage: push.sh "commit message"
|
| 3 |
+
set -e
|
| 4 |
+
SPACE=/tmp/hfspace
|
| 5 |
+
DST=$SPACE/eth-blueprint
|
| 6 |
+
mkdir -p $DST/web
|
| 7 |
+
rsync -a --delete --exclude dist --exclude web /workspaces/eth-blueprint/ $DST/ --exclude .venv --exclude out
|
| 8 |
+
rsync -a --delete --exclude node_modules --exclude dist --exclude .vite /workspaces/frontend/src/ $DST/web/src/
|
| 9 |
+
rsync -a --delete /workspaces/frontend/public/ $DST/web/public/ 2>/dev/null || true
|
| 10 |
+
cp /workspaces/frontend/package.json $DST/web/package.json
|
| 11 |
+
[ -d /workspaces/frontend/dist/client ] && rsync -a --delete /workspaces/frontend/dist/client/ $DST/dist/ || true
|
| 12 |
+
cd $SPACE
|
| 13 |
+
git lfs install --local >/dev/null
|
| 14 |
+
git add -A
|
| 15 |
+
git -c user.name="Surf Studio" -c user.email="studio@surf.local" commit -q -m "$1" || echo "nothing to commit"
|
| 16 |
+
git push -q origin HEAD:main 2>&1 | tail -3
|
| 17 |
+
git log --oneline | head -1
|
eth-blueprint/web/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "frontend",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.0.0",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "node scripts/check-env.cjs vite",
|
| 8 |
+
"build": "node scripts/check-env.cjs npm run build:client && npm run build:server",
|
| 9 |
+
"build:client": "vite build --outDir dist/client",
|
| 10 |
+
"build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server",
|
| 11 |
+
"lint": "eslint .",
|
| 12 |
+
"preview": "vite preview",
|
| 13 |
+
"type-check": "tsc --noEmit --incremental"
|
| 14 |
+
},
|
| 15 |
+
"dependencies": {
|
| 16 |
+
"@surf-ai/theme": "latest",
|
| 17 |
+
"react": "19.2.4",
|
| 18 |
+
"react-dom": "19.2.4",
|
| 19 |
+
"class-variance-authority": "0.7.1",
|
| 20 |
+
"clsx": "2.1.1",
|
| 21 |
+
"tailwind-merge": "2.6.1",
|
| 22 |
+
"lucide-react": "0.454.0",
|
| 23 |
+
"next-themes": "0.4.6",
|
| 24 |
+
"echarts": "5.6.0",
|
| 25 |
+
"echarts-for-react": "3.0.6",
|
| 26 |
+
"@radix-ui/react-accordion": "1.2.12",
|
| 27 |
+
"@radix-ui/react-aspect-ratio": "1.1.8",
|
| 28 |
+
"@radix-ui/react-avatar": "1.1.11",
|
| 29 |
+
"@radix-ui/react-checkbox": "1.3.3",
|
| 30 |
+
"@radix-ui/react-collapsible": "1.1.12",
|
| 31 |
+
"@radix-ui/react-context-menu": "2.2.16",
|
| 32 |
+
"@radix-ui/react-dialog": "1.1.15",
|
| 33 |
+
"@radix-ui/react-dropdown-menu": "2.1.16",
|
| 34 |
+
"@radix-ui/react-hover-card": "1.1.15",
|
| 35 |
+
"@radix-ui/react-label": "2.1.8",
|
| 36 |
+
"@radix-ui/react-menubar": "1.1.16",
|
| 37 |
+
"@radix-ui/react-navigation-menu": "1.2.14",
|
| 38 |
+
"@radix-ui/react-popover": "1.1.15",
|
| 39 |
+
"@radix-ui/react-progress": "1.1.8",
|
| 40 |
+
"@radix-ui/react-radio-group": "1.3.8",
|
| 41 |
+
"@radix-ui/react-scroll-area": "1.2.10",
|
| 42 |
+
"@radix-ui/react-select": "2.2.6",
|
| 43 |
+
"@radix-ui/react-separator": "1.1.8",
|
| 44 |
+
"@radix-ui/react-slider": "1.3.6",
|
| 45 |
+
"@radix-ui/react-slot": "1.2.4",
|
| 46 |
+
"@radix-ui/react-switch": "1.2.6",
|
| 47 |
+
"@radix-ui/react-tabs": "1.1.13",
|
| 48 |
+
"@radix-ui/react-toast": "1.2.15",
|
| 49 |
+
"@radix-ui/react-toggle": "1.1.10",
|
| 50 |
+
"@radix-ui/react-toggle-group": "1.1.11",
|
| 51 |
+
"@radix-ui/react-tooltip": "1.2.8",
|
| 52 |
+
"sonner": "1.7.4",
|
| 53 |
+
"cmdk": "1.1.1",
|
| 54 |
+
"vaul": "1.1.2",
|
| 55 |
+
"embla-carousel-react": "8.6.0",
|
| 56 |
+
"react-day-picker": "9.14.0",
|
| 57 |
+
"react-resizable-panels": "4.7.6",
|
| 58 |
+
"react-hook-form": "7.72.0",
|
| 59 |
+
"@hookform/resolvers": "5.2.2",
|
| 60 |
+
"date-fns": "4.1.0",
|
| 61 |
+
"zod": "3.25.76",
|
| 62 |
+
"@tanstack/react-query": "5.94.5",
|
| 63 |
+
"@tanstack/query-core": "5.94.5",
|
| 64 |
+
"scheduler": "0.27.0"
|
| 65 |
+
},
|
| 66 |
+
"devDependencies": {
|
| 67 |
+
"@types/react": "19.2.14",
|
| 68 |
+
"@types/react-dom": "19.2.3",
|
| 69 |
+
"@types/node": "22.19.15",
|
| 70 |
+
"@eslint/js": "9.39.4",
|
| 71 |
+
"@vitejs/plugin-react": "4.7.0",
|
| 72 |
+
"@tailwindcss/vite": "4.2.2",
|
| 73 |
+
"eslint": "9.39.4",
|
| 74 |
+
"eslint-plugin-react-hooks": "5.2.0",
|
| 75 |
+
"eslint-plugin-react-refresh": "0.4.26",
|
| 76 |
+
"globals": "16.5.0",
|
| 77 |
+
"tailwindcss": "4.2.2",
|
| 78 |
+
"tw-animate-css": "1.4.0",
|
| 79 |
+
"typescript-eslint": "8.57.1",
|
| 80 |
+
"typescript": "5.9.3",
|
| 81 |
+
"vite": "6.4.2"
|
| 82 |
+
}
|
| 83 |
+
}
|
eth-blueprint/web/src/App.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const SURF_LOGO_PATH = "M14.6875 13.333C15.0977 13.333 15.4859 13.5196 15.7422 13.8398L17.8721 16.502C17.9009 16.538 17.9308 16.5721 17.9619 16.6035C18.3091 16.9542 18.7529 17.3405 18.7529 17.834C18.7528 18.3399 18.3428 18.75 17.8369 18.75H17.5713C17.2123 18.75 16.8727 18.5869 16.6484 18.3066L15.4678 16.8311C14.761 15.9479 13.3369 16.4478 13.3369 17.5791V18.6494C13.3369 18.7062 13.2882 18.75 13.2314 18.75H11.3584C10.7127 18.75 10.1016 18.4564 9.69824 17.9521L8.80176 16.8311C8.09497 15.9477 6.66993 16.4478 6.66992 17.5791V18.6494C6.66991 18.7062 6.62124 18.75 6.56445 18.75H4.69141C4.04589 18.75 3.43548 18.4562 3.03223 17.9521L2.13477 16.8311C1.77885 16.3862 1.25293 15.931 1.25293 15.3613V13.4395C1.253 13.3822 1.29729 13.3331 1.35449 13.333C1.7646 13.3332 2.15295 13.5196 2.40918 13.8398L4.53809 16.502C5.24478 17.3853 6.66962 16.886 6.66992 15.7549V14.6836C6.67018 13.9379 7.27483 13.3332 8.02051 13.333C8.43065 13.333 8.81884 13.5197 9.0752 13.8398L11.2051 16.502C11.9097 17.3827 13.3282 16.8887 13.3369 15.7646V14.6836C13.3372 13.9378 13.9417 13.3331 14.6875 13.333ZM14.6875 6.66699C15.0978 6.66702 15.4859 6.85347 15.7422 7.17383L17.8721 9.83594C18.2276 10.2801 18.7526 10.7339 18.7529 11.3027V13.2266C18.7528 13.2833 18.7091 13.333 18.6523 13.333C18.2421 13.3329 17.8539 13.1465 17.5977 12.8262L15.4678 10.1641C14.7609 9.28113 13.3369 9.78089 13.3369 10.9121V11.9824C13.3369 12.7282 12.7321 13.3328 11.9863 13.333C11.5761 13.3329 11.187 13.1465 10.9307 12.8262L8.80176 10.1641C8.09497 9.28072 6.66993 9.78076 6.66992 10.9121V11.9824C6.66992 12.7284 6.06525 13.3329 5.31934 13.333C4.90908 13.3329 4.52094 13.1465 4.26465 12.8262L2.13477 10.1641C1.7788 9.71925 1.25293 9.26403 1.25293 8.69434V6.77344C1.253 6.71621 1.29728 6.6671 1.35449 6.66699C1.76461 6.66714 2.15295 6.85359 2.40918 7.17383L4.53809 9.83594C5.24487 10.7193 6.66989 10.2192 6.66992 9.08789V8.01758C6.66992 7.27168 7.27467 6.66722 8.02051 6.66699C8.43082 6.66699 8.81885 6.85345 9.0752 7.17383L11.2051 9.83594C11.9097 10.7163 13.3279 10.2223 13.3369 9.09863V8.01758C13.3369 7.27161 13.9416 6.6671 14.6875 6.66699ZM2.43555 1.25C2.79488 1.25 3.13499 1.41367 3.35938 1.69434L4.53809 3.16895C5.24485 4.05241 6.66991 3.55228 6.66992 2.4209V1.35059C6.66993 1.29391 6.71874 1.25017 6.77539 1.25H8.64844C9.29394 1.25 9.90438 1.5438 10.3076 2.04785L11.2051 3.16895C11.9097 4.04967 13.3282 3.55564 13.3369 2.43164V1.35059C13.3369 1.29391 13.3857 1.25017 13.4424 1.25H15.3154C15.9609 1.25 16.5714 1.5438 16.9746 2.04785L17.8721 3.16895C18.2275 3.61314 18.7526 4.06689 18.7529 4.63574V6.56055C18.7528 6.61728 18.7091 6.66699 18.6523 6.66699C18.2421 6.66688 17.8539 6.4795 17.5977 6.15918L15.4678 3.49805C14.761 2.61474 13.3371 3.11388 13.3369 4.24512V5.31543C13.3369 6.06126 12.7321 6.66673 11.9863 6.66699C11.5761 6.66693 11.187 6.47955 10.9307 6.15918L8.80176 3.49805C8.095 2.61474 6.67006 3.11388 6.66992 4.24512V5.31543C6.66992 6.06137 6.06525 6.66691 5.31934 6.66699C4.90908 6.66693 4.52094 6.47955 4.26465 6.15918L2.13477 3.49805C2.10558 3.46158 2.07543 3.42725 2.04395 3.39551C1.6966 3.04528 1.25293 2.6583 1.25293 2.16504C1.25317 1.65963 1.66348 1.25 2.16895 1.25H2.43555Z"
|
| 2 |
+
|
| 3 |
+
function SurfLogo() {
|
| 4 |
+
return (
|
| 5 |
+
<svg width="40" height="40" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
| 6 |
+
<path d={SURF_LOGO_PATH} fill="var(--fg-base, #212121)" />
|
| 7 |
+
</svg>
|
| 8 |
+
)
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
// Frontend API calls should use `src/lib/api.ts`, not absolute `/api/...` URLs.
|
| 12 |
+
export default function App() {
|
| 13 |
+
return (
|
| 14 |
+
<div data-surf-placeholder className="min-h-screen flex flex-col items-center justify-center gap-4 rounded-[14px]" style={{ background: 'var(--bg-chat-nav, #f4f4f4)', border: '1px solid var(--border-strong, rgba(42,42,42,0.08))' }}>
|
| 15 |
+
<SurfLogo />
|
| 16 |
+
<h1 className="font-black text-[36px] leading-[44px] text-[var(--fg-base,#212121)]">
|
| 17 |
+
GM, Builder<span style={{ color: 'var(--brand-100, #ff2882)' }}>.</span>
|
| 18 |
+
</h1>
|
| 19 |
+
<p className="text-xl leading-7 text-[var(--fg-subtle,#7a7a7a)]">
|
| 20 |
+
Start your crypto project here!
|
| 21 |
+
</p>
|
| 22 |
+
</div>
|
| 23 |
+
)
|
| 24 |
+
}
|
eth-blueprint/web/src/ErrorBoundary.tsx
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Component, type ReactNode } from 'react'
|
| 2 |
+
|
| 3 |
+
interface Props { children: ReactNode; fallback?: ReactNode }
|
| 4 |
+
interface State { error: Error | null }
|
| 5 |
+
|
| 6 |
+
// Auto-reload config for transient dep-optimization errors.
|
| 7 |
+
// Shares the same key as entry-client's cold-start guard so reload
|
| 8 |
+
// attempts are counted together, preventing double reload loops.
|
| 9 |
+
const RELOAD_KEY = '__dep_reload'
|
| 10 |
+
const MAX_RELOADS = 6
|
| 11 |
+
// If the last reload was more than this many ms ago, reset the counter.
|
| 12 |
+
// This prevents stale counters from blocking legitimate retries on a
|
| 13 |
+
// later visit, while still capping rapid reload loops.
|
| 14 |
+
const RELOAD_WINDOW_MS = 60_000
|
| 15 |
+
|
| 16 |
+
// Patterns that indicate React modules loaded as stubs (dep optimization in progress)
|
| 17 |
+
const DEP_OPT_PATTERNS = [
|
| 18 |
+
"reading 'useState'",
|
| 19 |
+
"reading 'useEffect'",
|
| 20 |
+
"reading 'useRef'",
|
| 21 |
+
"reading 'useCallback'",
|
| 22 |
+
"reading 'useMemo'",
|
| 23 |
+
"reading 'useContext'",
|
| 24 |
+
"reading 'useReducer'",
|
| 25 |
+
]
|
| 26 |
+
|
| 27 |
+
function isDepOptError(msg: string): boolean {
|
| 28 |
+
return DEP_OPT_PATTERNS.some((p) => msg.includes(p))
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// Shared format with entry-client: { c: count, t: timestamp }
|
| 32 |
+
function getReloadState(): { c: number; t: number } {
|
| 33 |
+
try {
|
| 34 |
+
const raw = sessionStorage.getItem(RELOAD_KEY)
|
| 35 |
+
if (raw) return JSON.parse(raw)
|
| 36 |
+
} catch { /* ignore parse errors */ }
|
| 37 |
+
return { c: 0, t: 0 }
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
export default class ErrorBoundary extends Component<Props, State> {
|
| 41 |
+
state: State = { error: null }
|
| 42 |
+
|
| 43 |
+
static getDerivedStateFromError(error: Error) {
|
| 44 |
+
return { error }
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
componentDidCatch(error: Error) {
|
| 48 |
+
if (!isDepOptError(error.message)) return
|
| 49 |
+
// Vite dep optimization may serve React stubs during cold start.
|
| 50 |
+
// Auto-reload so the browser fetches the real modules once ready.
|
| 51 |
+
const prev = getReloadState()
|
| 52 |
+
// Reset counter if outside the rapid-reload window (stale from earlier visit)
|
| 53 |
+
const count = (Date.now() - prev.t > RELOAD_WINDOW_MS) ? 0 : prev.c
|
| 54 |
+
if (count < MAX_RELOADS) {
|
| 55 |
+
sessionStorage.setItem(RELOAD_KEY, JSON.stringify({ c: count + 1, t: Date.now() }))
|
| 56 |
+
setTimeout(() => location.reload(), 3000)
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
render() {
|
| 61 |
+
if (this.state.error) {
|
| 62 |
+
if (this.props.fallback) return this.props.fallback
|
| 63 |
+
|
| 64 |
+
// Show a friendlier message for dep optimization errors that will auto-reload
|
| 65 |
+
if (isDepOptError(this.state.error.message)) {
|
| 66 |
+
const { c, t } = getReloadState()
|
| 67 |
+
const fresh = (Date.now() - t <= RELOAD_WINDOW_MS)
|
| 68 |
+
if (!fresh || c < MAX_RELOADS) {
|
| 69 |
+
return (
|
| 70 |
+
<div style={{
|
| 71 |
+
padding: '24px',
|
| 72 |
+
margin: '16px',
|
| 73 |
+
borderRadius: '12px',
|
| 74 |
+
background: 'rgba(59,130,246,0.06)',
|
| 75 |
+
border: '1px solid rgba(59,130,246,0.15)',
|
| 76 |
+
color: '#3b82f6',
|
| 77 |
+
fontSize: '13px',
|
| 78 |
+
fontFamily: 'system-ui, sans-serif',
|
| 79 |
+
textAlign: 'center',
|
| 80 |
+
}}>
|
| 81 |
+
<p style={{ fontWeight: 600, marginBottom: '4px' }}>Loading dependencies...</p>
|
| 82 |
+
<p style={{ opacity: 0.7, fontSize: '12px' }}>Reloading automatically</p>
|
| 83 |
+
</div>
|
| 84 |
+
)
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
return (
|
| 89 |
+
<div style={{
|
| 90 |
+
padding: '24px',
|
| 91 |
+
margin: '16px',
|
| 92 |
+
borderRadius: '12px',
|
| 93 |
+
background: 'rgba(245,34,45,0.06)',
|
| 94 |
+
border: '1px solid rgba(245,34,45,0.15)',
|
| 95 |
+
color: '#c0392b',
|
| 96 |
+
fontSize: '13px',
|
| 97 |
+
fontFamily: 'monospace',
|
| 98 |
+
}}>
|
| 99 |
+
<p style={{ fontWeight: 600, marginBottom: '8px' }}>Component Error</p>
|
| 100 |
+
<p style={{ opacity: 0.8 }}>{this.state.error.message}</p>
|
| 101 |
+
</div>
|
| 102 |
+
)
|
| 103 |
+
}
|
| 104 |
+
return this.props.children
|
| 105 |
+
}
|
| 106 |
+
}
|
eth-blueprint/web/src/components/ui/accordion.tsx
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
| 3 |
+
import { ChevronDown } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const Accordion = AccordionPrimitive.Root
|
| 8 |
+
|
| 9 |
+
const AccordionItem = React.forwardRef<
|
| 10 |
+
React.ElementRef<typeof AccordionPrimitive.Item>,
|
| 11 |
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
| 12 |
+
>(({ className, ...props }, ref) => (
|
| 13 |
+
<AccordionPrimitive.Item
|
| 14 |
+
ref={ref}
|
| 15 |
+
className={cn("border-b", className)}
|
| 16 |
+
{...props}
|
| 17 |
+
/>
|
| 18 |
+
))
|
| 19 |
+
AccordionItem.displayName = "AccordionItem"
|
| 20 |
+
|
| 21 |
+
const AccordionTrigger = React.forwardRef<
|
| 22 |
+
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
| 23 |
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
| 24 |
+
>(({ className, children, ...props }, ref) => (
|
| 25 |
+
<AccordionPrimitive.Header className="flex">
|
| 26 |
+
<AccordionPrimitive.Trigger
|
| 27 |
+
ref={ref}
|
| 28 |
+
className={cn(
|
| 29 |
+
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
|
| 30 |
+
className
|
| 31 |
+
)}
|
| 32 |
+
{...props}
|
| 33 |
+
>
|
| 34 |
+
{children}
|
| 35 |
+
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
|
| 36 |
+
</AccordionPrimitive.Trigger>
|
| 37 |
+
</AccordionPrimitive.Header>
|
| 38 |
+
))
|
| 39 |
+
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
| 40 |
+
|
| 41 |
+
const AccordionContent = React.forwardRef<
|
| 42 |
+
React.ElementRef<typeof AccordionPrimitive.Content>,
|
| 43 |
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
| 44 |
+
>(({ className, children, ...props }, ref) => (
|
| 45 |
+
<AccordionPrimitive.Content
|
| 46 |
+
ref={ref}
|
| 47 |
+
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
| 48 |
+
{...props}
|
| 49 |
+
>
|
| 50 |
+
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
| 51 |
+
</AccordionPrimitive.Content>
|
| 52 |
+
))
|
| 53 |
+
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
| 54 |
+
|
| 55 |
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
eth-blueprint/web/src/components/ui/alert.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const alertVariants = cva(
|
| 7 |
+
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
| 8 |
+
{
|
| 9 |
+
variants: {
|
| 10 |
+
variant: {
|
| 11 |
+
default: "bg-background text-foreground",
|
| 12 |
+
destructive:
|
| 13 |
+
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
| 14 |
+
},
|
| 15 |
+
},
|
| 16 |
+
defaultVariants: {
|
| 17 |
+
variant: "default",
|
| 18 |
+
},
|
| 19 |
+
}
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
const Alert = React.forwardRef<
|
| 23 |
+
HTMLDivElement,
|
| 24 |
+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
| 25 |
+
>(({ className, variant, ...props }, ref) => (
|
| 26 |
+
<div
|
| 27 |
+
ref={ref}
|
| 28 |
+
role="alert"
|
| 29 |
+
className={cn(alertVariants({ variant }), className)}
|
| 30 |
+
{...props}
|
| 31 |
+
/>
|
| 32 |
+
))
|
| 33 |
+
Alert.displayName = "Alert"
|
| 34 |
+
|
| 35 |
+
const AlertTitle = React.forwardRef<
|
| 36 |
+
HTMLParagraphElement,
|
| 37 |
+
React.HTMLAttributes<HTMLHeadingElement>
|
| 38 |
+
>(({ className, ...props }, ref) => (
|
| 39 |
+
<h5
|
| 40 |
+
ref={ref}
|
| 41 |
+
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
| 42 |
+
{...props}
|
| 43 |
+
/>
|
| 44 |
+
))
|
| 45 |
+
AlertTitle.displayName = "AlertTitle"
|
| 46 |
+
|
| 47 |
+
const AlertDescription = React.forwardRef<
|
| 48 |
+
HTMLParagraphElement,
|
| 49 |
+
React.HTMLAttributes<HTMLParagraphElement>
|
| 50 |
+
>(({ className, ...props }, ref) => (
|
| 51 |
+
<div
|
| 52 |
+
ref={ref}
|
| 53 |
+
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
| 54 |
+
{...props}
|
| 55 |
+
/>
|
| 56 |
+
))
|
| 57 |
+
AlertDescription.displayName = "AlertDescription"
|
| 58 |
+
|
| 59 |
+
export { Alert, AlertTitle, AlertDescription }
|
eth-blueprint/web/src/components/ui/aspect-ratio.tsx
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
|
| 2 |
+
|
| 3 |
+
const AspectRatio = AspectRatioPrimitive.Root
|
| 4 |
+
|
| 5 |
+
export { AspectRatio }
|
eth-blueprint/web/src/components/ui/avatar.tsx
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Avatar = React.forwardRef<
|
| 7 |
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
| 8 |
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
| 9 |
+
>(({ className, ...props }, ref) => (
|
| 10 |
+
<AvatarPrimitive.Root
|
| 11 |
+
ref={ref}
|
| 12 |
+
className={cn(
|
| 13 |
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
| 14 |
+
className
|
| 15 |
+
)}
|
| 16 |
+
{...props}
|
| 17 |
+
/>
|
| 18 |
+
))
|
| 19 |
+
Avatar.displayName = AvatarPrimitive.Root.displayName
|
| 20 |
+
|
| 21 |
+
const AvatarImage = React.forwardRef<
|
| 22 |
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
| 23 |
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
| 24 |
+
>(({ className, ...props }, ref) => (
|
| 25 |
+
<AvatarPrimitive.Image
|
| 26 |
+
ref={ref}
|
| 27 |
+
className={cn("aspect-square h-full w-full", className)}
|
| 28 |
+
{...props}
|
| 29 |
+
/>
|
| 30 |
+
))
|
| 31 |
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
| 32 |
+
|
| 33 |
+
const AvatarFallback = React.forwardRef<
|
| 34 |
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
| 35 |
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
| 36 |
+
>(({ className, ...props }, ref) => (
|
| 37 |
+
<AvatarPrimitive.Fallback
|
| 38 |
+
ref={ref}
|
| 39 |
+
className={cn(
|
| 40 |
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
| 41 |
+
className
|
| 42 |
+
)}
|
| 43 |
+
{...props}
|
| 44 |
+
/>
|
| 45 |
+
))
|
| 46 |
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
| 47 |
+
|
| 48 |
+
export { Avatar, AvatarImage, AvatarFallback }
|
eth-blueprint/web/src/components/ui/badge.tsx
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const badgeVariants = cva(
|
| 7 |
+
"inline-flex items-center rounded-md 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",
|
| 8 |
+
{
|
| 9 |
+
variants: {
|
| 10 |
+
variant: {
|
| 11 |
+
default:
|
| 12 |
+
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
| 13 |
+
secondary:
|
| 14 |
+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
| 15 |
+
destructive:
|
| 16 |
+
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
| 17 |
+
outline: "text-foreground",
|
| 18 |
+
},
|
| 19 |
+
},
|
| 20 |
+
defaultVariants: {
|
| 21 |
+
variant: "default",
|
| 22 |
+
},
|
| 23 |
+
}
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
export interface BadgeProps
|
| 27 |
+
extends React.HTMLAttributes<HTMLDivElement>,
|
| 28 |
+
VariantProps<typeof badgeVariants> {}
|
| 29 |
+
|
| 30 |
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
| 31 |
+
return (
|
| 32 |
+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
| 33 |
+
)
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
export { Badge, badgeVariants }
|
eth-blueprint/web/src/components/ui/breadcrumb.tsx
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { Slot } from "@radix-ui/react-slot"
|
| 3 |
+
import { ChevronRight, MoreHorizontal } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const Breadcrumb = React.forwardRef<
|
| 8 |
+
HTMLElement,
|
| 9 |
+
React.ComponentPropsWithoutRef<"nav"> & {
|
| 10 |
+
separator?: React.ReactNode
|
| 11 |
+
}
|
| 12 |
+
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
|
| 13 |
+
Breadcrumb.displayName = "Breadcrumb"
|
| 14 |
+
|
| 15 |
+
const BreadcrumbList = React.forwardRef<
|
| 16 |
+
HTMLOListElement,
|
| 17 |
+
React.ComponentPropsWithoutRef<"ol">
|
| 18 |
+
>(({ className, ...props }, ref) => (
|
| 19 |
+
<ol
|
| 20 |
+
ref={ref}
|
| 21 |
+
className={cn(
|
| 22 |
+
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
|
| 23 |
+
className
|
| 24 |
+
)}
|
| 25 |
+
{...props}
|
| 26 |
+
/>
|
| 27 |
+
))
|
| 28 |
+
BreadcrumbList.displayName = "BreadcrumbList"
|
| 29 |
+
|
| 30 |
+
const BreadcrumbItem = React.forwardRef<
|
| 31 |
+
HTMLLIElement,
|
| 32 |
+
React.ComponentPropsWithoutRef<"li">
|
| 33 |
+
>(({ className, ...props }, ref) => (
|
| 34 |
+
<li
|
| 35 |
+
ref={ref}
|
| 36 |
+
className={cn("inline-flex items-center gap-1.5", className)}
|
| 37 |
+
{...props}
|
| 38 |
+
/>
|
| 39 |
+
))
|
| 40 |
+
BreadcrumbItem.displayName = "BreadcrumbItem"
|
| 41 |
+
|
| 42 |
+
const BreadcrumbLink = React.forwardRef<
|
| 43 |
+
HTMLAnchorElement,
|
| 44 |
+
React.ComponentPropsWithoutRef<"a"> & {
|
| 45 |
+
asChild?: boolean
|
| 46 |
+
}
|
| 47 |
+
>(({ asChild, className, ...props }, ref) => {
|
| 48 |
+
const Comp = asChild ? Slot : "a"
|
| 49 |
+
|
| 50 |
+
return (
|
| 51 |
+
<Comp
|
| 52 |
+
ref={ref}
|
| 53 |
+
className={cn("transition-colors hover:text-foreground", className)}
|
| 54 |
+
{...props}
|
| 55 |
+
/>
|
| 56 |
+
)
|
| 57 |
+
})
|
| 58 |
+
BreadcrumbLink.displayName = "BreadcrumbLink"
|
| 59 |
+
|
| 60 |
+
const BreadcrumbPage = React.forwardRef<
|
| 61 |
+
HTMLSpanElement,
|
| 62 |
+
React.ComponentPropsWithoutRef<"span">
|
| 63 |
+
>(({ className, ...props }, ref) => (
|
| 64 |
+
<span
|
| 65 |
+
ref={ref}
|
| 66 |
+
role="link"
|
| 67 |
+
aria-disabled="true"
|
| 68 |
+
aria-current="page"
|
| 69 |
+
className={cn("font-normal text-foreground", className)}
|
| 70 |
+
{...props}
|
| 71 |
+
/>
|
| 72 |
+
))
|
| 73 |
+
BreadcrumbPage.displayName = "BreadcrumbPage"
|
| 74 |
+
|
| 75 |
+
const BreadcrumbSeparator = ({
|
| 76 |
+
children,
|
| 77 |
+
className,
|
| 78 |
+
...props
|
| 79 |
+
}: React.ComponentProps<"li">) => (
|
| 80 |
+
<li
|
| 81 |
+
role="presentation"
|
| 82 |
+
aria-hidden="true"
|
| 83 |
+
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
|
| 84 |
+
{...props}
|
| 85 |
+
>
|
| 86 |
+
{children ?? <ChevronRight />}
|
| 87 |
+
</li>
|
| 88 |
+
)
|
| 89 |
+
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
|
| 90 |
+
|
| 91 |
+
const BreadcrumbEllipsis = ({
|
| 92 |
+
className,
|
| 93 |
+
...props
|
| 94 |
+
}: React.ComponentProps<"span">) => (
|
| 95 |
+
<span
|
| 96 |
+
role="presentation"
|
| 97 |
+
aria-hidden="true"
|
| 98 |
+
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
| 99 |
+
{...props}
|
| 100 |
+
>
|
| 101 |
+
<MoreHorizontal className="h-4 w-4" />
|
| 102 |
+
<span className="sr-only">More</span>
|
| 103 |
+
</span>
|
| 104 |
+
)
|
| 105 |
+
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
|
| 106 |
+
|
| 107 |
+
export {
|
| 108 |
+
Breadcrumb,
|
| 109 |
+
BreadcrumbList,
|
| 110 |
+
BreadcrumbItem,
|
| 111 |
+
BreadcrumbLink,
|
| 112 |
+
BreadcrumbPage,
|
| 113 |
+
BreadcrumbSeparator,
|
| 114 |
+
BreadcrumbEllipsis,
|
| 115 |
+
}
|
eth-blueprint/web/src/components/ui/button.tsx
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { Slot } from "@radix-ui/react-slot"
|
| 3 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const buttonVariants = cva(
|
| 8 |
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
| 9 |
+
{
|
| 10 |
+
variants: {
|
| 11 |
+
variant: {
|
| 12 |
+
default:
|
| 13 |
+
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
| 14 |
+
destructive:
|
| 15 |
+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
| 16 |
+
outline:
|
| 17 |
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
| 18 |
+
secondary:
|
| 19 |
+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
| 20 |
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
| 21 |
+
link: "text-primary underline-offset-4 hover:underline",
|
| 22 |
+
},
|
| 23 |
+
size: {
|
| 24 |
+
default: "h-9 px-4 py-2",
|
| 25 |
+
sm: "h-8 rounded-md px-3 text-xs",
|
| 26 |
+
lg: "h-10 rounded-md px-8",
|
| 27 |
+
icon: "h-9 w-9",
|
| 28 |
+
},
|
| 29 |
+
},
|
| 30 |
+
defaultVariants: {
|
| 31 |
+
variant: "default",
|
| 32 |
+
size: "default",
|
| 33 |
+
},
|
| 34 |
+
}
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
export interface ButtonProps
|
| 38 |
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
| 39 |
+
VariantProps<typeof buttonVariants> {
|
| 40 |
+
asChild?: boolean
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
| 44 |
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
| 45 |
+
const Comp = asChild ? Slot : "button"
|
| 46 |
+
return (
|
| 47 |
+
<Comp
|
| 48 |
+
className={cn(buttonVariants({ variant, size, className }))}
|
| 49 |
+
ref={ref}
|
| 50 |
+
{...props}
|
| 51 |
+
/>
|
| 52 |
+
)
|
| 53 |
+
}
|
| 54 |
+
)
|
| 55 |
+
Button.displayName = "Button"
|
| 56 |
+
|
| 57 |
+
export { Button, buttonVariants }
|
eth-blueprint/web/src/components/ui/calendar.tsx
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import {
|
| 3 |
+
ChevronDownIcon,
|
| 4 |
+
ChevronLeftIcon,
|
| 5 |
+
ChevronRightIcon,
|
| 6 |
+
} from "lucide-react"
|
| 7 |
+
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
|
| 8 |
+
|
| 9 |
+
import { cn } from "@/lib/utils"
|
| 10 |
+
import { Button, buttonVariants } from "@/components/ui/button"
|
| 11 |
+
|
| 12 |
+
function Calendar({
|
| 13 |
+
className,
|
| 14 |
+
classNames,
|
| 15 |
+
showOutsideDays = true,
|
| 16 |
+
captionLayout = "label",
|
| 17 |
+
buttonVariant = "ghost",
|
| 18 |
+
formatters,
|
| 19 |
+
components,
|
| 20 |
+
...props
|
| 21 |
+
}: React.ComponentProps<typeof DayPicker> & {
|
| 22 |
+
buttonVariant?: React.ComponentProps<typeof Button>["variant"]
|
| 23 |
+
}) {
|
| 24 |
+
const defaultClassNames = getDefaultClassNames()
|
| 25 |
+
|
| 26 |
+
return (
|
| 27 |
+
<DayPicker
|
| 28 |
+
showOutsideDays={showOutsideDays}
|
| 29 |
+
className={cn(
|
| 30 |
+
"bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
| 31 |
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
| 32 |
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
| 33 |
+
className
|
| 34 |
+
)}
|
| 35 |
+
captionLayout={captionLayout}
|
| 36 |
+
formatters={{
|
| 37 |
+
formatMonthDropdown: (date) =>
|
| 38 |
+
date.toLocaleString("default", { month: "short" }),
|
| 39 |
+
...formatters,
|
| 40 |
+
}}
|
| 41 |
+
classNames={{
|
| 42 |
+
root: cn("w-fit", defaultClassNames.root),
|
| 43 |
+
months: cn(
|
| 44 |
+
"relative flex flex-col gap-4 md:flex-row",
|
| 45 |
+
defaultClassNames.months
|
| 46 |
+
),
|
| 47 |
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
| 48 |
+
nav: cn(
|
| 49 |
+
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
| 50 |
+
defaultClassNames.nav
|
| 51 |
+
),
|
| 52 |
+
button_previous: cn(
|
| 53 |
+
buttonVariants({ variant: buttonVariant }),
|
| 54 |
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
| 55 |
+
defaultClassNames.button_previous
|
| 56 |
+
),
|
| 57 |
+
button_next: cn(
|
| 58 |
+
buttonVariants({ variant: buttonVariant }),
|
| 59 |
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
| 60 |
+
defaultClassNames.button_next
|
| 61 |
+
),
|
| 62 |
+
month_caption: cn(
|
| 63 |
+
"flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
|
| 64 |
+
defaultClassNames.month_caption
|
| 65 |
+
),
|
| 66 |
+
dropdowns: cn(
|
| 67 |
+
"flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
|
| 68 |
+
defaultClassNames.dropdowns
|
| 69 |
+
),
|
| 70 |
+
dropdown_root: cn(
|
| 71 |
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
|
| 72 |
+
defaultClassNames.dropdown_root
|
| 73 |
+
),
|
| 74 |
+
dropdown: cn(
|
| 75 |
+
"bg-popover absolute inset-0 opacity-0",
|
| 76 |
+
defaultClassNames.dropdown
|
| 77 |
+
),
|
| 78 |
+
caption_label: cn(
|
| 79 |
+
"select-none font-medium",
|
| 80 |
+
captionLayout === "label"
|
| 81 |
+
? "text-sm"
|
| 82 |
+
: "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
|
| 83 |
+
defaultClassNames.caption_label
|
| 84 |
+
),
|
| 85 |
+
table: "w-full border-collapse",
|
| 86 |
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
| 87 |
+
weekday: cn(
|
| 88 |
+
"text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
|
| 89 |
+
defaultClassNames.weekday
|
| 90 |
+
),
|
| 91 |
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
| 92 |
+
week_number_header: cn(
|
| 93 |
+
"w-[--cell-size] select-none",
|
| 94 |
+
defaultClassNames.week_number_header
|
| 95 |
+
),
|
| 96 |
+
week_number: cn(
|
| 97 |
+
"text-muted-foreground select-none text-[0.8rem]",
|
| 98 |
+
defaultClassNames.week_number
|
| 99 |
+
),
|
| 100 |
+
day: cn(
|
| 101 |
+
"group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
| 102 |
+
defaultClassNames.day
|
| 103 |
+
),
|
| 104 |
+
range_start: cn(
|
| 105 |
+
"bg-accent rounded-l-md",
|
| 106 |
+
defaultClassNames.range_start
|
| 107 |
+
),
|
| 108 |
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
| 109 |
+
range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
|
| 110 |
+
today: cn(
|
| 111 |
+
"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
|
| 112 |
+
defaultClassNames.today
|
| 113 |
+
),
|
| 114 |
+
outside: cn(
|
| 115 |
+
"text-muted-foreground aria-selected:text-muted-foreground",
|
| 116 |
+
defaultClassNames.outside
|
| 117 |
+
),
|
| 118 |
+
disabled: cn(
|
| 119 |
+
"text-muted-foreground opacity-50",
|
| 120 |
+
defaultClassNames.disabled
|
| 121 |
+
),
|
| 122 |
+
hidden: cn("invisible", defaultClassNames.hidden),
|
| 123 |
+
...classNames,
|
| 124 |
+
}}
|
| 125 |
+
components={{
|
| 126 |
+
Root: ({ className, rootRef, ...props }) => {
|
| 127 |
+
return (
|
| 128 |
+
<div
|
| 129 |
+
data-slot="calendar"
|
| 130 |
+
ref={rootRef}
|
| 131 |
+
className={cn(className)}
|
| 132 |
+
{...props}
|
| 133 |
+
/>
|
| 134 |
+
)
|
| 135 |
+
},
|
| 136 |
+
Chevron: ({ className, orientation, ...props }) => {
|
| 137 |
+
if (orientation === "left") {
|
| 138 |
+
return (
|
| 139 |
+
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
| 140 |
+
)
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
if (orientation === "right") {
|
| 144 |
+
return (
|
| 145 |
+
<ChevronRightIcon
|
| 146 |
+
className={cn("size-4", className)}
|
| 147 |
+
{...props}
|
| 148 |
+
/>
|
| 149 |
+
)
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
return (
|
| 153 |
+
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
| 154 |
+
)
|
| 155 |
+
},
|
| 156 |
+
DayButton: CalendarDayButton,
|
| 157 |
+
WeekNumber: ({ children, ...props }) => {
|
| 158 |
+
return (
|
| 159 |
+
<td {...props}>
|
| 160 |
+
<div className="flex size-[--cell-size] items-center justify-center text-center">
|
| 161 |
+
{children}
|
| 162 |
+
</div>
|
| 163 |
+
</td>
|
| 164 |
+
)
|
| 165 |
+
},
|
| 166 |
+
...components,
|
| 167 |
+
}}
|
| 168 |
+
{...props}
|
| 169 |
+
/>
|
| 170 |
+
)
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
function CalendarDayButton({
|
| 174 |
+
className,
|
| 175 |
+
day,
|
| 176 |
+
modifiers,
|
| 177 |
+
...props
|
| 178 |
+
}: React.ComponentProps<typeof DayButton>) {
|
| 179 |
+
const defaultClassNames = getDefaultClassNames()
|
| 180 |
+
|
| 181 |
+
const ref = React.useRef<HTMLButtonElement>(null)
|
| 182 |
+
React.useEffect(() => {
|
| 183 |
+
if (modifiers.focused) ref.current?.focus()
|
| 184 |
+
}, [modifiers.focused])
|
| 185 |
+
|
| 186 |
+
return (
|
| 187 |
+
<Button
|
| 188 |
+
ref={ref}
|
| 189 |
+
variant="ghost"
|
| 190 |
+
size="icon"
|
| 191 |
+
data-day={day.date.toLocaleDateString()}
|
| 192 |
+
data-selected-single={
|
| 193 |
+
modifiers.selected &&
|
| 194 |
+
!modifiers.range_start &&
|
| 195 |
+
!modifiers.range_end &&
|
| 196 |
+
!modifiers.range_middle
|
| 197 |
+
}
|
| 198 |
+
data-range-start={modifiers.range_start}
|
| 199 |
+
data-range-end={modifiers.range_end}
|
| 200 |
+
data-range-middle={modifiers.range_middle}
|
| 201 |
+
className={cn(
|
| 202 |
+
"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 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70",
|
| 203 |
+
defaultClassNames.day,
|
| 204 |
+
className
|
| 205 |
+
)}
|
| 206 |
+
{...props}
|
| 207 |
+
/>
|
| 208 |
+
)
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
export { Calendar, CalendarDayButton }
|
eth-blueprint/web/src/components/ui/card.tsx
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
|
| 3 |
+
import { cn } from "@/lib/utils"
|
| 4 |
+
|
| 5 |
+
const Card = React.forwardRef<
|
| 6 |
+
HTMLDivElement,
|
| 7 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 8 |
+
>(({ className, ...props }, ref) => (
|
| 9 |
+
<div
|
| 10 |
+
ref={ref}
|
| 11 |
+
className={cn(
|
| 12 |
+
"rounded-xl border bg-card text-card-foreground shadow",
|
| 13 |
+
className
|
| 14 |
+
)}
|
| 15 |
+
{...props}
|
| 16 |
+
/>
|
| 17 |
+
))
|
| 18 |
+
Card.displayName = "Card"
|
| 19 |
+
|
| 20 |
+
const CardHeader = React.forwardRef<
|
| 21 |
+
HTMLDivElement,
|
| 22 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 23 |
+
>(({ className, ...props }, ref) => (
|
| 24 |
+
<div
|
| 25 |
+
ref={ref}
|
| 26 |
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
| 27 |
+
{...props}
|
| 28 |
+
/>
|
| 29 |
+
))
|
| 30 |
+
CardHeader.displayName = "CardHeader"
|
| 31 |
+
|
| 32 |
+
const CardTitle = React.forwardRef<
|
| 33 |
+
HTMLDivElement,
|
| 34 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 35 |
+
>(({ className, ...props }, ref) => (
|
| 36 |
+
<div
|
| 37 |
+
ref={ref}
|
| 38 |
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
| 39 |
+
{...props}
|
| 40 |
+
/>
|
| 41 |
+
))
|
| 42 |
+
CardTitle.displayName = "CardTitle"
|
| 43 |
+
|
| 44 |
+
const CardDescription = React.forwardRef<
|
| 45 |
+
HTMLDivElement,
|
| 46 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 47 |
+
>(({ className, ...props }, ref) => (
|
| 48 |
+
<div
|
| 49 |
+
ref={ref}
|
| 50 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 51 |
+
{...props}
|
| 52 |
+
/>
|
| 53 |
+
))
|
| 54 |
+
CardDescription.displayName = "CardDescription"
|
| 55 |
+
|
| 56 |
+
const CardContent = React.forwardRef<
|
| 57 |
+
HTMLDivElement,
|
| 58 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 59 |
+
>(({ className, ...props }, ref) => (
|
| 60 |
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
| 61 |
+
))
|
| 62 |
+
CardContent.displayName = "CardContent"
|
| 63 |
+
|
| 64 |
+
const CardFooter = React.forwardRef<
|
| 65 |
+
HTMLDivElement,
|
| 66 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 67 |
+
>(({ className, ...props }, ref) => (
|
| 68 |
+
<div
|
| 69 |
+
ref={ref}
|
| 70 |
+
className={cn("flex items-center p-6 pt-0", className)}
|
| 71 |
+
{...props}
|
| 72 |
+
/>
|
| 73 |
+
))
|
| 74 |
+
CardFooter.displayName = "CardFooter"
|
| 75 |
+
|
| 76 |
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
eth-blueprint/web/src/components/ui/carousel.tsx
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import useEmblaCarousel, {
|
| 5 |
+
type UseEmblaCarouselType,
|
| 6 |
+
} from "embla-carousel-react"
|
| 7 |
+
import { ArrowLeft, ArrowRight } from "lucide-react"
|
| 8 |
+
|
| 9 |
+
import { cn } from "@/lib/utils"
|
| 10 |
+
import { Button } from "@/components/ui/button"
|
| 11 |
+
|
| 12 |
+
type CarouselApi = UseEmblaCarouselType[1]
|
| 13 |
+
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
| 14 |
+
type CarouselOptions = UseCarouselParameters[0]
|
| 15 |
+
type CarouselPlugin = UseCarouselParameters[1]
|
| 16 |
+
|
| 17 |
+
type CarouselProps = {
|
| 18 |
+
opts?: CarouselOptions
|
| 19 |
+
plugins?: CarouselPlugin
|
| 20 |
+
orientation?: "horizontal" | "vertical"
|
| 21 |
+
setApi?: (api: CarouselApi) => void
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
type CarouselContextProps = {
|
| 25 |
+
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
| 26 |
+
api: ReturnType<typeof useEmblaCarousel>[1]
|
| 27 |
+
scrollPrev: () => void
|
| 28 |
+
scrollNext: () => void
|
| 29 |
+
canScrollPrev: boolean
|
| 30 |
+
canScrollNext: boolean
|
| 31 |
+
} & CarouselProps
|
| 32 |
+
|
| 33 |
+
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
|
| 34 |
+
|
| 35 |
+
function useCarousel() {
|
| 36 |
+
const context = React.useContext(CarouselContext)
|
| 37 |
+
|
| 38 |
+
if (!context) {
|
| 39 |
+
throw new Error("useCarousel must be used within a <Carousel />")
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
return context
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
const Carousel = React.forwardRef<
|
| 46 |
+
HTMLDivElement,
|
| 47 |
+
React.HTMLAttributes<HTMLDivElement> & CarouselProps
|
| 48 |
+
>(
|
| 49 |
+
(
|
| 50 |
+
{
|
| 51 |
+
orientation = "horizontal",
|
| 52 |
+
opts,
|
| 53 |
+
setApi,
|
| 54 |
+
plugins,
|
| 55 |
+
className,
|
| 56 |
+
children,
|
| 57 |
+
...props
|
| 58 |
+
},
|
| 59 |
+
ref
|
| 60 |
+
) => {
|
| 61 |
+
const [carouselRef, api] = useEmblaCarousel(
|
| 62 |
+
{
|
| 63 |
+
...opts,
|
| 64 |
+
axis: orientation === "horizontal" ? "x" : "y",
|
| 65 |
+
},
|
| 66 |
+
plugins
|
| 67 |
+
)
|
| 68 |
+
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
| 69 |
+
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
| 70 |
+
|
| 71 |
+
const onSelect = React.useCallback((api: CarouselApi) => {
|
| 72 |
+
if (!api) {
|
| 73 |
+
return
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
setCanScrollPrev(api.canScrollPrev())
|
| 77 |
+
setCanScrollNext(api.canScrollNext())
|
| 78 |
+
}, [])
|
| 79 |
+
|
| 80 |
+
const scrollPrev = React.useCallback(() => {
|
| 81 |
+
api?.scrollPrev()
|
| 82 |
+
}, [api])
|
| 83 |
+
|
| 84 |
+
const scrollNext = React.useCallback(() => {
|
| 85 |
+
api?.scrollNext()
|
| 86 |
+
}, [api])
|
| 87 |
+
|
| 88 |
+
const handleKeyDown = React.useCallback(
|
| 89 |
+
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
| 90 |
+
if (event.key === "ArrowLeft") {
|
| 91 |
+
event.preventDefault()
|
| 92 |
+
scrollPrev()
|
| 93 |
+
} else if (event.key === "ArrowRight") {
|
| 94 |
+
event.preventDefault()
|
| 95 |
+
scrollNext()
|
| 96 |
+
}
|
| 97 |
+
},
|
| 98 |
+
[scrollPrev, scrollNext]
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
React.useEffect(() => {
|
| 102 |
+
if (!api || !setApi) {
|
| 103 |
+
return
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
setApi(api)
|
| 107 |
+
}, [api, setApi])
|
| 108 |
+
|
| 109 |
+
React.useEffect(() => {
|
| 110 |
+
if (!api) {
|
| 111 |
+
return
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
onSelect(api)
|
| 115 |
+
api.on("reInit", onSelect)
|
| 116 |
+
api.on("select", onSelect)
|
| 117 |
+
|
| 118 |
+
return () => {
|
| 119 |
+
api?.off("select", onSelect)
|
| 120 |
+
}
|
| 121 |
+
}, [api, onSelect])
|
| 122 |
+
|
| 123 |
+
return (
|
| 124 |
+
<CarouselContext.Provider
|
| 125 |
+
value={{
|
| 126 |
+
carouselRef,
|
| 127 |
+
api: api,
|
| 128 |
+
opts,
|
| 129 |
+
orientation:
|
| 130 |
+
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
| 131 |
+
scrollPrev,
|
| 132 |
+
scrollNext,
|
| 133 |
+
canScrollPrev,
|
| 134 |
+
canScrollNext,
|
| 135 |
+
}}
|
| 136 |
+
>
|
| 137 |
+
<div
|
| 138 |
+
ref={ref}
|
| 139 |
+
onKeyDownCapture={handleKeyDown}
|
| 140 |
+
className={cn("relative", className)}
|
| 141 |
+
role="region"
|
| 142 |
+
aria-roledescription="carousel"
|
| 143 |
+
{...props}
|
| 144 |
+
>
|
| 145 |
+
{children}
|
| 146 |
+
</div>
|
| 147 |
+
</CarouselContext.Provider>
|
| 148 |
+
)
|
| 149 |
+
}
|
| 150 |
+
)
|
| 151 |
+
Carousel.displayName = "Carousel"
|
| 152 |
+
|
| 153 |
+
const CarouselContent = React.forwardRef<
|
| 154 |
+
HTMLDivElement,
|
| 155 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 156 |
+
>(({ className, ...props }, ref) => {
|
| 157 |
+
const { carouselRef, orientation } = useCarousel()
|
| 158 |
+
|
| 159 |
+
return (
|
| 160 |
+
<div ref={carouselRef} className="overflow-hidden">
|
| 161 |
+
<div
|
| 162 |
+
ref={ref}
|
| 163 |
+
className={cn(
|
| 164 |
+
"flex",
|
| 165 |
+
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
| 166 |
+
className
|
| 167 |
+
)}
|
| 168 |
+
{...props}
|
| 169 |
+
/>
|
| 170 |
+
</div>
|
| 171 |
+
)
|
| 172 |
+
})
|
| 173 |
+
CarouselContent.displayName = "CarouselContent"
|
| 174 |
+
|
| 175 |
+
const CarouselItem = React.forwardRef<
|
| 176 |
+
HTMLDivElement,
|
| 177 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 178 |
+
>(({ className, ...props }, ref) => {
|
| 179 |
+
const { orientation } = useCarousel()
|
| 180 |
+
|
| 181 |
+
return (
|
| 182 |
+
<div
|
| 183 |
+
ref={ref}
|
| 184 |
+
role="group"
|
| 185 |
+
aria-roledescription="slide"
|
| 186 |
+
className={cn(
|
| 187 |
+
"min-w-0 shrink-0 grow-0 basis-full",
|
| 188 |
+
orientation === "horizontal" ? "pl-4" : "pt-4",
|
| 189 |
+
className
|
| 190 |
+
)}
|
| 191 |
+
{...props}
|
| 192 |
+
/>
|
| 193 |
+
)
|
| 194 |
+
})
|
| 195 |
+
CarouselItem.displayName = "CarouselItem"
|
| 196 |
+
|
| 197 |
+
const CarouselPrevious = React.forwardRef<
|
| 198 |
+
HTMLButtonElement,
|
| 199 |
+
React.ComponentProps<typeof Button>
|
| 200 |
+
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
| 201 |
+
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
| 202 |
+
|
| 203 |
+
return (
|
| 204 |
+
<Button
|
| 205 |
+
ref={ref}
|
| 206 |
+
variant={variant}
|
| 207 |
+
size={size}
|
| 208 |
+
className={cn(
|
| 209 |
+
"absolute h-8 w-8 rounded-full",
|
| 210 |
+
orientation === "horizontal"
|
| 211 |
+
? "-left-12 top-1/2 -translate-y-1/2"
|
| 212 |
+
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
| 213 |
+
className
|
| 214 |
+
)}
|
| 215 |
+
disabled={!canScrollPrev}
|
| 216 |
+
onClick={scrollPrev}
|
| 217 |
+
{...props}
|
| 218 |
+
>
|
| 219 |
+
<ArrowLeft className="h-4 w-4" />
|
| 220 |
+
<span className="sr-only">Previous slide</span>
|
| 221 |
+
</Button>
|
| 222 |
+
)
|
| 223 |
+
})
|
| 224 |
+
CarouselPrevious.displayName = "CarouselPrevious"
|
| 225 |
+
|
| 226 |
+
const CarouselNext = React.forwardRef<
|
| 227 |
+
HTMLButtonElement,
|
| 228 |
+
React.ComponentProps<typeof Button>
|
| 229 |
+
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
| 230 |
+
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
| 231 |
+
|
| 232 |
+
return (
|
| 233 |
+
<Button
|
| 234 |
+
ref={ref}
|
| 235 |
+
variant={variant}
|
| 236 |
+
size={size}
|
| 237 |
+
className={cn(
|
| 238 |
+
"absolute h-8 w-8 rounded-full",
|
| 239 |
+
orientation === "horizontal"
|
| 240 |
+
? "-right-12 top-1/2 -translate-y-1/2"
|
| 241 |
+
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
| 242 |
+
className
|
| 243 |
+
)}
|
| 244 |
+
disabled={!canScrollNext}
|
| 245 |
+
onClick={scrollNext}
|
| 246 |
+
{...props}
|
| 247 |
+
>
|
| 248 |
+
<ArrowRight className="h-4 w-4" />
|
| 249 |
+
<span className="sr-only">Next slide</span>
|
| 250 |
+
</Button>
|
| 251 |
+
)
|
| 252 |
+
})
|
| 253 |
+
CarouselNext.displayName = "CarouselNext"
|
| 254 |
+
|
| 255 |
+
export {
|
| 256 |
+
type CarouselApi,
|
| 257 |
+
Carousel,
|
| 258 |
+
CarouselContent,
|
| 259 |
+
CarouselItem,
|
| 260 |
+
CarouselPrevious,
|
| 261 |
+
CarouselNext,
|
| 262 |
+
}
|
eth-blueprint/web/src/components/ui/checkbox.tsx
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
| 5 |
+
import { Check } from "lucide-react"
|
| 6 |
+
|
| 7 |
+
import { cn } from "@/lib/utils"
|
| 8 |
+
|
| 9 |
+
const Checkbox = React.forwardRef<
|
| 10 |
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
| 11 |
+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
| 12 |
+
>(({ className, ...props }, ref) => (
|
| 13 |
+
<CheckboxPrimitive.Root
|
| 14 |
+
ref={ref}
|
| 15 |
+
className={cn(
|
| 16 |
+
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
| 17 |
+
className
|
| 18 |
+
)}
|
| 19 |
+
{...props}
|
| 20 |
+
>
|
| 21 |
+
<CheckboxPrimitive.Indicator
|
| 22 |
+
className={cn("flex items-center justify-center text-current")}
|
| 23 |
+
>
|
| 24 |
+
<Check className="h-4 w-4" />
|
| 25 |
+
</CheckboxPrimitive.Indicator>
|
| 26 |
+
</CheckboxPrimitive.Root>
|
| 27 |
+
))
|
| 28 |
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
| 29 |
+
|
| 30 |
+
export { Checkbox }
|
eth-blueprint/web/src/components/ui/collapsible.tsx
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
|
| 2 |
+
|
| 3 |
+
const Collapsible = CollapsiblePrimitive.Root
|
| 4 |
+
|
| 5 |
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
|
| 6 |
+
|
| 7 |
+
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
|
| 8 |
+
|
| 9 |
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
eth-blueprint/web/src/components/ui/command.tsx
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import { type DialogProps } from "@radix-ui/react-dialog"
|
| 5 |
+
import { Command as CommandPrimitive } from "cmdk"
|
| 6 |
+
import { Search } from "lucide-react"
|
| 7 |
+
|
| 8 |
+
import { cn } from "@/lib/utils"
|
| 9 |
+
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
| 10 |
+
|
| 11 |
+
const Command = React.forwardRef<
|
| 12 |
+
React.ElementRef<typeof CommandPrimitive>,
|
| 13 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
| 14 |
+
>(({ className, ...props }, ref) => (
|
| 15 |
+
<CommandPrimitive
|
| 16 |
+
ref={ref}
|
| 17 |
+
className={cn(
|
| 18 |
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
| 19 |
+
className
|
| 20 |
+
)}
|
| 21 |
+
{...props}
|
| 22 |
+
/>
|
| 23 |
+
))
|
| 24 |
+
Command.displayName = CommandPrimitive.displayName
|
| 25 |
+
|
| 26 |
+
const CommandDialog = ({ children, ...props }: DialogProps) => {
|
| 27 |
+
return (
|
| 28 |
+
<Dialog {...props}>
|
| 29 |
+
<DialogContent className="overflow-hidden p-0">
|
| 30 |
+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
| 31 |
+
{children}
|
| 32 |
+
</Command>
|
| 33 |
+
</DialogContent>
|
| 34 |
+
</Dialog>
|
| 35 |
+
)
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
const CommandInput = React.forwardRef<
|
| 39 |
+
React.ElementRef<typeof CommandPrimitive.Input>,
|
| 40 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
| 41 |
+
>(({ className, ...props }, ref) => (
|
| 42 |
+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
| 43 |
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
| 44 |
+
<CommandPrimitive.Input
|
| 45 |
+
ref={ref}
|
| 46 |
+
className={cn(
|
| 47 |
+
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
| 48 |
+
className
|
| 49 |
+
)}
|
| 50 |
+
{...props}
|
| 51 |
+
/>
|
| 52 |
+
</div>
|
| 53 |
+
))
|
| 54 |
+
|
| 55 |
+
CommandInput.displayName = CommandPrimitive.Input.displayName
|
| 56 |
+
|
| 57 |
+
const CommandList = React.forwardRef<
|
| 58 |
+
React.ElementRef<typeof CommandPrimitive.List>,
|
| 59 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
| 60 |
+
>(({ className, ...props }, ref) => (
|
| 61 |
+
<CommandPrimitive.List
|
| 62 |
+
ref={ref}
|
| 63 |
+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
| 64 |
+
{...props}
|
| 65 |
+
/>
|
| 66 |
+
))
|
| 67 |
+
|
| 68 |
+
CommandList.displayName = CommandPrimitive.List.displayName
|
| 69 |
+
|
| 70 |
+
const CommandEmpty = React.forwardRef<
|
| 71 |
+
React.ElementRef<typeof CommandPrimitive.Empty>,
|
| 72 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
| 73 |
+
>((props, ref) => (
|
| 74 |
+
<CommandPrimitive.Empty
|
| 75 |
+
ref={ref}
|
| 76 |
+
className="py-6 text-center text-sm"
|
| 77 |
+
{...props}
|
| 78 |
+
/>
|
| 79 |
+
))
|
| 80 |
+
|
| 81 |
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
| 82 |
+
|
| 83 |
+
const CommandGroup = React.forwardRef<
|
| 84 |
+
React.ElementRef<typeof CommandPrimitive.Group>,
|
| 85 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
| 86 |
+
>(({ className, ...props }, ref) => (
|
| 87 |
+
<CommandPrimitive.Group
|
| 88 |
+
ref={ref}
|
| 89 |
+
className={cn(
|
| 90 |
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
| 91 |
+
className
|
| 92 |
+
)}
|
| 93 |
+
{...props}
|
| 94 |
+
/>
|
| 95 |
+
))
|
| 96 |
+
|
| 97 |
+
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
| 98 |
+
|
| 99 |
+
const CommandSeparator = React.forwardRef<
|
| 100 |
+
React.ElementRef<typeof CommandPrimitive.Separator>,
|
| 101 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
| 102 |
+
>(({ className, ...props }, ref) => (
|
| 103 |
+
<CommandPrimitive.Separator
|
| 104 |
+
ref={ref}
|
| 105 |
+
className={cn("-mx-1 h-px bg-border", className)}
|
| 106 |
+
{...props}
|
| 107 |
+
/>
|
| 108 |
+
))
|
| 109 |
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
| 110 |
+
|
| 111 |
+
const CommandItem = React.forwardRef<
|
| 112 |
+
React.ElementRef<typeof CommandPrimitive.Item>,
|
| 113 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
| 114 |
+
>(({ className, ...props }, ref) => (
|
| 115 |
+
<CommandPrimitive.Item
|
| 116 |
+
ref={ref}
|
| 117 |
+
className={cn(
|
| 118 |
+
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
| 119 |
+
className
|
| 120 |
+
)}
|
| 121 |
+
{...props}
|
| 122 |
+
/>
|
| 123 |
+
))
|
| 124 |
+
|
| 125 |
+
CommandItem.displayName = CommandPrimitive.Item.displayName
|
| 126 |
+
|
| 127 |
+
const CommandShortcut = ({
|
| 128 |
+
className,
|
| 129 |
+
...props
|
| 130 |
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
| 131 |
+
return (
|
| 132 |
+
<span
|
| 133 |
+
className={cn(
|
| 134 |
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
| 135 |
+
className
|
| 136 |
+
)}
|
| 137 |
+
{...props}
|
| 138 |
+
/>
|
| 139 |
+
)
|
| 140 |
+
}
|
| 141 |
+
CommandShortcut.displayName = "CommandShortcut"
|
| 142 |
+
|
| 143 |
+
export {
|
| 144 |
+
Command,
|
| 145 |
+
CommandDialog,
|
| 146 |
+
CommandInput,
|
| 147 |
+
CommandList,
|
| 148 |
+
CommandEmpty,
|
| 149 |
+
CommandGroup,
|
| 150 |
+
CommandItem,
|
| 151 |
+
CommandShortcut,
|
| 152 |
+
CommandSeparator,
|
| 153 |
+
}
|
eth-blueprint/web/src/components/ui/context-menu.tsx
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
|
| 5 |
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
| 6 |
+
|
| 7 |
+
import { cn } from "@/lib/utils"
|
| 8 |
+
|
| 9 |
+
const ContextMenu = ContextMenuPrimitive.Root
|
| 10 |
+
|
| 11 |
+
const ContextMenuTrigger = ContextMenuPrimitive.Trigger
|
| 12 |
+
|
| 13 |
+
const ContextMenuGroup = ContextMenuPrimitive.Group
|
| 14 |
+
|
| 15 |
+
const ContextMenuPortal = ContextMenuPrimitive.Portal
|
| 16 |
+
|
| 17 |
+
const ContextMenuSub = ContextMenuPrimitive.Sub
|
| 18 |
+
|
| 19 |
+
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
|
| 20 |
+
|
| 21 |
+
const ContextMenuSubTrigger = React.forwardRef<
|
| 22 |
+
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
| 23 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
|
| 24 |
+
inset?: boolean
|
| 25 |
+
}
|
| 26 |
+
>(({ className, inset, children, ...props }, ref) => (
|
| 27 |
+
<ContextMenuPrimitive.SubTrigger
|
| 28 |
+
ref={ref}
|
| 29 |
+
className={cn(
|
| 30 |
+
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
| 31 |
+
inset && "pl-8",
|
| 32 |
+
className
|
| 33 |
+
)}
|
| 34 |
+
{...props}
|
| 35 |
+
>
|
| 36 |
+
{children}
|
| 37 |
+
<ChevronRight className="ml-auto h-4 w-4" />
|
| 38 |
+
</ContextMenuPrimitive.SubTrigger>
|
| 39 |
+
))
|
| 40 |
+
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
|
| 41 |
+
|
| 42 |
+
const ContextMenuSubContent = React.forwardRef<
|
| 43 |
+
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
| 44 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
| 45 |
+
>(({ className, ...props }, ref) => (
|
| 46 |
+
<ContextMenuPrimitive.SubContent
|
| 47 |
+
ref={ref}
|
| 48 |
+
className={cn(
|
| 49 |
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
|
| 50 |
+
className
|
| 51 |
+
)}
|
| 52 |
+
{...props}
|
| 53 |
+
/>
|
| 54 |
+
))
|
| 55 |
+
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
|
| 56 |
+
|
| 57 |
+
const ContextMenuContent = React.forwardRef<
|
| 58 |
+
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
| 59 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
|
| 60 |
+
>(({ className, ...props }, ref) => (
|
| 61 |
+
<ContextMenuPrimitive.Portal>
|
| 62 |
+
<ContextMenuPrimitive.Content
|
| 63 |
+
ref={ref}
|
| 64 |
+
className={cn(
|
| 65 |
+
"z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
|
| 66 |
+
className
|
| 67 |
+
)}
|
| 68 |
+
{...props}
|
| 69 |
+
/>
|
| 70 |
+
</ContextMenuPrimitive.Portal>
|
| 71 |
+
))
|
| 72 |
+
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
|
| 73 |
+
|
| 74 |
+
const ContextMenuItem = React.forwardRef<
|
| 75 |
+
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
| 76 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
|
| 77 |
+
inset?: boolean
|
| 78 |
+
}
|
| 79 |
+
>(({ className, inset, ...props }, ref) => (
|
| 80 |
+
<ContextMenuPrimitive.Item
|
| 81 |
+
ref={ref}
|
| 82 |
+
className={cn(
|
| 83 |
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 84 |
+
inset && "pl-8",
|
| 85 |
+
className
|
| 86 |
+
)}
|
| 87 |
+
{...props}
|
| 88 |
+
/>
|
| 89 |
+
))
|
| 90 |
+
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
|
| 91 |
+
|
| 92 |
+
const ContextMenuCheckboxItem = React.forwardRef<
|
| 93 |
+
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
| 94 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
|
| 95 |
+
>(({ className, children, checked, ...props }, ref) => (
|
| 96 |
+
<ContextMenuPrimitive.CheckboxItem
|
| 97 |
+
ref={ref}
|
| 98 |
+
className={cn(
|
| 99 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 100 |
+
className
|
| 101 |
+
)}
|
| 102 |
+
checked={checked}
|
| 103 |
+
{...props}
|
| 104 |
+
>
|
| 105 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 106 |
+
<ContextMenuPrimitive.ItemIndicator>
|
| 107 |
+
<Check className="h-4 w-4" />
|
| 108 |
+
</ContextMenuPrimitive.ItemIndicator>
|
| 109 |
+
</span>
|
| 110 |
+
{children}
|
| 111 |
+
</ContextMenuPrimitive.CheckboxItem>
|
| 112 |
+
))
|
| 113 |
+
ContextMenuCheckboxItem.displayName =
|
| 114 |
+
ContextMenuPrimitive.CheckboxItem.displayName
|
| 115 |
+
|
| 116 |
+
const ContextMenuRadioItem = React.forwardRef<
|
| 117 |
+
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
| 118 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
|
| 119 |
+
>(({ className, children, ...props }, ref) => (
|
| 120 |
+
<ContextMenuPrimitive.RadioItem
|
| 121 |
+
ref={ref}
|
| 122 |
+
className={cn(
|
| 123 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 124 |
+
className
|
| 125 |
+
)}
|
| 126 |
+
{...props}
|
| 127 |
+
>
|
| 128 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 129 |
+
<ContextMenuPrimitive.ItemIndicator>
|
| 130 |
+
<Circle className="h-4 w-4 fill-current" />
|
| 131 |
+
</ContextMenuPrimitive.ItemIndicator>
|
| 132 |
+
</span>
|
| 133 |
+
{children}
|
| 134 |
+
</ContextMenuPrimitive.RadioItem>
|
| 135 |
+
))
|
| 136 |
+
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
|
| 137 |
+
|
| 138 |
+
const ContextMenuLabel = React.forwardRef<
|
| 139 |
+
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
| 140 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
| 141 |
+
inset?: boolean
|
| 142 |
+
}
|
| 143 |
+
>(({ className, inset, ...props }, ref) => (
|
| 144 |
+
<ContextMenuPrimitive.Label
|
| 145 |
+
ref={ref}
|
| 146 |
+
className={cn(
|
| 147 |
+
"px-2 py-1.5 text-sm font-semibold text-foreground",
|
| 148 |
+
inset && "pl-8",
|
| 149 |
+
className
|
| 150 |
+
)}
|
| 151 |
+
{...props}
|
| 152 |
+
/>
|
| 153 |
+
))
|
| 154 |
+
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
|
| 155 |
+
|
| 156 |
+
const ContextMenuSeparator = React.forwardRef<
|
| 157 |
+
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
| 158 |
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
| 159 |
+
>(({ className, ...props }, ref) => (
|
| 160 |
+
<ContextMenuPrimitive.Separator
|
| 161 |
+
ref={ref}
|
| 162 |
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
| 163 |
+
{...props}
|
| 164 |
+
/>
|
| 165 |
+
))
|
| 166 |
+
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
|
| 167 |
+
|
| 168 |
+
const ContextMenuShortcut = ({
|
| 169 |
+
className,
|
| 170 |
+
...props
|
| 171 |
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
| 172 |
+
return (
|
| 173 |
+
<span
|
| 174 |
+
className={cn(
|
| 175 |
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
| 176 |
+
className
|
| 177 |
+
)}
|
| 178 |
+
{...props}
|
| 179 |
+
/>
|
| 180 |
+
)
|
| 181 |
+
}
|
| 182 |
+
ContextMenuShortcut.displayName = "ContextMenuShortcut"
|
| 183 |
+
|
| 184 |
+
export {
|
| 185 |
+
ContextMenu,
|
| 186 |
+
ContextMenuTrigger,
|
| 187 |
+
ContextMenuContent,
|
| 188 |
+
ContextMenuItem,
|
| 189 |
+
ContextMenuCheckboxItem,
|
| 190 |
+
ContextMenuRadioItem,
|
| 191 |
+
ContextMenuLabel,
|
| 192 |
+
ContextMenuSeparator,
|
| 193 |
+
ContextMenuShortcut,
|
| 194 |
+
ContextMenuGroup,
|
| 195 |
+
ContextMenuPortal,
|
| 196 |
+
ContextMenuSub,
|
| 197 |
+
ContextMenuSubContent,
|
| 198 |
+
ContextMenuSubTrigger,
|
| 199 |
+
ContextMenuRadioGroup,
|
| 200 |
+
}
|
eth-blueprint/web/src/components/ui/dialog.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
| 3 |
+
import { X } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const Dialog = DialogPrimitive.Root
|
| 8 |
+
|
| 9 |
+
const DialogTrigger = DialogPrimitive.Trigger
|
| 10 |
+
|
| 11 |
+
const DialogPortal = DialogPrimitive.Portal
|
| 12 |
+
|
| 13 |
+
const DialogClose = DialogPrimitive.Close
|
| 14 |
+
|
| 15 |
+
const DialogOverlay = React.forwardRef<
|
| 16 |
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
| 17 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
| 18 |
+
>(({ className, ...props }, ref) => (
|
| 19 |
+
<DialogPrimitive.Overlay
|
| 20 |
+
ref={ref}
|
| 21 |
+
className={cn(
|
| 22 |
+
"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",
|
| 23 |
+
className
|
| 24 |
+
)}
|
| 25 |
+
{...props}
|
| 26 |
+
/>
|
| 27 |
+
))
|
| 28 |
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
| 29 |
+
|
| 30 |
+
const DialogContent = React.forwardRef<
|
| 31 |
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
| 32 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
| 33 |
+
>(({ className, children, ...props }, ref) => (
|
| 34 |
+
<DialogPortal>
|
| 35 |
+
<DialogOverlay />
|
| 36 |
+
<DialogPrimitive.Content
|
| 37 |
+
ref={ref}
|
| 38 |
+
className={cn(
|
| 39 |
+
"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",
|
| 40 |
+
className
|
| 41 |
+
)}
|
| 42 |
+
{...props}
|
| 43 |
+
>
|
| 44 |
+
{children}
|
| 45 |
+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
| 46 |
+
<X className="h-4 w-4" />
|
| 47 |
+
<span className="sr-only">Close</span>
|
| 48 |
+
</DialogPrimitive.Close>
|
| 49 |
+
</DialogPrimitive.Content>
|
| 50 |
+
</DialogPortal>
|
| 51 |
+
))
|
| 52 |
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
| 53 |
+
|
| 54 |
+
const DialogHeader = ({
|
| 55 |
+
className,
|
| 56 |
+
...props
|
| 57 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 58 |
+
<div
|
| 59 |
+
className={cn(
|
| 60 |
+
"flex flex-col space-y-1.5 text-center sm:text-left",
|
| 61 |
+
className
|
| 62 |
+
)}
|
| 63 |
+
{...props}
|
| 64 |
+
/>
|
| 65 |
+
)
|
| 66 |
+
DialogHeader.displayName = "DialogHeader"
|
| 67 |
+
|
| 68 |
+
const DialogFooter = ({
|
| 69 |
+
className,
|
| 70 |
+
...props
|
| 71 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 72 |
+
<div
|
| 73 |
+
className={cn(
|
| 74 |
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
| 75 |
+
className
|
| 76 |
+
)}
|
| 77 |
+
{...props}
|
| 78 |
+
/>
|
| 79 |
+
)
|
| 80 |
+
DialogFooter.displayName = "DialogFooter"
|
| 81 |
+
|
| 82 |
+
const DialogTitle = React.forwardRef<
|
| 83 |
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
| 84 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
| 85 |
+
>(({ className, ...props }, ref) => (
|
| 86 |
+
<DialogPrimitive.Title
|
| 87 |
+
ref={ref}
|
| 88 |
+
className={cn(
|
| 89 |
+
"text-lg font-semibold leading-none tracking-tight",
|
| 90 |
+
className
|
| 91 |
+
)}
|
| 92 |
+
{...props}
|
| 93 |
+
/>
|
| 94 |
+
))
|
| 95 |
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
| 96 |
+
|
| 97 |
+
const DialogDescription = React.forwardRef<
|
| 98 |
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
| 99 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
| 100 |
+
>(({ className, ...props }, ref) => (
|
| 101 |
+
<DialogPrimitive.Description
|
| 102 |
+
ref={ref}
|
| 103 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 104 |
+
{...props}
|
| 105 |
+
/>
|
| 106 |
+
))
|
| 107 |
+
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
| 108 |
+
|
| 109 |
+
export {
|
| 110 |
+
Dialog,
|
| 111 |
+
DialogPortal,
|
| 112 |
+
DialogOverlay,
|
| 113 |
+
DialogTrigger,
|
| 114 |
+
DialogClose,
|
| 115 |
+
DialogContent,
|
| 116 |
+
DialogHeader,
|
| 117 |
+
DialogFooter,
|
| 118 |
+
DialogTitle,
|
| 119 |
+
DialogDescription,
|
| 120 |
+
}
|
eth-blueprint/web/src/components/ui/drawer.tsx
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import { Drawer as DrawerPrimitive } from "vaul"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const Drawer = ({
|
| 9 |
+
shouldScaleBackground = true,
|
| 10 |
+
...props
|
| 11 |
+
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
|
| 12 |
+
<DrawerPrimitive.Root
|
| 13 |
+
shouldScaleBackground={shouldScaleBackground}
|
| 14 |
+
{...props}
|
| 15 |
+
/>
|
| 16 |
+
)
|
| 17 |
+
Drawer.displayName = "Drawer"
|
| 18 |
+
|
| 19 |
+
const DrawerTrigger = DrawerPrimitive.Trigger
|
| 20 |
+
|
| 21 |
+
const DrawerPortal = DrawerPrimitive.Portal
|
| 22 |
+
|
| 23 |
+
const DrawerClose = DrawerPrimitive.Close
|
| 24 |
+
|
| 25 |
+
const DrawerOverlay = React.forwardRef<
|
| 26 |
+
React.ElementRef<typeof DrawerPrimitive.Overlay>,
|
| 27 |
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
|
| 28 |
+
>(({ className, ...props }, ref) => (
|
| 29 |
+
<DrawerPrimitive.Overlay
|
| 30 |
+
ref={ref}
|
| 31 |
+
className={cn("fixed inset-0 z-50 bg-black/80", className)}
|
| 32 |
+
{...props}
|
| 33 |
+
/>
|
| 34 |
+
))
|
| 35 |
+
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
|
| 36 |
+
|
| 37 |
+
const DrawerContent = React.forwardRef<
|
| 38 |
+
React.ElementRef<typeof DrawerPrimitive.Content>,
|
| 39 |
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
|
| 40 |
+
>(({ className, children, ...props }, ref) => (
|
| 41 |
+
<DrawerPortal>
|
| 42 |
+
<DrawerOverlay />
|
| 43 |
+
<DrawerPrimitive.Content
|
| 44 |
+
ref={ref}
|
| 45 |
+
className={cn(
|
| 46 |
+
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
| 47 |
+
className
|
| 48 |
+
)}
|
| 49 |
+
{...props}
|
| 50 |
+
>
|
| 51 |
+
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
|
| 52 |
+
{children}
|
| 53 |
+
</DrawerPrimitive.Content>
|
| 54 |
+
</DrawerPortal>
|
| 55 |
+
))
|
| 56 |
+
DrawerContent.displayName = "DrawerContent"
|
| 57 |
+
|
| 58 |
+
const DrawerHeader = ({
|
| 59 |
+
className,
|
| 60 |
+
...props
|
| 61 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 62 |
+
<div
|
| 63 |
+
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
|
| 64 |
+
{...props}
|
| 65 |
+
/>
|
| 66 |
+
)
|
| 67 |
+
DrawerHeader.displayName = "DrawerHeader"
|
| 68 |
+
|
| 69 |
+
const DrawerFooter = ({
|
| 70 |
+
className,
|
| 71 |
+
...props
|
| 72 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 73 |
+
<div
|
| 74 |
+
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
| 75 |
+
{...props}
|
| 76 |
+
/>
|
| 77 |
+
)
|
| 78 |
+
DrawerFooter.displayName = "DrawerFooter"
|
| 79 |
+
|
| 80 |
+
const DrawerTitle = React.forwardRef<
|
| 81 |
+
React.ElementRef<typeof DrawerPrimitive.Title>,
|
| 82 |
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
|
| 83 |
+
>(({ className, ...props }, ref) => (
|
| 84 |
+
<DrawerPrimitive.Title
|
| 85 |
+
ref={ref}
|
| 86 |
+
className={cn(
|
| 87 |
+
"text-lg font-semibold leading-none tracking-tight",
|
| 88 |
+
className
|
| 89 |
+
)}
|
| 90 |
+
{...props}
|
| 91 |
+
/>
|
| 92 |
+
))
|
| 93 |
+
DrawerTitle.displayName = DrawerPrimitive.Title.displayName
|
| 94 |
+
|
| 95 |
+
const DrawerDescription = React.forwardRef<
|
| 96 |
+
React.ElementRef<typeof DrawerPrimitive.Description>,
|
| 97 |
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
|
| 98 |
+
>(({ className, ...props }, ref) => (
|
| 99 |
+
<DrawerPrimitive.Description
|
| 100 |
+
ref={ref}
|
| 101 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 102 |
+
{...props}
|
| 103 |
+
/>
|
| 104 |
+
))
|
| 105 |
+
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
|
| 106 |
+
|
| 107 |
+
export {
|
| 108 |
+
Drawer,
|
| 109 |
+
DrawerPortal,
|
| 110 |
+
DrawerOverlay,
|
| 111 |
+
DrawerTrigger,
|
| 112 |
+
DrawerClose,
|
| 113 |
+
DrawerContent,
|
| 114 |
+
DrawerHeader,
|
| 115 |
+
DrawerFooter,
|
| 116 |
+
DrawerTitle,
|
| 117 |
+
DrawerDescription,
|
| 118 |
+
}
|
eth-blueprint/web/src/components/ui/dropdown-menu.tsx
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
| 5 |
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
| 6 |
+
|
| 7 |
+
import { cn } from "@/lib/utils"
|
| 8 |
+
|
| 9 |
+
const DropdownMenu = DropdownMenuPrimitive.Root
|
| 10 |
+
|
| 11 |
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
| 12 |
+
|
| 13 |
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
| 14 |
+
|
| 15 |
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
| 16 |
+
|
| 17 |
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
| 18 |
+
|
| 19 |
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
| 20 |
+
|
| 21 |
+
const DropdownMenuSubTrigger = React.forwardRef<
|
| 22 |
+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
| 23 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
| 24 |
+
inset?: boolean
|
| 25 |
+
}
|
| 26 |
+
>(({ className, inset, children, ...props }, ref) => (
|
| 27 |
+
<DropdownMenuPrimitive.SubTrigger
|
| 28 |
+
ref={ref}
|
| 29 |
+
className={cn(
|
| 30 |
+
"flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
| 31 |
+
inset && "pl-8",
|
| 32 |
+
className
|
| 33 |
+
)}
|
| 34 |
+
{...props}
|
| 35 |
+
>
|
| 36 |
+
{children}
|
| 37 |
+
<ChevronRight className="ml-auto" />
|
| 38 |
+
</DropdownMenuPrimitive.SubTrigger>
|
| 39 |
+
))
|
| 40 |
+
DropdownMenuSubTrigger.displayName =
|
| 41 |
+
DropdownMenuPrimitive.SubTrigger.displayName
|
| 42 |
+
|
| 43 |
+
const DropdownMenuSubContent = React.forwardRef<
|
| 44 |
+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
| 45 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
| 46 |
+
>(({ className, ...props }, ref) => (
|
| 47 |
+
<DropdownMenuPrimitive.SubContent
|
| 48 |
+
ref={ref}
|
| 49 |
+
className={cn(
|
| 50 |
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
| 51 |
+
className
|
| 52 |
+
)}
|
| 53 |
+
{...props}
|
| 54 |
+
/>
|
| 55 |
+
))
|
| 56 |
+
DropdownMenuSubContent.displayName =
|
| 57 |
+
DropdownMenuPrimitive.SubContent.displayName
|
| 58 |
+
|
| 59 |
+
const DropdownMenuContent = React.forwardRef<
|
| 60 |
+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
| 61 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
| 62 |
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
| 63 |
+
<DropdownMenuPrimitive.Portal>
|
| 64 |
+
<DropdownMenuPrimitive.Content
|
| 65 |
+
ref={ref}
|
| 66 |
+
sideOffset={sideOffset}
|
| 67 |
+
className={cn(
|
| 68 |
+
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
| 69 |
+
"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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
|
| 70 |
+
className
|
| 71 |
+
)}
|
| 72 |
+
{...props}
|
| 73 |
+
/>
|
| 74 |
+
</DropdownMenuPrimitive.Portal>
|
| 75 |
+
))
|
| 76 |
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
| 77 |
+
|
| 78 |
+
const DropdownMenuItem = React.forwardRef<
|
| 79 |
+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
| 80 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
| 81 |
+
inset?: boolean
|
| 82 |
+
}
|
| 83 |
+
>(({ className, inset, ...props }, ref) => (
|
| 84 |
+
<DropdownMenuPrimitive.Item
|
| 85 |
+
ref={ref}
|
| 86 |
+
className={cn(
|
| 87 |
+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
| 88 |
+
inset && "pl-8",
|
| 89 |
+
className
|
| 90 |
+
)}
|
| 91 |
+
{...props}
|
| 92 |
+
/>
|
| 93 |
+
))
|
| 94 |
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
| 95 |
+
|
| 96 |
+
const DropdownMenuCheckboxItem = React.forwardRef<
|
| 97 |
+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
| 98 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
| 99 |
+
>(({ className, children, checked, ...props }, ref) => (
|
| 100 |
+
<DropdownMenuPrimitive.CheckboxItem
|
| 101 |
+
ref={ref}
|
| 102 |
+
className={cn(
|
| 103 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 104 |
+
className
|
| 105 |
+
)}
|
| 106 |
+
checked={checked}
|
| 107 |
+
{...props}
|
| 108 |
+
>
|
| 109 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 110 |
+
<DropdownMenuPrimitive.ItemIndicator>
|
| 111 |
+
<Check className="h-4 w-4" />
|
| 112 |
+
</DropdownMenuPrimitive.ItemIndicator>
|
| 113 |
+
</span>
|
| 114 |
+
{children}
|
| 115 |
+
</DropdownMenuPrimitive.CheckboxItem>
|
| 116 |
+
))
|
| 117 |
+
DropdownMenuCheckboxItem.displayName =
|
| 118 |
+
DropdownMenuPrimitive.CheckboxItem.displayName
|
| 119 |
+
|
| 120 |
+
const DropdownMenuRadioItem = React.forwardRef<
|
| 121 |
+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
| 122 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
| 123 |
+
>(({ className, children, ...props }, ref) => (
|
| 124 |
+
<DropdownMenuPrimitive.RadioItem
|
| 125 |
+
ref={ref}
|
| 126 |
+
className={cn(
|
| 127 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 128 |
+
className
|
| 129 |
+
)}
|
| 130 |
+
{...props}
|
| 131 |
+
>
|
| 132 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 133 |
+
<DropdownMenuPrimitive.ItemIndicator>
|
| 134 |
+
<Circle className="h-2 w-2 fill-current" />
|
| 135 |
+
</DropdownMenuPrimitive.ItemIndicator>
|
| 136 |
+
</span>
|
| 137 |
+
{children}
|
| 138 |
+
</DropdownMenuPrimitive.RadioItem>
|
| 139 |
+
))
|
| 140 |
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
| 141 |
+
|
| 142 |
+
const DropdownMenuLabel = React.forwardRef<
|
| 143 |
+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
| 144 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
| 145 |
+
inset?: boolean
|
| 146 |
+
}
|
| 147 |
+
>(({ className, inset, ...props }, ref) => (
|
| 148 |
+
<DropdownMenuPrimitive.Label
|
| 149 |
+
ref={ref}
|
| 150 |
+
className={cn(
|
| 151 |
+
"px-2 py-1.5 text-sm font-semibold",
|
| 152 |
+
inset && "pl-8",
|
| 153 |
+
className
|
| 154 |
+
)}
|
| 155 |
+
{...props}
|
| 156 |
+
/>
|
| 157 |
+
))
|
| 158 |
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
| 159 |
+
|
| 160 |
+
const DropdownMenuSeparator = React.forwardRef<
|
| 161 |
+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
| 162 |
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
| 163 |
+
>(({ className, ...props }, ref) => (
|
| 164 |
+
<DropdownMenuPrimitive.Separator
|
| 165 |
+
ref={ref}
|
| 166 |
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
| 167 |
+
{...props}
|
| 168 |
+
/>
|
| 169 |
+
))
|
| 170 |
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
| 171 |
+
|
| 172 |
+
const DropdownMenuShortcut = ({
|
| 173 |
+
className,
|
| 174 |
+
...props
|
| 175 |
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
| 176 |
+
return (
|
| 177 |
+
<span
|
| 178 |
+
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
| 179 |
+
{...props}
|
| 180 |
+
/>
|
| 181 |
+
)
|
| 182 |
+
}
|
| 183 |
+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
| 184 |
+
|
| 185 |
+
export {
|
| 186 |
+
DropdownMenu,
|
| 187 |
+
DropdownMenuTrigger,
|
| 188 |
+
DropdownMenuContent,
|
| 189 |
+
DropdownMenuItem,
|
| 190 |
+
DropdownMenuCheckboxItem,
|
| 191 |
+
DropdownMenuRadioItem,
|
| 192 |
+
DropdownMenuLabel,
|
| 193 |
+
DropdownMenuSeparator,
|
| 194 |
+
DropdownMenuShortcut,
|
| 195 |
+
DropdownMenuGroup,
|
| 196 |
+
DropdownMenuPortal,
|
| 197 |
+
DropdownMenuSub,
|
| 198 |
+
DropdownMenuSubContent,
|
| 199 |
+
DropdownMenuSubTrigger,
|
| 200 |
+
DropdownMenuRadioGroup,
|
| 201 |
+
}
|
eth-blueprint/web/src/components/ui/form.tsx
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
| 3 |
+
import { Slot } from "@radix-ui/react-slot"
|
| 4 |
+
import {
|
| 5 |
+
Controller,
|
| 6 |
+
FormProvider,
|
| 7 |
+
useFormContext,
|
| 8 |
+
type ControllerProps,
|
| 9 |
+
type FieldPath,
|
| 10 |
+
type FieldValues,
|
| 11 |
+
} from "react-hook-form"
|
| 12 |
+
|
| 13 |
+
import { cn } from "@/lib/utils"
|
| 14 |
+
import { Label } from "@/components/ui/label"
|
| 15 |
+
|
| 16 |
+
const Form = FormProvider
|
| 17 |
+
|
| 18 |
+
type FormFieldContextValue<
|
| 19 |
+
TFieldValues extends FieldValues = FieldValues,
|
| 20 |
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
| 21 |
+
> = {
|
| 22 |
+
name: TName
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
const FormFieldContext = React.createContext<FormFieldContextValue>(
|
| 26 |
+
{} as FormFieldContextValue
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
const FormField = <
|
| 30 |
+
TFieldValues extends FieldValues = FieldValues,
|
| 31 |
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
| 32 |
+
>({
|
| 33 |
+
...props
|
| 34 |
+
}: ControllerProps<TFieldValues, TName>) => {
|
| 35 |
+
return (
|
| 36 |
+
<FormFieldContext.Provider value={{ name: props.name }}>
|
| 37 |
+
<Controller {...props} />
|
| 38 |
+
</FormFieldContext.Provider>
|
| 39 |
+
)
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
const useFormField = () => {
|
| 43 |
+
const fieldContext = React.useContext(FormFieldContext)
|
| 44 |
+
const itemContext = React.useContext(FormItemContext)
|
| 45 |
+
const { getFieldState, formState } = useFormContext()
|
| 46 |
+
|
| 47 |
+
const fieldState = getFieldState(fieldContext.name, formState)
|
| 48 |
+
|
| 49 |
+
if (!fieldContext) {
|
| 50 |
+
throw new Error("useFormField should be used within <FormField>")
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
const { id } = itemContext
|
| 54 |
+
|
| 55 |
+
return {
|
| 56 |
+
id,
|
| 57 |
+
name: fieldContext.name,
|
| 58 |
+
formItemId: `${id}-form-item`,
|
| 59 |
+
formDescriptionId: `${id}-form-item-description`,
|
| 60 |
+
formMessageId: `${id}-form-item-message`,
|
| 61 |
+
...fieldState,
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
type FormItemContextValue = {
|
| 66 |
+
id: string
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
const FormItemContext = React.createContext<FormItemContextValue>(
|
| 70 |
+
{} as FormItemContextValue
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
const FormItem = React.forwardRef<
|
| 74 |
+
HTMLDivElement,
|
| 75 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 76 |
+
>(({ className, ...props }, ref) => {
|
| 77 |
+
const id = React.useId()
|
| 78 |
+
|
| 79 |
+
return (
|
| 80 |
+
<FormItemContext.Provider value={{ id }}>
|
| 81 |
+
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
| 82 |
+
</FormItemContext.Provider>
|
| 83 |
+
)
|
| 84 |
+
})
|
| 85 |
+
FormItem.displayName = "FormItem"
|
| 86 |
+
|
| 87 |
+
const FormLabel = React.forwardRef<
|
| 88 |
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
| 89 |
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
| 90 |
+
>(({ className, ...props }, ref) => {
|
| 91 |
+
const { error, formItemId } = useFormField()
|
| 92 |
+
|
| 93 |
+
return (
|
| 94 |
+
<Label
|
| 95 |
+
ref={ref}
|
| 96 |
+
className={cn(error && "text-destructive", className)}
|
| 97 |
+
htmlFor={formItemId}
|
| 98 |
+
{...props}
|
| 99 |
+
/>
|
| 100 |
+
)
|
| 101 |
+
})
|
| 102 |
+
FormLabel.displayName = "FormLabel"
|
| 103 |
+
|
| 104 |
+
const FormControl = React.forwardRef<
|
| 105 |
+
React.ElementRef<typeof Slot>,
|
| 106 |
+
React.ComponentPropsWithoutRef<typeof Slot>
|
| 107 |
+
>(({ ...props }, ref) => {
|
| 108 |
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
| 109 |
+
|
| 110 |
+
return (
|
| 111 |
+
<Slot
|
| 112 |
+
ref={ref}
|
| 113 |
+
id={formItemId}
|
| 114 |
+
aria-describedby={
|
| 115 |
+
!error
|
| 116 |
+
? `${formDescriptionId}`
|
| 117 |
+
: `${formDescriptionId} ${formMessageId}`
|
| 118 |
+
}
|
| 119 |
+
aria-invalid={!!error}
|
| 120 |
+
{...props}
|
| 121 |
+
/>
|
| 122 |
+
)
|
| 123 |
+
})
|
| 124 |
+
FormControl.displayName = "FormControl"
|
| 125 |
+
|
| 126 |
+
const FormDescription = React.forwardRef<
|
| 127 |
+
HTMLParagraphElement,
|
| 128 |
+
React.HTMLAttributes<HTMLParagraphElement>
|
| 129 |
+
>(({ className, ...props }, ref) => {
|
| 130 |
+
const { formDescriptionId } = useFormField()
|
| 131 |
+
|
| 132 |
+
return (
|
| 133 |
+
<p
|
| 134 |
+
ref={ref}
|
| 135 |
+
id={formDescriptionId}
|
| 136 |
+
className={cn("text-[0.8rem] text-muted-foreground", className)}
|
| 137 |
+
{...props}
|
| 138 |
+
/>
|
| 139 |
+
)
|
| 140 |
+
})
|
| 141 |
+
FormDescription.displayName = "FormDescription"
|
| 142 |
+
|
| 143 |
+
const FormMessage = React.forwardRef<
|
| 144 |
+
HTMLParagraphElement,
|
| 145 |
+
React.HTMLAttributes<HTMLParagraphElement>
|
| 146 |
+
>(({ className, children, ...props }, ref) => {
|
| 147 |
+
const { error, formMessageId } = useFormField()
|
| 148 |
+
const body = error ? String(error?.message ?? "") : children
|
| 149 |
+
|
| 150 |
+
if (!body) {
|
| 151 |
+
return null
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
return (
|
| 155 |
+
<p
|
| 156 |
+
ref={ref}
|
| 157 |
+
id={formMessageId}
|
| 158 |
+
className={cn("text-[0.8rem] font-medium text-destructive", className)}
|
| 159 |
+
{...props}
|
| 160 |
+
>
|
| 161 |
+
{body}
|
| 162 |
+
</p>
|
| 163 |
+
)
|
| 164 |
+
})
|
| 165 |
+
FormMessage.displayName = "FormMessage"
|
| 166 |
+
|
| 167 |
+
export {
|
| 168 |
+
useFormField,
|
| 169 |
+
Form,
|
| 170 |
+
FormItem,
|
| 171 |
+
FormLabel,
|
| 172 |
+
FormControl,
|
| 173 |
+
FormDescription,
|
| 174 |
+
FormMessage,
|
| 175 |
+
FormField,
|
| 176 |
+
}
|
eth-blueprint/web/src/components/ui/hover-card.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const HoverCard = HoverCardPrimitive.Root
|
| 9 |
+
|
| 10 |
+
const HoverCardTrigger = HoverCardPrimitive.Trigger
|
| 11 |
+
|
| 12 |
+
const HoverCardContent = React.forwardRef<
|
| 13 |
+
React.ElementRef<typeof HoverCardPrimitive.Content>,
|
| 14 |
+
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
|
| 15 |
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
| 16 |
+
<HoverCardPrimitive.Content
|
| 17 |
+
ref={ref}
|
| 18 |
+
align={align}
|
| 19 |
+
sideOffset={sideOffset}
|
| 20 |
+
className={cn(
|
| 21 |
+
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
|
| 22 |
+
className
|
| 23 |
+
)}
|
| 24 |
+
{...props}
|
| 25 |
+
/>
|
| 26 |
+
))
|
| 27 |
+
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
|
| 28 |
+
|
| 29 |
+
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
eth-blueprint/web/src/components/ui/input.tsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
|
| 3 |
+
import { cn } from "@/lib/utils"
|
| 4 |
+
|
| 5 |
+
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
| 6 |
+
({ className, type, ...props }, ref) => {
|
| 7 |
+
return (
|
| 8 |
+
<input
|
| 9 |
+
type={type}
|
| 10 |
+
className={cn(
|
| 11 |
+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-[color,box-shadow] file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:border-[var(--fg-base)] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
| 12 |
+
className
|
| 13 |
+
)}
|
| 14 |
+
ref={ref}
|
| 15 |
+
{...props}
|
| 16 |
+
/>
|
| 17 |
+
)
|
| 18 |
+
}
|
| 19 |
+
)
|
| 20 |
+
Input.displayName = "Input"
|
| 21 |
+
|
| 22 |
+
export { Input }
|
eth-blueprint/web/src/components/ui/label.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
| 5 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 6 |
+
|
| 7 |
+
import { cn } from "@/lib/utils"
|
| 8 |
+
|
| 9 |
+
const labelVariants = cva(
|
| 10 |
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
const Label = React.forwardRef<
|
| 14 |
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
| 15 |
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
| 16 |
+
VariantProps<typeof labelVariants>
|
| 17 |
+
>(({ className, ...props }, ref) => (
|
| 18 |
+
<LabelPrimitive.Root
|
| 19 |
+
ref={ref}
|
| 20 |
+
className={cn(labelVariants(), className)}
|
| 21 |
+
{...props}
|
| 22 |
+
/>
|
| 23 |
+
))
|
| 24 |
+
Label.displayName = LabelPrimitive.Root.displayName
|
| 25 |
+
|
| 26 |
+
export { Label }
|
eth-blueprint/web/src/components/ui/menubar.tsx
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as MenubarPrimitive from "@radix-ui/react-menubar"
|
| 5 |
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
| 6 |
+
|
| 7 |
+
import { cn } from "@/lib/utils"
|
| 8 |
+
|
| 9 |
+
function MenubarMenu({
|
| 10 |
+
...props
|
| 11 |
+
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
| 12 |
+
return <MenubarPrimitive.Menu {...props} />
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
function MenubarGroup({
|
| 16 |
+
...props
|
| 17 |
+
}: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
| 18 |
+
return <MenubarPrimitive.Group {...props} />
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
function MenubarPortal({
|
| 22 |
+
...props
|
| 23 |
+
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
| 24 |
+
return <MenubarPrimitive.Portal {...props} />
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
function MenubarRadioGroup({
|
| 28 |
+
...props
|
| 29 |
+
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
| 30 |
+
return <MenubarPrimitive.RadioGroup {...props} />
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
function MenubarSub({
|
| 34 |
+
...props
|
| 35 |
+
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
| 36 |
+
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
const Menubar = React.forwardRef<
|
| 40 |
+
React.ElementRef<typeof MenubarPrimitive.Root>,
|
| 41 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
|
| 42 |
+
>(({ className, ...props }, ref) => (
|
| 43 |
+
<MenubarPrimitive.Root
|
| 44 |
+
ref={ref}
|
| 45 |
+
className={cn(
|
| 46 |
+
"flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm",
|
| 47 |
+
className
|
| 48 |
+
)}
|
| 49 |
+
{...props}
|
| 50 |
+
/>
|
| 51 |
+
))
|
| 52 |
+
Menubar.displayName = MenubarPrimitive.Root.displayName
|
| 53 |
+
|
| 54 |
+
const MenubarTrigger = React.forwardRef<
|
| 55 |
+
React.ElementRef<typeof MenubarPrimitive.Trigger>,
|
| 56 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
|
| 57 |
+
>(({ className, ...props }, ref) => (
|
| 58 |
+
<MenubarPrimitive.Trigger
|
| 59 |
+
ref={ref}
|
| 60 |
+
className={cn(
|
| 61 |
+
"flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
| 62 |
+
className
|
| 63 |
+
)}
|
| 64 |
+
{...props}
|
| 65 |
+
/>
|
| 66 |
+
))
|
| 67 |
+
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
|
| 68 |
+
|
| 69 |
+
const MenubarSubTrigger = React.forwardRef<
|
| 70 |
+
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
|
| 71 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
|
| 72 |
+
inset?: boolean
|
| 73 |
+
}
|
| 74 |
+
>(({ className, inset, children, ...props }, ref) => (
|
| 75 |
+
<MenubarPrimitive.SubTrigger
|
| 76 |
+
ref={ref}
|
| 77 |
+
className={cn(
|
| 78 |
+
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
| 79 |
+
inset && "pl-8",
|
| 80 |
+
className
|
| 81 |
+
)}
|
| 82 |
+
{...props}
|
| 83 |
+
>
|
| 84 |
+
{children}
|
| 85 |
+
<ChevronRight className="ml-auto h-4 w-4" />
|
| 86 |
+
</MenubarPrimitive.SubTrigger>
|
| 87 |
+
))
|
| 88 |
+
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
|
| 89 |
+
|
| 90 |
+
const MenubarSubContent = React.forwardRef<
|
| 91 |
+
React.ElementRef<typeof MenubarPrimitive.SubContent>,
|
| 92 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
|
| 93 |
+
>(({ className, ...props }, ref) => (
|
| 94 |
+
<MenubarPrimitive.SubContent
|
| 95 |
+
ref={ref}
|
| 96 |
+
className={cn(
|
| 97 |
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
|
| 98 |
+
className
|
| 99 |
+
)}
|
| 100 |
+
{...props}
|
| 101 |
+
/>
|
| 102 |
+
))
|
| 103 |
+
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
|
| 104 |
+
|
| 105 |
+
const MenubarContent = React.forwardRef<
|
| 106 |
+
React.ElementRef<typeof MenubarPrimitive.Content>,
|
| 107 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
|
| 108 |
+
>(
|
| 109 |
+
(
|
| 110 |
+
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
|
| 111 |
+
ref
|
| 112 |
+
) => (
|
| 113 |
+
<MenubarPrimitive.Portal>
|
| 114 |
+
<MenubarPrimitive.Content
|
| 115 |
+
ref={ref}
|
| 116 |
+
align={align}
|
| 117 |
+
alignOffset={alignOffset}
|
| 118 |
+
sideOffset={sideOffset}
|
| 119 |
+
className={cn(
|
| 120 |
+
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
|
| 121 |
+
className
|
| 122 |
+
)}
|
| 123 |
+
{...props}
|
| 124 |
+
/>
|
| 125 |
+
</MenubarPrimitive.Portal>
|
| 126 |
+
)
|
| 127 |
+
)
|
| 128 |
+
MenubarContent.displayName = MenubarPrimitive.Content.displayName
|
| 129 |
+
|
| 130 |
+
const MenubarItem = React.forwardRef<
|
| 131 |
+
React.ElementRef<typeof MenubarPrimitive.Item>,
|
| 132 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
|
| 133 |
+
inset?: boolean
|
| 134 |
+
}
|
| 135 |
+
>(({ className, inset, ...props }, ref) => (
|
| 136 |
+
<MenubarPrimitive.Item
|
| 137 |
+
ref={ref}
|
| 138 |
+
className={cn(
|
| 139 |
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 140 |
+
inset && "pl-8",
|
| 141 |
+
className
|
| 142 |
+
)}
|
| 143 |
+
{...props}
|
| 144 |
+
/>
|
| 145 |
+
))
|
| 146 |
+
MenubarItem.displayName = MenubarPrimitive.Item.displayName
|
| 147 |
+
|
| 148 |
+
const MenubarCheckboxItem = React.forwardRef<
|
| 149 |
+
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
|
| 150 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
|
| 151 |
+
>(({ className, children, checked, ...props }, ref) => (
|
| 152 |
+
<MenubarPrimitive.CheckboxItem
|
| 153 |
+
ref={ref}
|
| 154 |
+
className={cn(
|
| 155 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 156 |
+
className
|
| 157 |
+
)}
|
| 158 |
+
checked={checked}
|
| 159 |
+
{...props}
|
| 160 |
+
>
|
| 161 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 162 |
+
<MenubarPrimitive.ItemIndicator>
|
| 163 |
+
<Check className="h-4 w-4" />
|
| 164 |
+
</MenubarPrimitive.ItemIndicator>
|
| 165 |
+
</span>
|
| 166 |
+
{children}
|
| 167 |
+
</MenubarPrimitive.CheckboxItem>
|
| 168 |
+
))
|
| 169 |
+
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
|
| 170 |
+
|
| 171 |
+
const MenubarRadioItem = React.forwardRef<
|
| 172 |
+
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
|
| 173 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
|
| 174 |
+
>(({ className, children, ...props }, ref) => (
|
| 175 |
+
<MenubarPrimitive.RadioItem
|
| 176 |
+
ref={ref}
|
| 177 |
+
className={cn(
|
| 178 |
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 179 |
+
className
|
| 180 |
+
)}
|
| 181 |
+
{...props}
|
| 182 |
+
>
|
| 183 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 184 |
+
<MenubarPrimitive.ItemIndicator>
|
| 185 |
+
<Circle className="h-4 w-4 fill-current" />
|
| 186 |
+
</MenubarPrimitive.ItemIndicator>
|
| 187 |
+
</span>
|
| 188 |
+
{children}
|
| 189 |
+
</MenubarPrimitive.RadioItem>
|
| 190 |
+
))
|
| 191 |
+
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
|
| 192 |
+
|
| 193 |
+
const MenubarLabel = React.forwardRef<
|
| 194 |
+
React.ElementRef<typeof MenubarPrimitive.Label>,
|
| 195 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
|
| 196 |
+
inset?: boolean
|
| 197 |
+
}
|
| 198 |
+
>(({ className, inset, ...props }, ref) => (
|
| 199 |
+
<MenubarPrimitive.Label
|
| 200 |
+
ref={ref}
|
| 201 |
+
className={cn(
|
| 202 |
+
"px-2 py-1.5 text-sm font-semibold",
|
| 203 |
+
inset && "pl-8",
|
| 204 |
+
className
|
| 205 |
+
)}
|
| 206 |
+
{...props}
|
| 207 |
+
/>
|
| 208 |
+
))
|
| 209 |
+
MenubarLabel.displayName = MenubarPrimitive.Label.displayName
|
| 210 |
+
|
| 211 |
+
const MenubarSeparator = React.forwardRef<
|
| 212 |
+
React.ElementRef<typeof MenubarPrimitive.Separator>,
|
| 213 |
+
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
|
| 214 |
+
>(({ className, ...props }, ref) => (
|
| 215 |
+
<MenubarPrimitive.Separator
|
| 216 |
+
ref={ref}
|
| 217 |
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
| 218 |
+
{...props}
|
| 219 |
+
/>
|
| 220 |
+
))
|
| 221 |
+
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
|
| 222 |
+
|
| 223 |
+
const MenubarShortcut = ({
|
| 224 |
+
className,
|
| 225 |
+
...props
|
| 226 |
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
| 227 |
+
return (
|
| 228 |
+
<span
|
| 229 |
+
className={cn(
|
| 230 |
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
| 231 |
+
className
|
| 232 |
+
)}
|
| 233 |
+
{...props}
|
| 234 |
+
/>
|
| 235 |
+
)
|
| 236 |
+
}
|
| 237 |
+
MenubarShortcut.displayname = "MenubarShortcut"
|
| 238 |
+
|
| 239 |
+
export {
|
| 240 |
+
Menubar,
|
| 241 |
+
MenubarMenu,
|
| 242 |
+
MenubarTrigger,
|
| 243 |
+
MenubarContent,
|
| 244 |
+
MenubarItem,
|
| 245 |
+
MenubarSeparator,
|
| 246 |
+
MenubarLabel,
|
| 247 |
+
MenubarCheckboxItem,
|
| 248 |
+
MenubarRadioGroup,
|
| 249 |
+
MenubarRadioItem,
|
| 250 |
+
MenubarPortal,
|
| 251 |
+
MenubarSubContent,
|
| 252 |
+
MenubarSubTrigger,
|
| 253 |
+
MenubarGroup,
|
| 254 |
+
MenubarSub,
|
| 255 |
+
MenubarShortcut,
|
| 256 |
+
}
|
eth-blueprint/web/src/components/ui/navigation-menu.tsx
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
| 3 |
+
import { cva } from "class-variance-authority"
|
| 4 |
+
import { ChevronDown } from "lucide-react"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const NavigationMenu = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
|
| 11 |
+
>(({ className, children, ...props }, ref) => (
|
| 12 |
+
<NavigationMenuPrimitive.Root
|
| 13 |
+
ref={ref}
|
| 14 |
+
className={cn(
|
| 15 |
+
"relative z-10 flex max-w-max flex-1 items-center justify-center",
|
| 16 |
+
className
|
| 17 |
+
)}
|
| 18 |
+
{...props}
|
| 19 |
+
>
|
| 20 |
+
{children}
|
| 21 |
+
<NavigationMenuViewport />
|
| 22 |
+
</NavigationMenuPrimitive.Root>
|
| 23 |
+
))
|
| 24 |
+
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
|
| 25 |
+
|
| 26 |
+
const NavigationMenuList = React.forwardRef<
|
| 27 |
+
React.ElementRef<typeof NavigationMenuPrimitive.List>,
|
| 28 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
|
| 29 |
+
>(({ className, ...props }, ref) => (
|
| 30 |
+
<NavigationMenuPrimitive.List
|
| 31 |
+
ref={ref}
|
| 32 |
+
className={cn(
|
| 33 |
+
"group flex flex-1 list-none items-center justify-center space-x-1",
|
| 34 |
+
className
|
| 35 |
+
)}
|
| 36 |
+
{...props}
|
| 37 |
+
/>
|
| 38 |
+
))
|
| 39 |
+
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
|
| 40 |
+
|
| 41 |
+
const NavigationMenuItem = NavigationMenuPrimitive.Item
|
| 42 |
+
|
| 43 |
+
const navigationMenuTriggerStyle = cva(
|
| 44 |
+
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent"
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
const NavigationMenuTrigger = React.forwardRef<
|
| 48 |
+
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
|
| 49 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
|
| 50 |
+
>(({ className, children, ...props }, ref) => (
|
| 51 |
+
<NavigationMenuPrimitive.Trigger
|
| 52 |
+
ref={ref}
|
| 53 |
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
| 54 |
+
{...props}
|
| 55 |
+
>
|
| 56 |
+
{children}{" "}
|
| 57 |
+
<ChevronDown
|
| 58 |
+
className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
|
| 59 |
+
aria-hidden="true"
|
| 60 |
+
/>
|
| 61 |
+
</NavigationMenuPrimitive.Trigger>
|
| 62 |
+
))
|
| 63 |
+
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
|
| 64 |
+
|
| 65 |
+
const NavigationMenuContent = React.forwardRef<
|
| 66 |
+
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
|
| 67 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
|
| 68 |
+
>(({ className, ...props }, ref) => (
|
| 69 |
+
<NavigationMenuPrimitive.Content
|
| 70 |
+
ref={ref}
|
| 71 |
+
className={cn(
|
| 72 |
+
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
|
| 73 |
+
className
|
| 74 |
+
)}
|
| 75 |
+
{...props}
|
| 76 |
+
/>
|
| 77 |
+
))
|
| 78 |
+
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
|
| 79 |
+
|
| 80 |
+
const NavigationMenuLink = NavigationMenuPrimitive.Link
|
| 81 |
+
|
| 82 |
+
const NavigationMenuViewport = React.forwardRef<
|
| 83 |
+
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
| 84 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
|
| 85 |
+
>(({ className, ...props }, ref) => (
|
| 86 |
+
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
| 87 |
+
<NavigationMenuPrimitive.Viewport
|
| 88 |
+
className={cn(
|
| 89 |
+
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
| 90 |
+
className
|
| 91 |
+
)}
|
| 92 |
+
ref={ref}
|
| 93 |
+
{...props}
|
| 94 |
+
/>
|
| 95 |
+
</div>
|
| 96 |
+
))
|
| 97 |
+
NavigationMenuViewport.displayName =
|
| 98 |
+
NavigationMenuPrimitive.Viewport.displayName
|
| 99 |
+
|
| 100 |
+
const NavigationMenuIndicator = React.forwardRef<
|
| 101 |
+
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
|
| 102 |
+
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
|
| 103 |
+
>(({ className, ...props }, ref) => (
|
| 104 |
+
<NavigationMenuPrimitive.Indicator
|
| 105 |
+
ref={ref}
|
| 106 |
+
className={cn(
|
| 107 |
+
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
|
| 108 |
+
className
|
| 109 |
+
)}
|
| 110 |
+
{...props}
|
| 111 |
+
>
|
| 112 |
+
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
| 113 |
+
</NavigationMenuPrimitive.Indicator>
|
| 114 |
+
))
|
| 115 |
+
NavigationMenuIndicator.displayName =
|
| 116 |
+
NavigationMenuPrimitive.Indicator.displayName
|
| 117 |
+
|
| 118 |
+
export {
|
| 119 |
+
navigationMenuTriggerStyle,
|
| 120 |
+
NavigationMenu,
|
| 121 |
+
NavigationMenuList,
|
| 122 |
+
NavigationMenuItem,
|
| 123 |
+
NavigationMenuContent,
|
| 124 |
+
NavigationMenuTrigger,
|
| 125 |
+
NavigationMenuLink,
|
| 126 |
+
NavigationMenuIndicator,
|
| 127 |
+
NavigationMenuViewport,
|
| 128 |
+
}
|
eth-blueprint/web/src/components/ui/popover.tsx
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const Popover = PopoverPrimitive.Root
|
| 9 |
+
|
| 10 |
+
const PopoverTrigger = PopoverPrimitive.Trigger
|
| 11 |
+
|
| 12 |
+
const PopoverAnchor = PopoverPrimitive.Anchor
|
| 13 |
+
|
| 14 |
+
const PopoverContent = React.forwardRef<
|
| 15 |
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
| 16 |
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
| 17 |
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
| 18 |
+
<PopoverPrimitive.Portal>
|
| 19 |
+
<PopoverPrimitive.Content
|
| 20 |
+
ref={ref}
|
| 21 |
+
align={align}
|
| 22 |
+
sideOffset={sideOffset}
|
| 23 |
+
className={cn(
|
| 24 |
+
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
| 25 |
+
className
|
| 26 |
+
)}
|
| 27 |
+
{...props}
|
| 28 |
+
/>
|
| 29 |
+
</PopoverPrimitive.Portal>
|
| 30 |
+
))
|
| 31 |
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
| 32 |
+
|
| 33 |
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
eth-blueprint/web/src/components/ui/progress.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as ProgressPrimitive from "@radix-ui/react-progress"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Progress = React.forwardRef<
|
| 7 |
+
React.ElementRef<typeof ProgressPrimitive.Root>,
|
| 8 |
+
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
|
| 9 |
+
>(({ className, value, ...props }, ref) => (
|
| 10 |
+
<ProgressPrimitive.Root
|
| 11 |
+
ref={ref}
|
| 12 |
+
className={cn(
|
| 13 |
+
"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
|
| 14 |
+
className
|
| 15 |
+
)}
|
| 16 |
+
{...props}
|
| 17 |
+
>
|
| 18 |
+
<ProgressPrimitive.Indicator
|
| 19 |
+
className="h-full w-full flex-1 bg-primary transition-all"
|
| 20 |
+
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
| 21 |
+
/>
|
| 22 |
+
</ProgressPrimitive.Root>
|
| 23 |
+
))
|
| 24 |
+
Progress.displayName = ProgressPrimitive.Root.displayName
|
| 25 |
+
|
| 26 |
+
export { Progress }
|
eth-blueprint/web/src/components/ui/radio-group.tsx
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
| 3 |
+
import { Circle } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const RadioGroup = React.forwardRef<
|
| 8 |
+
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
| 9 |
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
| 10 |
+
>(({ className, ...props }, ref) => {
|
| 11 |
+
return (
|
| 12 |
+
<RadioGroupPrimitive.Root
|
| 13 |
+
className={cn("grid gap-2", className)}
|
| 14 |
+
{...props}
|
| 15 |
+
ref={ref}
|
| 16 |
+
/>
|
| 17 |
+
)
|
| 18 |
+
})
|
| 19 |
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
|
| 20 |
+
|
| 21 |
+
const RadioGroupItem = React.forwardRef<
|
| 22 |
+
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
| 23 |
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
|
| 24 |
+
>(({ className, ...props }, ref) => {
|
| 25 |
+
return (
|
| 26 |
+
<RadioGroupPrimitive.Item
|
| 27 |
+
ref={ref}
|
| 28 |
+
className={cn(
|
| 29 |
+
"aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
| 30 |
+
className
|
| 31 |
+
)}
|
| 32 |
+
{...props}
|
| 33 |
+
>
|
| 34 |
+
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
| 35 |
+
<Circle className="h-3.5 w-3.5 fill-primary" />
|
| 36 |
+
</RadioGroupPrimitive.Indicator>
|
| 37 |
+
</RadioGroupPrimitive.Item>
|
| 38 |
+
)
|
| 39 |
+
})
|
| 40 |
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
|
| 41 |
+
|
| 42 |
+
export { RadioGroup, RadioGroupItem }
|
eth-blueprint/web/src/components/ui/resizable.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { GripVertical } from "lucide-react"
|
| 2 |
+
import { Group, Panel, Separator } from "react-resizable-panels"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const ResizablePanelGroup = ({
|
| 7 |
+
className,
|
| 8 |
+
...props
|
| 9 |
+
}: React.ComponentProps<typeof Group>) => (
|
| 10 |
+
<Group
|
| 11 |
+
className={cn(
|
| 12 |
+
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
| 13 |
+
className
|
| 14 |
+
)}
|
| 15 |
+
{...props}
|
| 16 |
+
/>
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
const ResizablePanel = Panel
|
| 20 |
+
|
| 21 |
+
const ResizableHandle = ({
|
| 22 |
+
withHandle,
|
| 23 |
+
className,
|
| 24 |
+
...props
|
| 25 |
+
}: React.ComponentProps<typeof Separator> & {
|
| 26 |
+
withHandle?: boolean
|
| 27 |
+
}) => (
|
| 28 |
+
<Separator
|
| 29 |
+
className={cn(
|
| 30 |
+
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
| 31 |
+
className
|
| 32 |
+
)}
|
| 33 |
+
{...props}
|
| 34 |
+
>
|
| 35 |
+
{withHandle && (
|
| 36 |
+
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
|
| 37 |
+
<GripVertical className="h-2.5 w-2.5" />
|
| 38 |
+
</div>
|
| 39 |
+
)}
|
| 40 |
+
</Separator>
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
|
eth-blueprint/web/src/components/ui/scroll-area.tsx
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const ScrollArea = React.forwardRef<
|
| 7 |
+
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
| 8 |
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
| 9 |
+
>(({ className, children, ...props }, ref) => (
|
| 10 |
+
<ScrollAreaPrimitive.Root
|
| 11 |
+
ref={ref}
|
| 12 |
+
className={cn("relative overflow-hidden", className)}
|
| 13 |
+
{...props}
|
| 14 |
+
>
|
| 15 |
+
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
| 16 |
+
{children}
|
| 17 |
+
</ScrollAreaPrimitive.Viewport>
|
| 18 |
+
<ScrollBar />
|
| 19 |
+
<ScrollAreaPrimitive.Corner />
|
| 20 |
+
</ScrollAreaPrimitive.Root>
|
| 21 |
+
))
|
| 22 |
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
| 23 |
+
|
| 24 |
+
const ScrollBar = React.forwardRef<
|
| 25 |
+
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
| 26 |
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
| 27 |
+
>(({ className, orientation = "vertical", ...props }, ref) => (
|
| 28 |
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
| 29 |
+
ref={ref}
|
| 30 |
+
orientation={orientation}
|
| 31 |
+
className={cn(
|
| 32 |
+
"flex touch-none select-none transition-colors",
|
| 33 |
+
orientation === "vertical" &&
|
| 34 |
+
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
| 35 |
+
orientation === "horizontal" &&
|
| 36 |
+
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
| 37 |
+
className
|
| 38 |
+
)}
|
| 39 |
+
{...props}
|
| 40 |
+
>
|
| 41 |
+
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
| 42 |
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
| 43 |
+
))
|
| 44 |
+
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
| 45 |
+
|
| 46 |
+
export { ScrollArea, ScrollBar }
|
eth-blueprint/web/src/components/ui/select.tsx
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as SelectPrimitive from "@radix-ui/react-select"
|
| 3 |
+
import { Check, ChevronDown, ChevronUp } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const Select = SelectPrimitive.Root
|
| 8 |
+
|
| 9 |
+
const SelectGroup = SelectPrimitive.Group
|
| 10 |
+
|
| 11 |
+
const SelectValue = SelectPrimitive.Value
|
| 12 |
+
|
| 13 |
+
const SelectTrigger = React.forwardRef<
|
| 14 |
+
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
| 15 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
| 16 |
+
>(({ className, children, ...props }, ref) => (
|
| 17 |
+
<SelectPrimitive.Trigger
|
| 18 |
+
ref={ref}
|
| 19 |
+
className={cn(
|
| 20 |
+
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
| 21 |
+
className
|
| 22 |
+
)}
|
| 23 |
+
{...props}
|
| 24 |
+
>
|
| 25 |
+
{children}
|
| 26 |
+
<SelectPrimitive.Icon asChild>
|
| 27 |
+
<ChevronDown className="h-4 w-4 opacity-50" />
|
| 28 |
+
</SelectPrimitive.Icon>
|
| 29 |
+
</SelectPrimitive.Trigger>
|
| 30 |
+
))
|
| 31 |
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
| 32 |
+
|
| 33 |
+
const SelectScrollUpButton = React.forwardRef<
|
| 34 |
+
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
| 35 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
| 36 |
+
>(({ className, ...props }, ref) => (
|
| 37 |
+
<SelectPrimitive.ScrollUpButton
|
| 38 |
+
ref={ref}
|
| 39 |
+
className={cn(
|
| 40 |
+
"flex cursor-default items-center justify-center py-1",
|
| 41 |
+
className
|
| 42 |
+
)}
|
| 43 |
+
{...props}
|
| 44 |
+
>
|
| 45 |
+
<ChevronUp className="h-4 w-4" />
|
| 46 |
+
</SelectPrimitive.ScrollUpButton>
|
| 47 |
+
))
|
| 48 |
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
|
| 49 |
+
|
| 50 |
+
const SelectScrollDownButton = React.forwardRef<
|
| 51 |
+
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
| 52 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
| 53 |
+
>(({ className, ...props }, ref) => (
|
| 54 |
+
<SelectPrimitive.ScrollDownButton
|
| 55 |
+
ref={ref}
|
| 56 |
+
className={cn(
|
| 57 |
+
"flex cursor-default items-center justify-center py-1",
|
| 58 |
+
className
|
| 59 |
+
)}
|
| 60 |
+
{...props}
|
| 61 |
+
>
|
| 62 |
+
<ChevronDown className="h-4 w-4" />
|
| 63 |
+
</SelectPrimitive.ScrollDownButton>
|
| 64 |
+
))
|
| 65 |
+
SelectScrollDownButton.displayName =
|
| 66 |
+
SelectPrimitive.ScrollDownButton.displayName
|
| 67 |
+
|
| 68 |
+
const SelectContent = React.forwardRef<
|
| 69 |
+
React.ElementRef<typeof SelectPrimitive.Content>,
|
| 70 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
| 71 |
+
>(({ className, children, position = "popper", ...props }, ref) => (
|
| 72 |
+
<SelectPrimitive.Portal>
|
| 73 |
+
<SelectPrimitive.Content
|
| 74 |
+
ref={ref}
|
| 75 |
+
className={cn(
|
| 76 |
+
"relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-select-content-transform-origin]",
|
| 77 |
+
position === "popper" &&
|
| 78 |
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
| 79 |
+
className
|
| 80 |
+
)}
|
| 81 |
+
position={position}
|
| 82 |
+
{...props}
|
| 83 |
+
>
|
| 84 |
+
<SelectScrollUpButton />
|
| 85 |
+
<SelectPrimitive.Viewport
|
| 86 |
+
className={cn(
|
| 87 |
+
"p-1",
|
| 88 |
+
position === "popper" &&
|
| 89 |
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
| 90 |
+
)}
|
| 91 |
+
>
|
| 92 |
+
{children}
|
| 93 |
+
</SelectPrimitive.Viewport>
|
| 94 |
+
<SelectScrollDownButton />
|
| 95 |
+
</SelectPrimitive.Content>
|
| 96 |
+
</SelectPrimitive.Portal>
|
| 97 |
+
))
|
| 98 |
+
SelectContent.displayName = SelectPrimitive.Content.displayName
|
| 99 |
+
|
| 100 |
+
const SelectLabel = React.forwardRef<
|
| 101 |
+
React.ElementRef<typeof SelectPrimitive.Label>,
|
| 102 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
| 103 |
+
>(({ className, ...props }, ref) => (
|
| 104 |
+
<SelectPrimitive.Label
|
| 105 |
+
ref={ref}
|
| 106 |
+
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
|
| 107 |
+
{...props}
|
| 108 |
+
/>
|
| 109 |
+
))
|
| 110 |
+
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
| 111 |
+
|
| 112 |
+
const SelectItem = React.forwardRef<
|
| 113 |
+
React.ElementRef<typeof SelectPrimitive.Item>,
|
| 114 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
| 115 |
+
>(({ className, children, ...props }, ref) => (
|
| 116 |
+
<SelectPrimitive.Item
|
| 117 |
+
ref={ref}
|
| 118 |
+
className={cn(
|
| 119 |
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 120 |
+
className
|
| 121 |
+
)}
|
| 122 |
+
{...props}
|
| 123 |
+
>
|
| 124 |
+
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 125 |
+
<SelectPrimitive.ItemIndicator>
|
| 126 |
+
<Check className="h-4 w-4" />
|
| 127 |
+
</SelectPrimitive.ItemIndicator>
|
| 128 |
+
</span>
|
| 129 |
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
| 130 |
+
</SelectPrimitive.Item>
|
| 131 |
+
))
|
| 132 |
+
SelectItem.displayName = SelectPrimitive.Item.displayName
|
| 133 |
+
|
| 134 |
+
const SelectSeparator = React.forwardRef<
|
| 135 |
+
React.ElementRef<typeof SelectPrimitive.Separator>,
|
| 136 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
| 137 |
+
>(({ className, ...props }, ref) => (
|
| 138 |
+
<SelectPrimitive.Separator
|
| 139 |
+
ref={ref}
|
| 140 |
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
| 141 |
+
{...props}
|
| 142 |
+
/>
|
| 143 |
+
))
|
| 144 |
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
| 145 |
+
|
| 146 |
+
export {
|
| 147 |
+
Select,
|
| 148 |
+
SelectGroup,
|
| 149 |
+
SelectValue,
|
| 150 |
+
SelectTrigger,
|
| 151 |
+
SelectContent,
|
| 152 |
+
SelectLabel,
|
| 153 |
+
SelectItem,
|
| 154 |
+
SelectSeparator,
|
| 155 |
+
SelectScrollUpButton,
|
| 156 |
+
SelectScrollDownButton,
|
| 157 |
+
}
|
eth-blueprint/web/src/components/ui/separator.tsx
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const Separator = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
| 11 |
+
>(
|
| 12 |
+
(
|
| 13 |
+
{ className, orientation = "horizontal", decorative = true, ...props },
|
| 14 |
+
ref
|
| 15 |
+
) => (
|
| 16 |
+
<SeparatorPrimitive.Root
|
| 17 |
+
ref={ref}
|
| 18 |
+
decorative={decorative}
|
| 19 |
+
orientation={orientation}
|
| 20 |
+
className={cn(
|
| 21 |
+
"shrink-0 bg-border",
|
| 22 |
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
| 23 |
+
className
|
| 24 |
+
)}
|
| 25 |
+
{...props}
|
| 26 |
+
/>
|
| 27 |
+
)
|
| 28 |
+
)
|
| 29 |
+
Separator.displayName = SeparatorPrimitive.Root.displayName
|
| 30 |
+
|
| 31 |
+
export { Separator }
|
eth-blueprint/web/src/components/ui/sheet.tsx
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
| 5 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 6 |
+
import { X } from "lucide-react"
|
| 7 |
+
|
| 8 |
+
import { cn } from "@/lib/utils"
|
| 9 |
+
|
| 10 |
+
const Sheet = SheetPrimitive.Root
|
| 11 |
+
|
| 12 |
+
const SheetTrigger = SheetPrimitive.Trigger
|
| 13 |
+
|
| 14 |
+
const SheetClose = SheetPrimitive.Close
|
| 15 |
+
|
| 16 |
+
const SheetPortal = SheetPrimitive.Portal
|
| 17 |
+
|
| 18 |
+
const SheetOverlay = React.forwardRef<
|
| 19 |
+
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
| 20 |
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
| 21 |
+
>(({ className, ...props }, ref) => (
|
| 22 |
+
<SheetPrimitive.Overlay
|
| 23 |
+
className={cn(
|
| 24 |
+
"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",
|
| 25 |
+
className
|
| 26 |
+
)}
|
| 27 |
+
{...props}
|
| 28 |
+
ref={ref}
|
| 29 |
+
/>
|
| 30 |
+
))
|
| 31 |
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
| 32 |
+
|
| 33 |
+
const sheetVariants = cva(
|
| 34 |
+
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
| 35 |
+
{
|
| 36 |
+
variants: {
|
| 37 |
+
side: {
|
| 38 |
+
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
| 39 |
+
bottom:
|
| 40 |
+
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
| 41 |
+
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
| 42 |
+
right:
|
| 43 |
+
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
| 44 |
+
},
|
| 45 |
+
},
|
| 46 |
+
defaultVariants: {
|
| 47 |
+
side: "right",
|
| 48 |
+
},
|
| 49 |
+
}
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
interface SheetContentProps
|
| 53 |
+
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
| 54 |
+
VariantProps<typeof sheetVariants> {}
|
| 55 |
+
|
| 56 |
+
const SheetContent = React.forwardRef<
|
| 57 |
+
React.ElementRef<typeof SheetPrimitive.Content>,
|
| 58 |
+
SheetContentProps
|
| 59 |
+
>(({ side = "right", className, children, ...props }, ref) => (
|
| 60 |
+
<SheetPortal>
|
| 61 |
+
<SheetOverlay />
|
| 62 |
+
<SheetPrimitive.Content
|
| 63 |
+
ref={ref}
|
| 64 |
+
className={cn(sheetVariants({ side }), className)}
|
| 65 |
+
{...props}
|
| 66 |
+
>
|
| 67 |
+
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
| 68 |
+
<X className="h-4 w-4" />
|
| 69 |
+
<span className="sr-only">Close</span>
|
| 70 |
+
</SheetPrimitive.Close>
|
| 71 |
+
{children}
|
| 72 |
+
</SheetPrimitive.Content>
|
| 73 |
+
</SheetPortal>
|
| 74 |
+
))
|
| 75 |
+
SheetContent.displayName = SheetPrimitive.Content.displayName
|
| 76 |
+
|
| 77 |
+
const SheetHeader = ({
|
| 78 |
+
className,
|
| 79 |
+
...props
|
| 80 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 81 |
+
<div
|
| 82 |
+
className={cn(
|
| 83 |
+
"flex flex-col space-y-2 text-center sm:text-left",
|
| 84 |
+
className
|
| 85 |
+
)}
|
| 86 |
+
{...props}
|
| 87 |
+
/>
|
| 88 |
+
)
|
| 89 |
+
SheetHeader.displayName = "SheetHeader"
|
| 90 |
+
|
| 91 |
+
const SheetFooter = ({
|
| 92 |
+
className,
|
| 93 |
+
...props
|
| 94 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 95 |
+
<div
|
| 96 |
+
className={cn(
|
| 97 |
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
| 98 |
+
className
|
| 99 |
+
)}
|
| 100 |
+
{...props}
|
| 101 |
+
/>
|
| 102 |
+
)
|
| 103 |
+
SheetFooter.displayName = "SheetFooter"
|
| 104 |
+
|
| 105 |
+
const SheetTitle = React.forwardRef<
|
| 106 |
+
React.ElementRef<typeof SheetPrimitive.Title>,
|
| 107 |
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
| 108 |
+
>(({ className, ...props }, ref) => (
|
| 109 |
+
<SheetPrimitive.Title
|
| 110 |
+
ref={ref}
|
| 111 |
+
className={cn("text-lg font-semibold text-foreground", className)}
|
| 112 |
+
{...props}
|
| 113 |
+
/>
|
| 114 |
+
))
|
| 115 |
+
SheetTitle.displayName = SheetPrimitive.Title.displayName
|
| 116 |
+
|
| 117 |
+
const SheetDescription = React.forwardRef<
|
| 118 |
+
React.ElementRef<typeof SheetPrimitive.Description>,
|
| 119 |
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
| 120 |
+
>(({ className, ...props }, ref) => (
|
| 121 |
+
<SheetPrimitive.Description
|
| 122 |
+
ref={ref}
|
| 123 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 124 |
+
{...props}
|
| 125 |
+
/>
|
| 126 |
+
))
|
| 127 |
+
SheetDescription.displayName = SheetPrimitive.Description.displayName
|
| 128 |
+
|
| 129 |
+
export {
|
| 130 |
+
Sheet,
|
| 131 |
+
SheetPortal,
|
| 132 |
+
SheetOverlay,
|
| 133 |
+
SheetTrigger,
|
| 134 |
+
SheetClose,
|
| 135 |
+
SheetContent,
|
| 136 |
+
SheetHeader,
|
| 137 |
+
SheetFooter,
|
| 138 |
+
SheetTitle,
|
| 139 |
+
SheetDescription,
|
| 140 |
+
}
|
eth-blueprint/web/src/components/ui/skeleton.tsx
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { cn } from "@/lib/utils"
|
| 2 |
+
|
| 3 |
+
function Skeleton({
|
| 4 |
+
className,
|
| 5 |
+
...props
|
| 6 |
+
}: React.HTMLAttributes<HTMLDivElement>) {
|
| 7 |
+
return (
|
| 8 |
+
<div
|
| 9 |
+
className={cn("animate-pulse rounded-md bg-[var(--bg-subtle)]", className)}
|
| 10 |
+
{...props}
|
| 11 |
+
/>
|
| 12 |
+
)
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
export { Skeleton }
|
eth-blueprint/web/src/components/ui/slider.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as SliderPrimitive from "@radix-ui/react-slider"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Slider = React.forwardRef<
|
| 7 |
+
React.ElementRef<typeof SliderPrimitive.Root>,
|
| 8 |
+
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
| 9 |
+
>(({ className, ...props }, ref) => (
|
| 10 |
+
<SliderPrimitive.Root
|
| 11 |
+
ref={ref}
|
| 12 |
+
className={cn(
|
| 13 |
+
"relative flex w-full touch-none select-none items-center",
|
| 14 |
+
className
|
| 15 |
+
)}
|
| 16 |
+
{...props}
|
| 17 |
+
>
|
| 18 |
+
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
|
| 19 |
+
<SliderPrimitive.Range className="absolute h-full bg-primary" />
|
| 20 |
+
</SliderPrimitive.Track>
|
| 21 |
+
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
|
| 22 |
+
</SliderPrimitive.Root>
|
| 23 |
+
))
|
| 24 |
+
Slider.displayName = SliderPrimitive.Root.displayName
|
| 25 |
+
|
| 26 |
+
export { Slider }
|
eth-blueprint/web/src/components/ui/sonner.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useTheme } from "next-themes"
|
| 2 |
+
import { Toaster as Sonner } from "sonner"
|
| 3 |
+
|
| 4 |
+
type ToasterProps = React.ComponentProps<typeof Sonner>
|
| 5 |
+
|
| 6 |
+
const Toaster = ({ ...props }: ToasterProps) => {
|
| 7 |
+
const { theme = "system" } = useTheme()
|
| 8 |
+
|
| 9 |
+
return (
|
| 10 |
+
<Sonner
|
| 11 |
+
theme={theme as ToasterProps["theme"]}
|
| 12 |
+
className="toaster group"
|
| 13 |
+
toastOptions={{
|
| 14 |
+
classNames: {
|
| 15 |
+
toast:
|
| 16 |
+
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
| 17 |
+
description: "group-[.toast]:text-muted-foreground",
|
| 18 |
+
actionButton:
|
| 19 |
+
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
| 20 |
+
cancelButton:
|
| 21 |
+
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
| 22 |
+
},
|
| 23 |
+
}}
|
| 24 |
+
{...props}
|
| 25 |
+
/>
|
| 26 |
+
)
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
export { Toaster }
|
eth-blueprint/web/src/components/ui/switch.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as SwitchPrimitives from "@radix-ui/react-switch"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
|
| 8 |
+
const Switch = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof SwitchPrimitives.Root>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
| 11 |
+
>(({ className, ...props }, ref) => (
|
| 12 |
+
<SwitchPrimitives.Root
|
| 13 |
+
className={cn(
|
| 14 |
+
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
| 15 |
+
className
|
| 16 |
+
)}
|
| 17 |
+
{...props}
|
| 18 |
+
ref={ref}
|
| 19 |
+
>
|
| 20 |
+
<SwitchPrimitives.Thumb
|
| 21 |
+
className={cn(
|
| 22 |
+
"pointer-events-none block h-4 w-4 rounded-full bg-[var(--neutral-0)] shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
| 23 |
+
)}
|
| 24 |
+
/>
|
| 25 |
+
</SwitchPrimitives.Root>
|
| 26 |
+
))
|
| 27 |
+
Switch.displayName = SwitchPrimitives.Root.displayName
|
| 28 |
+
|
| 29 |
+
export { Switch }
|
eth-blueprint/web/src/components/ui/table.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
|
| 3 |
+
import { cn } from "@/lib/utils"
|
| 4 |
+
|
| 5 |
+
const Table = React.forwardRef<
|
| 6 |
+
HTMLTableElement,
|
| 7 |
+
React.HTMLAttributes<HTMLTableElement>
|
| 8 |
+
>(({ className, ...props }, ref) => (
|
| 9 |
+
<div className="relative w-full overflow-auto">
|
| 10 |
+
<table
|
| 11 |
+
ref={ref}
|
| 12 |
+
className={cn("w-full caption-bottom text-sm", className)}
|
| 13 |
+
{...props}
|
| 14 |
+
/>
|
| 15 |
+
</div>
|
| 16 |
+
))
|
| 17 |
+
Table.displayName = "Table"
|
| 18 |
+
|
| 19 |
+
const TableHeader = React.forwardRef<
|
| 20 |
+
HTMLTableSectionElement,
|
| 21 |
+
React.HTMLAttributes<HTMLTableSectionElement>
|
| 22 |
+
>(({ className, ...props }, ref) => (
|
| 23 |
+
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
| 24 |
+
))
|
| 25 |
+
TableHeader.displayName = "TableHeader"
|
| 26 |
+
|
| 27 |
+
const TableBody = React.forwardRef<
|
| 28 |
+
HTMLTableSectionElement,
|
| 29 |
+
React.HTMLAttributes<HTMLTableSectionElement>
|
| 30 |
+
>(({ className, ...props }, ref) => (
|
| 31 |
+
<tbody
|
| 32 |
+
ref={ref}
|
| 33 |
+
className={cn("[&_tr:last-child]:border-0", className)}
|
| 34 |
+
{...props}
|
| 35 |
+
/>
|
| 36 |
+
))
|
| 37 |
+
TableBody.displayName = "TableBody"
|
| 38 |
+
|
| 39 |
+
const TableFooter = React.forwardRef<
|
| 40 |
+
HTMLTableSectionElement,
|
| 41 |
+
React.HTMLAttributes<HTMLTableSectionElement>
|
| 42 |
+
>(({ className, ...props }, ref) => (
|
| 43 |
+
<tfoot
|
| 44 |
+
ref={ref}
|
| 45 |
+
className={cn(
|
| 46 |
+
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
| 47 |
+
className
|
| 48 |
+
)}
|
| 49 |
+
{...props}
|
| 50 |
+
/>
|
| 51 |
+
))
|
| 52 |
+
TableFooter.displayName = "TableFooter"
|
| 53 |
+
|
| 54 |
+
const TableRow = React.forwardRef<
|
| 55 |
+
HTMLTableRowElement,
|
| 56 |
+
React.HTMLAttributes<HTMLTableRowElement>
|
| 57 |
+
>(({ className, ...props }, ref) => (
|
| 58 |
+
<tr
|
| 59 |
+
ref={ref}
|
| 60 |
+
className={cn(
|
| 61 |
+
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
| 62 |
+
className
|
| 63 |
+
)}
|
| 64 |
+
{...props}
|
| 65 |
+
/>
|
| 66 |
+
))
|
| 67 |
+
TableRow.displayName = "TableRow"
|
| 68 |
+
|
| 69 |
+
const TableHead = React.forwardRef<
|
| 70 |
+
HTMLTableCellElement,
|
| 71 |
+
React.ThHTMLAttributes<HTMLTableCellElement>
|
| 72 |
+
>(({ className, ...props }, ref) => (
|
| 73 |
+
<th
|
| 74 |
+
ref={ref}
|
| 75 |
+
className={cn(
|
| 76 |
+
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
| 77 |
+
className
|
| 78 |
+
)}
|
| 79 |
+
{...props}
|
| 80 |
+
/>
|
| 81 |
+
))
|
| 82 |
+
TableHead.displayName = "TableHead"
|
| 83 |
+
|
| 84 |
+
const TableCell = React.forwardRef<
|
| 85 |
+
HTMLTableCellElement,
|
| 86 |
+
React.TdHTMLAttributes<HTMLTableCellElement>
|
| 87 |
+
>(({ className, ...props }, ref) => (
|
| 88 |
+
<td
|
| 89 |
+
ref={ref}
|
| 90 |
+
className={cn(
|
| 91 |
+
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
| 92 |
+
className
|
| 93 |
+
)}
|
| 94 |
+
{...props}
|
| 95 |
+
/>
|
| 96 |
+
))
|
| 97 |
+
TableCell.displayName = "TableCell"
|
| 98 |
+
|
| 99 |
+
const TableCaption = React.forwardRef<
|
| 100 |
+
HTMLTableCaptionElement,
|
| 101 |
+
React.HTMLAttributes<HTMLTableCaptionElement>
|
| 102 |
+
>(({ className, ...props }, ref) => (
|
| 103 |
+
<caption
|
| 104 |
+
ref={ref}
|
| 105 |
+
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
| 106 |
+
{...props}
|
| 107 |
+
/>
|
| 108 |
+
))
|
| 109 |
+
TableCaption.displayName = "TableCaption"
|
| 110 |
+
|
| 111 |
+
export {
|
| 112 |
+
Table,
|
| 113 |
+
TableHeader,
|
| 114 |
+
TableBody,
|
| 115 |
+
TableFooter,
|
| 116 |
+
TableHead,
|
| 117 |
+
TableRow,
|
| 118 |
+
TableCell,
|
| 119 |
+
TableCaption,
|
| 120 |
+
}
|
eth-blueprint/web/src/components/ui/tabs.tsx
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Tabs = TabsPrimitive.Root
|
| 7 |
+
|
| 8 |
+
const TabsList = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof TabsPrimitive.List>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
| 11 |
+
>(({ className, ...props }, ref) => (
|
| 12 |
+
<TabsPrimitive.List
|
| 13 |
+
ref={ref}
|
| 14 |
+
className={cn(
|
| 15 |
+
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
| 16 |
+
className
|
| 17 |
+
)}
|
| 18 |
+
{...props}
|
| 19 |
+
/>
|
| 20 |
+
))
|
| 21 |
+
TabsList.displayName = TabsPrimitive.List.displayName
|
| 22 |
+
|
| 23 |
+
const TabsTrigger = React.forwardRef<
|
| 24 |
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
| 25 |
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
| 26 |
+
>(({ className, ...props }, ref) => (
|
| 27 |
+
<TabsPrimitive.Trigger
|
| 28 |
+
ref={ref}
|
| 29 |
+
className={cn(
|
| 30 |
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
|
| 31 |
+
className
|
| 32 |
+
)}
|
| 33 |
+
{...props}
|
| 34 |
+
/>
|
| 35 |
+
))
|
| 36 |
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
| 37 |
+
|
| 38 |
+
const TabsContent = React.forwardRef<
|
| 39 |
+
React.ElementRef<typeof TabsPrimitive.Content>,
|
| 40 |
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
| 41 |
+
>(({ className, ...props }, ref) => (
|
| 42 |
+
<TabsPrimitive.Content
|
| 43 |
+
ref={ref}
|
| 44 |
+
className={cn(
|
| 45 |
+
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
| 46 |
+
className
|
| 47 |
+
)}
|
| 48 |
+
{...props}
|
| 49 |
+
/>
|
| 50 |
+
))
|
| 51 |
+
TabsContent.displayName = TabsPrimitive.Content.displayName
|
| 52 |
+
|
| 53 |
+
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
eth-blueprint/web/src/components/ui/textarea.tsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
|
| 3 |
+
import { cn } from "@/lib/utils"
|
| 4 |
+
|
| 5 |
+
const Textarea = React.forwardRef<
|
| 6 |
+
HTMLTextAreaElement,
|
| 7 |
+
React.ComponentProps<"textarea">
|
| 8 |
+
>(({ className, ...props }, ref) => {
|
| 9 |
+
return (
|
| 10 |
+
<textarea
|
| 11 |
+
className={cn(
|
| 12 |
+
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
| 13 |
+
className
|
| 14 |
+
)}
|
| 15 |
+
ref={ref}
|
| 16 |
+
{...props}
|
| 17 |
+
/>
|
| 18 |
+
)
|
| 19 |
+
})
|
| 20 |
+
Textarea.displayName = "Textarea"
|
| 21 |
+
|
| 22 |
+
export { Textarea }
|
eth-blueprint/web/src/components/ui/toast.tsx
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as ToastPrimitives from "@radix-ui/react-toast"
|
| 5 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 6 |
+
import { X } from "lucide-react"
|
| 7 |
+
|
| 8 |
+
import { cn } from "@/lib/utils"
|
| 9 |
+
|
| 10 |
+
const ToastProvider = ToastPrimitives.Provider
|
| 11 |
+
|
| 12 |
+
const ToastViewport = React.forwardRef<
|
| 13 |
+
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
| 14 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
| 15 |
+
>(({ className, ...props }, ref) => (
|
| 16 |
+
<ToastPrimitives.Viewport
|
| 17 |
+
ref={ref}
|
| 18 |
+
className={cn(
|
| 19 |
+
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
| 20 |
+
className
|
| 21 |
+
)}
|
| 22 |
+
{...props}
|
| 23 |
+
/>
|
| 24 |
+
))
|
| 25 |
+
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
|
| 26 |
+
|
| 27 |
+
const toastVariants = cva(
|
| 28 |
+
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
| 29 |
+
{
|
| 30 |
+
variants: {
|
| 31 |
+
variant: {
|
| 32 |
+
default: "border bg-background text-foreground",
|
| 33 |
+
destructive:
|
| 34 |
+
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
| 35 |
+
},
|
| 36 |
+
},
|
| 37 |
+
defaultVariants: {
|
| 38 |
+
variant: "default",
|
| 39 |
+
},
|
| 40 |
+
}
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
const Toast = React.forwardRef<
|
| 44 |
+
React.ElementRef<typeof ToastPrimitives.Root>,
|
| 45 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
| 46 |
+
VariantProps<typeof toastVariants>
|
| 47 |
+
>(({ className, variant, ...props }, ref) => {
|
| 48 |
+
return (
|
| 49 |
+
<ToastPrimitives.Root
|
| 50 |
+
ref={ref}
|
| 51 |
+
className={cn(toastVariants({ variant }), className)}
|
| 52 |
+
{...props}
|
| 53 |
+
/>
|
| 54 |
+
)
|
| 55 |
+
})
|
| 56 |
+
Toast.displayName = ToastPrimitives.Root.displayName
|
| 57 |
+
|
| 58 |
+
const ToastAction = React.forwardRef<
|
| 59 |
+
React.ElementRef<typeof ToastPrimitives.Action>,
|
| 60 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
| 61 |
+
>(({ className, ...props }, ref) => (
|
| 62 |
+
<ToastPrimitives.Action
|
| 63 |
+
ref={ref}
|
| 64 |
+
className={cn(
|
| 65 |
+
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
|
| 66 |
+
className
|
| 67 |
+
)}
|
| 68 |
+
{...props}
|
| 69 |
+
/>
|
| 70 |
+
))
|
| 71 |
+
ToastAction.displayName = ToastPrimitives.Action.displayName
|
| 72 |
+
|
| 73 |
+
const ToastClose = React.forwardRef<
|
| 74 |
+
React.ElementRef<typeof ToastPrimitives.Close>,
|
| 75 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
| 76 |
+
>(({ className, ...props }, ref) => (
|
| 77 |
+
<ToastPrimitives.Close
|
| 78 |
+
ref={ref}
|
| 79 |
+
className={cn(
|
| 80 |
+
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
| 81 |
+
className
|
| 82 |
+
)}
|
| 83 |
+
toast-close=""
|
| 84 |
+
{...props}
|
| 85 |
+
>
|
| 86 |
+
<X className="h-4 w-4" />
|
| 87 |
+
</ToastPrimitives.Close>
|
| 88 |
+
))
|
| 89 |
+
ToastClose.displayName = ToastPrimitives.Close.displayName
|
| 90 |
+
|
| 91 |
+
const ToastTitle = React.forwardRef<
|
| 92 |
+
React.ElementRef<typeof ToastPrimitives.Title>,
|
| 93 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
| 94 |
+
>(({ className, ...props }, ref) => (
|
| 95 |
+
<ToastPrimitives.Title
|
| 96 |
+
ref={ref}
|
| 97 |
+
className={cn("text-sm font-semibold [&+div]:text-xs", className)}
|
| 98 |
+
{...props}
|
| 99 |
+
/>
|
| 100 |
+
))
|
| 101 |
+
ToastTitle.displayName = ToastPrimitives.Title.displayName
|
| 102 |
+
|
| 103 |
+
const ToastDescription = React.forwardRef<
|
| 104 |
+
React.ElementRef<typeof ToastPrimitives.Description>,
|
| 105 |
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
| 106 |
+
>(({ className, ...props }, ref) => (
|
| 107 |
+
<ToastPrimitives.Description
|
| 108 |
+
ref={ref}
|
| 109 |
+
className={cn("text-sm opacity-90", className)}
|
| 110 |
+
{...props}
|
| 111 |
+
/>
|
| 112 |
+
))
|
| 113 |
+
ToastDescription.displayName = ToastPrimitives.Description.displayName
|
| 114 |
+
|
| 115 |
+
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
|
| 116 |
+
|
| 117 |
+
type ToastActionElement = React.ReactElement<typeof ToastAction>
|
| 118 |
+
|
| 119 |
+
export {
|
| 120 |
+
type ToastProps,
|
| 121 |
+
type ToastActionElement,
|
| 122 |
+
ToastProvider,
|
| 123 |
+
ToastViewport,
|
| 124 |
+
Toast,
|
| 125 |
+
ToastTitle,
|
| 126 |
+
ToastDescription,
|
| 127 |
+
ToastClose,
|
| 128 |
+
ToastAction,
|
| 129 |
+
}
|
eth-blueprint/web/src/components/ui/toaster.tsx
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import { useToast } from "@/hooks/use-toast"
|
| 4 |
+
import {
|
| 5 |
+
Toast,
|
| 6 |
+
ToastClose,
|
| 7 |
+
ToastDescription,
|
| 8 |
+
ToastProvider,
|
| 9 |
+
ToastTitle,
|
| 10 |
+
ToastViewport,
|
| 11 |
+
} from "@/components/ui/toast"
|
| 12 |
+
|
| 13 |
+
export function Toaster() {
|
| 14 |
+
const { toasts } = useToast()
|
| 15 |
+
|
| 16 |
+
return (
|
| 17 |
+
<ToastProvider>
|
| 18 |
+
{toasts.map(function ({ id, title, description, action, ...props }) {
|
| 19 |
+
return (
|
| 20 |
+
<Toast key={id} {...props}>
|
| 21 |
+
<div className="grid gap-1">
|
| 22 |
+
{title && <ToastTitle>{title}</ToastTitle>}
|
| 23 |
+
{description && (
|
| 24 |
+
<ToastDescription>{description}</ToastDescription>
|
| 25 |
+
)}
|
| 26 |
+
</div>
|
| 27 |
+
{action}
|
| 28 |
+
<ToastClose />
|
| 29 |
+
</Toast>
|
| 30 |
+
)
|
| 31 |
+
})}
|
| 32 |
+
<ToastViewport />
|
| 33 |
+
</ToastProvider>
|
| 34 |
+
)
|
| 35 |
+
}
|
eth-blueprint/web/src/components/ui/toggle-group.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
|
| 3 |
+
import { type VariantProps } from "class-variance-authority"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
import { toggleVariants } from "@/components/ui/toggle"
|
| 7 |
+
|
| 8 |
+
const ToggleGroupContext = React.createContext<
|
| 9 |
+
VariantProps<typeof toggleVariants>
|
| 10 |
+
>({
|
| 11 |
+
size: "default",
|
| 12 |
+
variant: "default",
|
| 13 |
+
})
|
| 14 |
+
|
| 15 |
+
const ToggleGroup = React.forwardRef<
|
| 16 |
+
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
|
| 17 |
+
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
|
| 18 |
+
VariantProps<typeof toggleVariants>
|
| 19 |
+
>(({ className, variant, size, children, ...props }, ref) => (
|
| 20 |
+
<ToggleGroupPrimitive.Root
|
| 21 |
+
ref={ref}
|
| 22 |
+
className={cn("flex items-center justify-center gap-1", className)}
|
| 23 |
+
{...props}
|
| 24 |
+
>
|
| 25 |
+
<ToggleGroupContext.Provider value={{ variant, size }}>
|
| 26 |
+
{children}
|
| 27 |
+
</ToggleGroupContext.Provider>
|
| 28 |
+
</ToggleGroupPrimitive.Root>
|
| 29 |
+
))
|
| 30 |
+
|
| 31 |
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
|
| 32 |
+
|
| 33 |
+
const ToggleGroupItem = React.forwardRef<
|
| 34 |
+
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
|
| 35 |
+
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
|
| 36 |
+
VariantProps<typeof toggleVariants>
|
| 37 |
+
>(({ className, children, variant, size, ...props }, ref) => {
|
| 38 |
+
const context = React.useContext(ToggleGroupContext)
|
| 39 |
+
|
| 40 |
+
return (
|
| 41 |
+
<ToggleGroupPrimitive.Item
|
| 42 |
+
ref={ref}
|
| 43 |
+
className={cn(
|
| 44 |
+
toggleVariants({
|
| 45 |
+
variant: context.variant || variant,
|
| 46 |
+
size: context.size || size,
|
| 47 |
+
}),
|
| 48 |
+
className
|
| 49 |
+
)}
|
| 50 |
+
{...props}
|
| 51 |
+
>
|
| 52 |
+
{children}
|
| 53 |
+
</ToggleGroupPrimitive.Item>
|
| 54 |
+
)
|
| 55 |
+
})
|
| 56 |
+
|
| 57 |
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
|
| 58 |
+
|
| 59 |
+
export { ToggleGroup, ToggleGroupItem }
|
eth-blueprint/web/src/components/ui/toggle.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
| 3 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const toggleVariants = cva(
|
| 8 |
+
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
| 9 |
+
{
|
| 10 |
+
variants: {
|
| 11 |
+
variant: {
|
| 12 |
+
default: "bg-transparent",
|
| 13 |
+
outline:
|
| 14 |
+
"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
|
| 15 |
+
},
|
| 16 |
+
size: {
|
| 17 |
+
default: "h-9 px-2 min-w-9",
|
| 18 |
+
sm: "h-8 px-1.5 min-w-8",
|
| 19 |
+
lg: "h-10 px-2.5 min-w-10",
|
| 20 |
+
},
|
| 21 |
+
},
|
| 22 |
+
defaultVariants: {
|
| 23 |
+
variant: "default",
|
| 24 |
+
size: "default",
|
| 25 |
+
},
|
| 26 |
+
}
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
const Toggle = React.forwardRef<
|
| 30 |
+
React.ElementRef<typeof TogglePrimitive.Root>,
|
| 31 |
+
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
| 32 |
+
VariantProps<typeof toggleVariants>
|
| 33 |
+
>(({ className, variant, size, ...props }, ref) => (
|
| 34 |
+
<TogglePrimitive.Root
|
| 35 |
+
ref={ref}
|
| 36 |
+
className={cn(toggleVariants({ variant, size, className }))}
|
| 37 |
+
{...props}
|
| 38 |
+
/>
|
| 39 |
+
))
|
| 40 |
+
|
| 41 |
+
Toggle.displayName = TogglePrimitive.Root.displayName
|
| 42 |
+
|
| 43 |
+
export { Toggle, toggleVariants }
|
eth-blueprint/web/src/components/ui/tooltip.tsx
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const TooltipProvider = TooltipPrimitive.Provider
|
| 7 |
+
|
| 8 |
+
const Tooltip = TooltipPrimitive.Root
|
| 9 |
+
|
| 10 |
+
const TooltipTrigger = TooltipPrimitive.Trigger
|
| 11 |
+
|
| 12 |
+
const TooltipContent = React.forwardRef<
|
| 13 |
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
| 14 |
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
| 15 |
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
| 16 |
+
<TooltipPrimitive.Portal>
|
| 17 |
+
<TooltipPrimitive.Content
|
| 18 |
+
ref={ref}
|
| 19 |
+
sideOffset={sideOffset}
|
| 20 |
+
className={cn(
|
| 21 |
+
"z-50 w-fit text-balance rounded-[10px] border border-[var(--border-base)] bg-foreground/5 px-3 py-2 text-xs text-[var(--fg-subtle)] backdrop-blur-2xl animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-tooltip-content-transform-origin]",
|
| 22 |
+
className
|
| 23 |
+
)}
|
| 24 |
+
{...props}
|
| 25 |
+
/>
|
| 26 |
+
</TooltipPrimitive.Portal>
|
| 27 |
+
))
|
| 28 |
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
| 29 |
+
|
| 30 |
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|