@@ -23,7 +23,7 @@ import { Surface } from "./index";
2323import type { SurfaceLevel , SurfaceRadius , SurfaceTag } from "./index" ;
2424
2525/** 契约名单:与 `Surface.css` 的规则一一对应(改名单必须同时改 CSS 与测试) */
26- const LEVELS : readonly SurfaceLevel [ ] = [ "sunken" , "canvas" , "surface" , "raised" ] ;
26+ const LEVELS : readonly SurfaceLevel [ ] = [ "sunken" , "canvas" , "surface" , "raised" , "none" ] ;
2727const RADIUS : readonly SurfaceRadius [ ] = [ "stamp" , "control" , "panel" , "overlay" , "pill" ] ;
2828const TAGS : ReadonlyArray < readonly [ SurfaceTag , string ] > = [
2929 [ "div" , "DIV" ] , [ "section" , "SECTION" ] , [ "article" , "ARTICLE" ] , [ "aside" , "ASIDE" ] , [ "li" , "LI" ] ,
@@ -61,7 +61,7 @@ describe("Surface 默认契约", () => {
6161} ) ;
6262
6363describe ( "Surface 四档底 / 五档圆角映射到类" , ( ) => {
64- it ( "4 档 level 各有对应类(sunken 输入槽 · canvas 纸 · surface 卡面 · raised 弹层)" , ( ) => {
64+ it ( "5 档 level 各有对应类(sunken 输入槽 · canvas 纸 · surface 卡面 · raised 弹层 · none 只出边框 )" , ( ) => {
6565 for ( const level of LEVELS ) {
6666 const cls = classesOf ( render ( < Surface level = { level } > x</ Surface > ) . container ) ;
6767 expect ( cls , `档位 ${ level } ` ) . toContain ( `ed-surface--${ level } ` ) ;
@@ -154,6 +154,35 @@ describe("Surface 语义与透传", () => {
154154 } ) ;
155155} ) ;
156156
157+ describe ( "Surface 受控槽(批 7 T7:`html` / `domId` —— 只开属性级的两个口,**不开 `...rest`**)" , ( ) => {
158+ it ( "`html` 走 `dangerouslySetInnerHTML`:宿主的 innerHTML 含该串,且**不**渲染 children" , ( ) => {
159+ const { container } = render ( < Surface html = { '<p class="x">已渲染串</p>' } /> ) ;
160+ expect ( root ( container ) . innerHTML ) . toBe ( '<p class="x">已渲染串</p>' ) ;
161+ expect ( root ( container ) . querySelector ( "p" ) ?. className ) . toBe ( "x" ) ;
162+ } ) ;
163+
164+ it ( "`html` 与面本身的正交性:类名/圆角档照旧,`html` 不吞掉面的契约" , ( ) => {
165+ const cls = classesOf ( render ( < Surface level = "none" radius = "panel" html = "<b>k</b>" /> ) . container ) ;
166+ expect ( cls ) . toContain ( "ed-surface--none" ) ;
167+ expect ( cls ) . toContain ( "ed-surface--r-panel" ) ;
168+ } ) ;
169+
170+ it ( "`domId` 落到宿主的 `id` ⇒ `document.getElementById` 找得到(锚点跳转的落点)" , ( ) => {
171+ render ( < Surface domId = "anchor-x" > x</ Surface > ) ;
172+ expect ( document . getElementById ( "anchor-x" ) ?. textContent ) . toBe ( "x" ) ;
173+ } ) ;
174+
175+ it ( "`domId` 不给时不产生 `id` 属性(不留 `id=\"undefined\"`)" , ( ) => {
176+ expect ( root ( render ( < Surface > x</ Surface > ) . container ) . hasAttribute ( "id" ) ) . toBe ( false ) ;
177+ } ) ;
178+
179+ it ( "反例守门:`...rest` 没开 —— 未知属性既不被解构也不被渲染(编译期那一半由 tsc 探针 V2 守)" , ( ) => {
180+ const stray = { "data-foo" : "1" } ;
181+ const { container } = render ( < Surface { ...stray } > x</ Surface > ) ;
182+ expect ( root ( container ) . hasAttribute ( "data-foo" ) ) . toBe ( false ) ;
183+ } ) ;
184+ } ) ;
185+
157186describe ( "Surface 反例守门(批 6 要一处改对所有地方)" , ( ) => {
158187 it ( "底 / 边框 / 圆角 / 阴影 / 内边距 / 位移**只走类**,绝不落内联 style" , ( ) => {
159188 const el = root (
0 commit comments