@aidget-community/deepseek-whale-pendant 0.0.0-stage → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/agents.md ADDED
@@ -0,0 +1,75 @@
1
+ # deepseek-whale-pendant · DeepSeek 鲸鱼娘 · 亚克力挂件
2
+
3
+ ## 用途
4
+
5
+ 透明桌面上的亚克力挂件复刻:吃饭场景的鲸鱼娘立绘加底部 DeepSeek 铭牌,边缘是半透明
6
+ 玻璃刀模,高光跟随鼠标。原照片里的米色布纹背景和下方显示器桌面已扣除,只保留图案本体。
7
+
8
+ ## 素材
9
+
10
+ - 图案由生图模型按实物照片复刻为 `1254 × 1254` 透明底图,再离线加工成 `700 × 692` 的
11
+ RGBA PNG,作为运行期资源放在 `assets/pendant.png`,由 `style.css` 的 `--sil` 变量声明
12
+ 一次,可见层与遮罩层共用。`assets/screenshot.png` 只给社区卡片用,运行期不加载。
13
+ - 资源引用必须是包内相对路径:Aidget 只放行 `index.html`、`style.css` 和 `assets/**`,
14
+ PNG 以 `image/png` 返回,CSP 的 `img-src` 与 `style-src` 已包含本地源。不要改成绝对
15
+ 路径或远程 URL,也不要为此往 `network` 里加源。
16
+ - 图案自带的白色贴纸描边(实测厚 14–20px)已按“到轮廓的深度”改成渐隐透明:环带内
17
+ alpha 由约 0.14 的底色线性升到原值,深度 22px 处接回画面自己的深蓝描边。不要把这层
18
+ 重新涂成不透明白色,也不要反过来把整张图加一圈实心白边——凸起之间的缝隙会被糊住,
19
+ 看起来就像凸起被削平。
20
+ - 玻璃刀模是四圈向外偏移的轮廓,全部半透明:内侧高光线(半径 3、白 50%)、玻璃本体
21
+ (半径 9、冷白 12%)、外缘亮边(半径 12、近白 38%)、外围冷色轮廓(半径 15、深蓝
22
+ 18%),并按左上打光做亮度渐变。半径刻意保持窄:刀模外扩会填平相邻凸起之间的窄缝。
23
+ 外围轮廓不能删,浅色桌面上的剪影靠它撑住。
24
+ - 素材四周自带 7.5%(约 53px)透明留白,挂件本体只占画布 85%。这圈留白用于消除
25
+ “上方和左侧凸起被截断”的观感,同时保证玻璃边和投影不被窗口边缘切掉;不要为了填满
26
+ 画面收紧它。需要更大挂件就整体放大窗口,留白按比例跟着长。
27
+ - 必须完整保留:人物与饭碗、筷子、水滴与气泡、右侧红心气泡、底部 `DeepSeek` 铭牌
28
+ (鲸鱼尾图标、蓝色文字、两端四角星)。
29
+
30
+ ## 结构
31
+
32
+ - `main.stage` 带 `data-aidget-region="stage"`,可整体替换挂件结构;内部不要新增文字、
33
+ 底板或按钮。`<script>` 在 `main` 之外,patch stage 区域不会影响脚本。
34
+ - `.pendant-art`(可见层)与 `.pendant-shine`(遮罩层)共用同一个 `--sil`,轮廓只有一份
35
+ 数据;两层分别按 `background-size: contain` 与 `mask-size: contain` 居中,改画布边距时
36
+ 必须同步,否则遮罩与图案错位。
37
+ - 初始尺寸 `249 × 247`,与图案等比:本体约 212 CSS px,四边各约 18 CSS px 透明空隙。
38
+ 安装后窗口位置和尺寸归用户所有,内容更新不得移动窗口。
39
+ - 换图案只替换 `assets/pendant.png`;改动画布尺寸或留白时同步 `style.css`,否则遮罩与
40
+ 图案错位。`aidget_patch` 只适合改 HTML 结构,不能用来换二进制资源。
41
+ - 用 `aidget widget create` 建的本地开发副本没有写入 `assets/` 的通道,可能把同一张 PNG
42
+ 内联成 data URI;那是调试形态,不是发布形态,两边各自核对字节。
43
+
44
+ ## 扫光(跟随鼠标)
45
+
46
+ - `.pendant-shine` 内含 `.shine-spot`(径向柔光)与 `.shine-streak`(斜向高光带),位置由
47
+ `--mx` / `--my` 决定,整层被 `--sil` 遮罩限制在轮廓内,用 `mix-blend-mode: screen` 提亮,
48
+ `isolation: isolate` 防止溢出到透明区。
49
+ - `index.html` 末尾的内联脚本通过 `window.aidget.onPointer` 接收宿主 hover 事件;
50
+ `enter` / `move` 把 viewport 局部坐标写入 `--mx` / `--my` 并升到全亮,`leave` 回到
51
+ 静止位 `(30%, 20%)`、亮度 `0.42`。不要改回 DOM `pointermove`,也不要在窗口 `blur`
52
+ 时收掉高光,否则非活动窗口会失去跟随效果。
53
+ - `--shine` 初值必须保持 `0`:脚本未执行时挂件呈无高光降级态,截图里能否看到柔光也用来
54
+ 判断脚本是否运行。
55
+ - 扫光动画使用 `window.aidget.requestAnimationFrame`,按经过时间插值;收敛后停止申请帧。
56
+ 需要宿主提供该动画 API,不要改用 iframe 的原生帧时钟或增加常驻循环。
57
+ - `prefers-reduced-motion: reduce` 时脚本直接跳到目标值,不做插值跟随。
58
+
59
+ ## 权限与外观
60
+
61
+ - `permissions` 仅 `["script"]`,只为扫光跟随鼠标;`network` 必须保持空数组,不加远程
62
+ 资源或数据请求。无外部数据、无定时刷新,除扫光外没有 CSS 动画。
63
+ - `dragMode` 为 `all`:拖动需要按下鼠标,不干扰悬停扫光。若宿主拖动吞掉指针事件导致
64
+ 扫光不动,改成 `handle`,不要删脚本。
65
+ - 使用 `aidget-surface="none"` 与透明页面背景;不要矩形底板、窗口材质,也不要用
66
+ `backdrop-filter`(挂件页面背后没有可采样的内容,拖动时只会闪空白)。
67
+ - 保留图案本身的扁平赛璐璐上色,不要叠加新的调色滤镜。
68
+
69
+ ## 平台
70
+
71
+ - 实现只用标准 HTML/CSS/JS,遮罩与高光定位均写 `-webkit-` 前缀版本,无构建步骤、无依赖。
72
+ - `config.json` 按仓库负责人要求声明全平台,与 `whalechan-acrylic` 和三个热搜组件同一
73
+ 口径。真实渲染验证目前只有 macOS(Aidget 截图加原生窗口抓取);Windows 与 Linux 未做
74
+ 运行时确认,若遮罩或 `mix-blend-mode` 在别的内核上有差异,在实现层修,不要靠平台分支
75
+ 删效果。
Binary file
Binary file
package/config.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "deepseek-whale-pendant",
3
+ "title": "DeepSeek 鲸鱼娘 · 亚克力挂件",
4
+ "minHostVersion": "0.1.13",
5
+ "logo": null,
6
+ "screenshots": ["assets/screenshot.png"],
7
+ "platforms": ["macos", "windows", "linux"],
8
+ "size": { "width": 249, "height": 247 },
9
+ "dragMode": "all",
10
+ "permissions": ["script"],
11
+ "network": []
12
+ }
package/index.html ADDED
@@ -0,0 +1,111 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="aidget-surface" content="none" />
7
+ <link rel="stylesheet" href="style.css" />
8
+ <title>DeepSeek 鲸鱼娘 · 亚克力挂件</title>
9
+ </head>
10
+ <body>
11
+ <main class="stage" data-aidget-region="stage">
12
+ <div class="pendant" role="img" aria-label="DeepSeek 鲸鱼娘吃米饭亚克力挂件">
13
+ <div class="pendant-art" aria-hidden="true"></div>
14
+ <div class="pendant-shine" aria-hidden="true">
15
+ <span class="shine-spot"></span>
16
+ <span class="shine-streak"></span>
17
+ </div>
18
+ </div>
19
+ </main>
20
+ <script>
21
+ (() => {
22
+ const stage = document.querySelector('.stage');
23
+ const root = document.documentElement;
24
+ const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
25
+ const REST = { x: 0.3, y: 0.2 };
26
+ const IDLE_GLOW = 0.42;
27
+ const clamp = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
28
+
29
+ let target = { ...REST };
30
+ let pos = { ...REST };
31
+ let glow = { value: 0, target: IDLE_GLOW };
32
+ let running = false;
33
+ let previousTime = null;
34
+
35
+ function paint() {
36
+ root.style.setProperty('--mx', `${(pos.x * 100).toFixed(2)}%`);
37
+ root.style.setProperty('--my', `${(pos.y * 100).toFixed(2)}%`);
38
+ root.style.setProperty('--shine', glow.value.toFixed(3));
39
+ }
40
+
41
+ function tick(timestamp) {
42
+ const elapsed =
43
+ previousTime === null
44
+ ? 1000 / 60
45
+ : Math.min(100, Math.max(0, timestamp - previousTime));
46
+ previousTime = timestamp;
47
+ const ease = reduceMotion.matches ? 1 : 1 - Math.pow(0.82, elapsed / (1000 / 60));
48
+ pos.x += (target.x - pos.x) * ease;
49
+ pos.y += (target.y - pos.y) * ease;
50
+ glow.value +=
51
+ (glow.target - glow.value) *
52
+ (reduceMotion.matches ? 1 : 1 - Math.pow(0.88, elapsed / (1000 / 60)));
53
+ paint();
54
+ const settled =
55
+ Math.abs(target.x - pos.x) < 0.002 &&
56
+ Math.abs(target.y - pos.y) < 0.002 &&
57
+ Math.abs(glow.target - glow.value) < 0.004;
58
+ if (settled) {
59
+ pos = { ...target };
60
+ glow.value = glow.target;
61
+ paint();
62
+ running = false;
63
+ previousTime = null;
64
+ return;
65
+ }
66
+ window.aidget.requestAnimationFrame(tick);
67
+ }
68
+
69
+ function wake() {
70
+ if (!running) {
71
+ running = true;
72
+ window.aidget.requestAnimationFrame(tick);
73
+ }
74
+ }
75
+
76
+ function follow(x, y) {
77
+ const rect = stage.getBoundingClientRect();
78
+ if (!rect.width || !rect.height) return;
79
+ target.x = clamp((x - rect.left) / rect.width, 0, 1);
80
+ target.y = clamp((y - rect.top) / rect.height, 0, 1);
81
+ glow.target = 1;
82
+ wake();
83
+ }
84
+
85
+ function rest() {
86
+ target = { ...REST };
87
+ glow.target = IDLE_GLOW;
88
+ wake();
89
+ }
90
+
91
+ window.aidget.onPointer((event) => {
92
+ if (event.type === 'leave') {
93
+ rest();
94
+ return;
95
+ }
96
+ follow(event.x, event.y);
97
+ });
98
+ document.addEventListener('visibilitychange', () => {
99
+ if (document.hidden) rest();
100
+ });
101
+
102
+ paint();
103
+ wake();
104
+
105
+ if (window.aidget && typeof window.aidget.ready === 'function') {
106
+ window.aidget.ready();
107
+ }
108
+ })();
109
+ </script>
110
+ </body>
111
+ </html>
package/package.json CHANGED
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "@aidget-community/deepseek-whale-pendant",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.1",
4
+ "description": "透明桌面上的 DeepSeek 鲸鱼娘亚克力挂件,半透明玻璃刀模与跟随鼠标的扫光。",
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "micooz",
8
+ "url": "https://github.com/micooz"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/aidget-ai/widgets.git",
13
+ "directory": "packages/deepseek-whale-pendant"
14
+ },
15
+ "files": [
16
+ "config.json",
17
+ "index.html",
18
+ "style.css",
19
+ "agents.md",
20
+ "assets"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ }
25
+ }
package/style.css ADDED
@@ -0,0 +1,103 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --sil: url(assets/pendant.png);
4
+ --mx: 30%;
5
+ --my: 20%;
6
+ --shine: 0;
7
+ }
8
+
9
+ * {
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ html,
14
+ body {
15
+ width: 100%;
16
+ height: 100%;
17
+ margin: 0;
18
+ overflow: hidden;
19
+ background: transparent;
20
+ }
21
+
22
+ .stage {
23
+ position: relative;
24
+ width: 100%;
25
+ height: 100%;
26
+ min-height: 120px;
27
+ user-select: none;
28
+ -webkit-user-select: none;
29
+ }
30
+
31
+ .pendant {
32
+ position: absolute;
33
+ inset: 0;
34
+ isolation: isolate;
35
+ }
36
+
37
+ .pendant-art {
38
+ position: absolute;
39
+ inset: 0;
40
+ z-index: 1;
41
+ background-image: var(--sil);
42
+ background-repeat: no-repeat;
43
+ background-position: center;
44
+ background-size: contain;
45
+ filter: drop-shadow(0 2px 3px rgb(14 40 64 / 30%));
46
+ }
47
+
48
+ .pendant-shine {
49
+ position: absolute;
50
+ inset: 0;
51
+ z-index: 2;
52
+ opacity: var(--shine);
53
+ mix-blend-mode: screen;
54
+ pointer-events: none;
55
+ -webkit-mask-image: var(--sil);
56
+ mask-image: var(--sil);
57
+ -webkit-mask-repeat: no-repeat;
58
+ mask-repeat: no-repeat;
59
+ -webkit-mask-position: center;
60
+ mask-position: center;
61
+ -webkit-mask-size: contain;
62
+ mask-size: contain;
63
+ }
64
+
65
+ .shine-spot,
66
+ .shine-streak {
67
+ position: absolute;
68
+ left: var(--mx);
69
+ top: var(--my);
70
+ }
71
+
72
+ .shine-spot {
73
+ width: 78%;
74
+ height: 78%;
75
+ transform: translate(-50%, -50%);
76
+ background-image: radial-gradient(
77
+ circle,
78
+ rgb(255 255 255 / 24%) 0%,
79
+ rgb(255 255 255 / 6%) 38%,
80
+ rgb(255 255 255 / 0%) 64%
81
+ );
82
+ }
83
+
84
+ .shine-streak {
85
+ width: 190%;
86
+ height: 17%;
87
+ transform: translate(-50%, -50%) rotate(-26deg);
88
+ background-image: linear-gradient(
89
+ 90deg,
90
+ rgb(255 255 255 / 0%) 0%,
91
+ rgb(255 255 255 / 30%) 36%,
92
+ rgb(255 255 255 / 58%) 50%,
93
+ rgb(255 255 255 / 30%) 64%,
94
+ rgb(255 255 255 / 0%) 100%
95
+ );
96
+ filter: blur(3px);
97
+ }
98
+
99
+ @media (prefers-reduced-motion: reduce) {
100
+ .shine-streak {
101
+ filter: blur(4px);
102
+ }
103
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.