feat(embed,viewer): UI-01 complete carousel, loader config and accessibility

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-21 18:55:15 +08:00
parent 1f67b7c818
commit ddf26a177f
22 changed files with 2274 additions and 326 deletions
+16 -5
View File
@@ -1,20 +1,31 @@
// apps/viewer/src/embed/postMessage.ts —— 嵌入 iframe ↔ 宿主 loader 消息通道
// (P4b Task 4)。协议与白名单模型见 packages/embed-loader(README-embed.md):
// 载荷恒为 {photoliveEmbed: true, type: 'resize'|'collapse'|..., ...}。
// (P4b Task 4;UI-01 扩展 config/destroy)。协议与白名单模型见
// packages/embed-loader(README-embed.md):载荷恒为
// {photoliveEmbed: true, type: 'resize'|'collapse'|'config'|'destroy'|...}。
//
// 上行(iframe → 宿主):resize(高度)/ collapse(收起,宿主侧高度 0 + 把手)。
// 上行(iframe → 宿主):
// resize(高度)/ collapse(用户收起,宿主侧高度 0 + 把手);
// config(后台设置动态应用,UI-01:configVersion + settings 归一全集,
// 宿主侧再验证一次——仅 position/size/offsetX/offsetBottom/zIndex/
// collapsedDefault 等白名单字段,不传任意 CSS/HTML);
// destroy(服务端终止展示:槽 404/410/停用/解绑——宿主移除卡片+把手,
// 与「用户收起」语义区分,§5.3)。
// 目标 origin 尽量收敛到 document.referrer 的源(loader 的 iframe 带
// no-referrer-when-downgrade,宿主正常配置下可得完整来源 URL);referrer 被宿主
// 隐去时退回 '*'——载荷仅含高度/收起意图,无敏感数据,且宿主侧 loader 以
// 隐去时退回 '*'——载荷仅含展示意图/公开设置,无敏感数据,且宿主侧 loader 以
// 「event.source === 已登记 iframe && event.origin === iframe 源」双重严格校验,
// 通配目标不构成越权面。
//
// 下行(宿主 → iframe):expand(把手点击恢复)——只认 event.source ===
// window.parent 且载荷形状匹配(source 校验即充分:宿主页内任意脚本无法伪造
// parent 窗口引用;loader 对上行另有 origin 全等白名单)。
import type { EmbedSlotSettings } from '../api/client';
export type EmbedUpMessage =
| { photoliveEmbed: true; type: 'resize'; height: number }
| { photoliveEmbed: true; type: 'collapse' };
| { photoliveEmbed: true; type: 'collapse' }
| { photoliveEmbed: true; type: 'config'; configVersion: number; settings: EmbedSlotSettings }
| { photoliveEmbed: true; type: 'destroy' };
/** 宿主源(referrer 推导);取不到(被隐去/直接打开)为 null。 */
export function embedParentOrigin(): string | null {