eis-ui-render 0.34.3 → 0.35.0
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/README.md +411 -18
- package/THIRD-PARTY-NOTICES.md +127 -0
- package/dist/THIRD-PARTY-LICENSES.txt +429 -0
- package/dist/contract.d.ts +299 -0
- package/dist/index.d.ts +42 -5
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +0 -15
- package/dist/index.js.map +1 -1
- package/dist/sbom.cdx.json +338 -0
- package/dist/static/all.css +2 -39
- package/dist/static/font.css +2 -8
- package/docs/BUILT-IN-PHRASES.md +79 -0
- package/docs/SUPPORTED-PROPS.md +422 -0
- package/docs/SUPPORTED-VIEWS.md +140 -0
- package/meta.schema.json +494 -0
- package/package.json +113 -73
- package/static/all.css +4 -22
- package/static/all.css.map +1 -1
- package/dist/UIRender.d.ts +0 -43
- package/dist/static/all.css.map +0 -1
- package/dist/static/fonts/icons/fonts/iconsOpenL.eot +0 -0
- package/dist/static/fonts/icons/fonts/iconsOpenL.svg +0 -95
- package/dist/static/fonts/icons/fonts/iconsOpenL.ttf +0 -0
- package/dist/static/fonts/icons/fonts/iconsOpenL.woff +0 -0
- package/dist/static/images/diamonds-dimmed-flipped.png +0 -0
- package/dist/static/images/diamonds-dimmed.png +0 -0
- package/dist/static/images/diamonds.png +0 -0
- package/dist/static/images/flags/ad.svg +0 -150
- package/dist/static/images/flags/ae.svg +0 -6
- package/dist/static/images/flags/af.svg +0 -81
- package/dist/static/images/flags/ag.svg +0 -14
- package/dist/static/images/flags/ai.svg +0 -767
- package/dist/static/images/flags/al.svg +0 -5
- package/dist/static/images/flags/am.svg +0 -5
- package/dist/static/images/flags/ao.svg +0 -13
- package/dist/static/images/flags/aq.svg +0 -6
- package/dist/static/images/flags/ar.svg +0 -31
- package/dist/static/images/flags/as.svg +0 -33
- package/dist/static/images/flags/at.svg +0 -6
- package/dist/static/images/flags/au.svg +0 -9
- package/dist/static/images/flags/aw.svg +0 -186
- package/dist/static/images/flags/ax.svg +0 -18
- package/dist/static/images/flags/az.svg +0 -8
- package/dist/static/images/flags/ba.svg +0 -12
- package/dist/static/images/flags/bb.svg +0 -6
- package/dist/static/images/flags/bd.svg +0 -4
- package/dist/static/images/flags/be.svg +0 -7
- package/dist/static/images/flags/bf.svg +0 -7
- package/dist/static/images/flags/bg.svg +0 -7
- package/dist/static/images/flags/bh.svg +0 -11
- package/dist/static/images/flags/bi.svg +0 -15
- package/dist/static/images/flags/bj.svg +0 -14
- package/dist/static/images/flags/bl.svg +0 -7
- package/dist/static/images/flags/bm.svg +0 -98
- package/dist/static/images/flags/bn.svg +0 -36
- package/dist/static/images/flags/bo.svg +0 -676
- package/dist/static/images/flags/bq.svg +0 -5
- package/dist/static/images/flags/br.svg +0 -45
- package/dist/static/images/flags/bs.svg +0 -13
- package/dist/static/images/flags/bt.svg +0 -89
- package/dist/static/images/flags/bv.svg +0 -13
- package/dist/static/images/flags/bw.svg +0 -7
- package/dist/static/images/flags/by.svg +0 -20
- package/dist/static/images/flags/bz.svg +0 -145
- package/dist/static/images/flags/ca.svg +0 -4
- package/dist/static/images/flags/cc.svg +0 -19
- package/dist/static/images/flags/cd.svg +0 -5
- package/dist/static/images/flags/cf.svg +0 -15
- package/dist/static/images/flags/cg.svg +0 -12
- package/dist/static/images/flags/ch.svg +0 -9
- package/dist/static/images/flags/ci.svg +0 -7
- package/dist/static/images/flags/ck.svg +0 -9
- package/dist/static/images/flags/cl.svg +0 -13
- package/dist/static/images/flags/cm.svg +0 -15
- package/dist/static/images/flags/cn.svg +0 -11
- package/dist/static/images/flags/co.svg +0 -7
- package/dist/static/images/flags/cr.svg +0 -7
- package/dist/static/images/flags/cu.svg +0 -13
- package/dist/static/images/flags/cv.svg +0 -13
- package/dist/static/images/flags/cw.svg +0 -14
- package/dist/static/images/flags/cx.svg +0 -15
- package/dist/static/images/flags/cy.svg +0 -6
- package/dist/static/images/flags/cz.svg +0 -12
- package/dist/static/images/flags/de.svg +0 -5
- package/dist/static/images/flags/dj.svg +0 -13
- package/dist/static/images/flags/dk.svg +0 -5
- package/dist/static/images/flags/dm.svg +0 -152
- package/dist/static/images/flags/do.svg +0 -6745
- package/dist/static/images/flags/dz.svg +0 -5
- package/dist/static/images/flags/ec.svg +0 -138
- package/dist/static/images/flags/ee.svg +0 -7
- package/dist/static/images/flags/eg.svg +0 -38
- package/dist/static/images/flags/eh.svg +0 -15
- package/dist/static/images/flags/el.svg +0 -22
- package/dist/static/images/flags/en.svg +0 -15
- package/dist/static/images/flags/er.svg +0 -8
- package/dist/static/images/flags/es-ct.svg +0 -4
- package/dist/static/images/flags/es.svg +0 -544
- package/dist/static/images/flags/et.svg +0 -14
- package/dist/static/images/flags/eu.svg +0 -28
- package/dist/static/images/flags/fa.svg +0 -219
- package/dist/static/images/flags/fi.svg +0 -5
- package/dist/static/images/flags/fj.svg +0 -120
- package/dist/static/images/flags/fk.svg +0 -89
- package/dist/static/images/flags/fm.svg +0 -11
- package/dist/static/images/flags/fo.svg +0 -12
- package/dist/static/images/flags/fr.svg +0 -7
- package/dist/static/images/flags/ga.svg +0 -7
- package/dist/static/images/flags/gb-eng.svg +0 -5
- package/dist/static/images/flags/gb-nir.svg +0 -131
- package/dist/static/images/flags/gb-sct.svg +0 -4
- package/dist/static/images/flags/gb-wls.svg +0 -9
- package/dist/static/images/flags/gb.svg +0 -15
- package/dist/static/images/flags/gd.svg +0 -27
- package/dist/static/images/flags/ge.svg +0 -6
- package/dist/static/images/flags/gf.svg +0 -5
- package/dist/static/images/flags/gg.svg +0 -9
- package/dist/static/images/flags/gh.svg +0 -6
- package/dist/static/images/flags/gi.svg +0 -32
- package/dist/static/images/flags/gl.svg +0 -4
- package/dist/static/images/flags/gm.svg +0 -14
- package/dist/static/images/flags/gn.svg +0 -7
- package/dist/static/images/flags/gp.svg +0 -7
- package/dist/static/images/flags/gq.svg +0 -23
- package/dist/static/images/flags/gr.svg +0 -22
- package/dist/static/images/flags/gs.svg +0 -201
- package/dist/static/images/flags/gt.svg +0 -204
- package/dist/static/images/flags/gu.svg +0 -39
- package/dist/static/images/flags/gw.svg +0 -13
- package/dist/static/images/flags/gy.svg +0 -9
- package/dist/static/images/flags/he.svg +0 -14
- package/dist/static/images/flags/hk.svg +0 -30
- package/dist/static/images/flags/hm.svg +0 -9
- package/dist/static/images/flags/hn.svg +0 -18
- package/dist/static/images/flags/hr.svg +0 -58
- package/dist/static/images/flags/ht.svg +0 -116
- package/dist/static/images/flags/hu.svg +0 -7
- package/dist/static/images/flags/id.svg +0 -6
- package/dist/static/images/flags/ie.svg +0 -7
- package/dist/static/images/flags/il.svg +0 -14
- package/dist/static/images/flags/im.svg +0 -36
- package/dist/static/images/flags/in.svg +0 -25
- package/dist/static/images/flags/io.svg +0 -138
- package/dist/static/images/flags/iq.svg +0 -10
- package/dist/static/images/flags/ir.svg +0 -219
- package/dist/static/images/flags/is.svg +0 -12
- package/dist/static/images/flags/it.svg +0 -7
- package/dist/static/images/flags/ja.svg +0 -11
- package/dist/static/images/flags/je.svg +0 -29
- package/dist/static/images/flags/jm.svg +0 -8
- package/dist/static/images/flags/jo.svg +0 -16
- package/dist/static/images/flags/jp.svg +0 -11
- package/dist/static/images/flags/ke.svg +0 -23
- package/dist/static/images/flags/kg.svg +0 -15
- package/dist/static/images/flags/kh.svg +0 -61
- package/dist/static/images/flags/ki.svg +0 -36
- package/dist/static/images/flags/km.svg +0 -16
- package/dist/static/images/flags/kn.svg +0 -14
- package/dist/static/images/flags/ko.svg +0 -24
- package/dist/static/images/flags/kp.svg +0 -15
- package/dist/static/images/flags/kr.svg +0 -24
- package/dist/static/images/flags/kw.svg +0 -13
- package/dist/static/images/flags/ky.svg +0 -63
- package/dist/static/images/flags/kz.svg +0 -23
- package/dist/static/images/flags/la.svg +0 -12
- package/dist/static/images/flags/lb.svg +0 -15
- package/dist/static/images/flags/lc.svg +0 -8
- package/dist/static/images/flags/li.svg +0 -43
- package/dist/static/images/flags/lk.svg +0 -22
- package/dist/static/images/flags/lr.svg +0 -14
- package/dist/static/images/flags/ls.svg +0 -8
- package/dist/static/images/flags/lt.svg +0 -7
- package/dist/static/images/flags/lu.svg +0 -5
- package/dist/static/images/flags/lv.svg +0 -6
- package/dist/static/images/flags/ly.svg +0 -13
- package/dist/static/images/flags/ma.svg +0 -4
- package/dist/static/images/flags/mc.svg +0 -6
- package/dist/static/images/flags/md.svg +0 -70
- package/dist/static/images/flags/me.svg +0 -116
- package/dist/static/images/flags/mf.svg +0 -7
- package/dist/static/images/flags/mg.svg +0 -7
- package/dist/static/images/flags/mh.svg +0 -7
- package/dist/static/images/flags/mk.svg +0 -5
- package/dist/static/images/flags/ml.svg +0 -7
- package/dist/static/images/flags/mm.svg +0 -16
- package/dist/static/images/flags/mn.svg +0 -13
- package/dist/static/images/flags/mo.svg +0 -9
- package/dist/static/images/flags/mp.svg +0 -86
- package/dist/static/images/flags/mq.svg +0 -7
- package/dist/static/images/flags/mr.svg +0 -6
- package/dist/static/images/flags/ms.svg +0 -39
- package/dist/static/images/flags/mt.svg +0 -49
- package/dist/static/images/flags/mu.svg +0 -8
- package/dist/static/images/flags/mv.svg +0 -6
- package/dist/static/images/flags/mw.svg +0 -10
- package/dist/static/images/flags/mx.svg +0 -382
- package/dist/static/images/flags/my.svg +0 -15
- package/dist/static/images/flags/mz.svg +0 -21
- package/dist/static/images/flags/na.svg +0 -16
- package/dist/static/images/flags/nc.svg +0 -7
- package/dist/static/images/flags/ne.svg +0 -6
- package/dist/static/images/flags/nf.svg +0 -9
- package/dist/static/images/flags/ng.svg +0 -6
- package/dist/static/images/flags/ni.svg +0 -129
- package/dist/static/images/flags/nl.svg +0 -7
- package/dist/static/images/flags/no.svg +0 -7
- package/dist/static/images/flags/np.svg +0 -14
- package/dist/static/images/flags/nr.svg +0 -12
- package/dist/static/images/flags/nu.svg +0 -26
- package/dist/static/images/flags/nz.svg +0 -41
- package/dist/static/images/flags/om.svg +0 -115
- package/dist/static/images/flags/pa.svg +0 -14
- package/dist/static/images/flags/pe.svg +0 -244
- package/dist/static/images/flags/pf.svg +0 -19
- package/dist/static/images/flags/pg.svg +0 -9
- package/dist/static/images/flags/ph.svg +0 -9
- package/dist/static/images/flags/pk.svg +0 -15
- package/dist/static/images/flags/pl.svg +0 -6
- package/dist/static/images/flags/pm.svg +0 -7
- package/dist/static/images/flags/pn.svg +0 -62
- package/dist/static/images/flags/pr.svg +0 -13
- package/dist/static/images/flags/ps.svg +0 -15
- package/dist/static/images/flags/pt.svg +0 -57
- package/dist/static/images/flags/pw.svg +0 -11
- package/dist/static/images/flags/py.svg +0 -157
- package/dist/static/images/flags/qa.svg +0 -4
- package/dist/static/images/flags/re.svg +0 -7
- package/dist/static/images/flags/ro.svg +0 -7
- package/dist/static/images/flags/rs.svg +0 -292
- package/dist/static/images/flags/ru.svg +0 -7
- package/dist/static/images/flags/rw.svg +0 -13
- package/dist/static/images/flags/sa.svg +0 -26
- package/dist/static/images/flags/sb.svg +0 -13
- package/dist/static/images/flags/sc.svg +0 -14
- package/dist/static/images/flags/sd.svg +0 -13
- package/dist/static/images/flags/se.svg +0 -16
- package/dist/static/images/flags/sg.svg +0 -13
- package/dist/static/images/flags/sh.svg +0 -74
- package/dist/static/images/flags/si.svg +0 -18
- package/dist/static/images/flags/sj.svg +0 -7
- package/dist/static/images/flags/sk.svg +0 -9
- package/dist/static/images/flags/sl.svg +0 -7
- package/dist/static/images/flags/sm.svg +0 -91
- package/dist/static/images/flags/sn.svg +0 -8
- package/dist/static/images/flags/so.svg +0 -11
- package/dist/static/images/flags/sr.svg +0 -6
- package/dist/static/images/flags/ss.svg +0 -8
- package/dist/static/images/flags/st.svg +0 -16
- package/dist/static/images/flags/sv.svg +0 -601
- package/dist/static/images/flags/sx.svg +0 -56
- package/dist/static/images/flags/sy.svg +0 -6
- package/dist/static/images/flags/sz.svg +0 -45
- package/dist/static/images/flags/tc.svg +0 -67
- package/dist/static/images/flags/td.svg +0 -7
- package/dist/static/images/flags/tf.svg +0 -15
- package/dist/static/images/flags/tg.svg +0 -14
- package/dist/static/images/flags/th.svg +0 -7
- package/dist/static/images/flags/tj.svg +0 -22
- package/dist/static/images/flags/tk.svg +0 -5
- package/dist/static/images/flags/tl.svg +0 -13
- package/dist/static/images/flags/tm.svg +0 -206
- package/dist/static/images/flags/tn.svg +0 -13
- package/dist/static/images/flags/to.svg +0 -10
- package/dist/static/images/flags/tr.svg +0 -8
- package/dist/static/images/flags/tt.svg +0 -5
- package/dist/static/images/flags/tv.svg +0 -27
- package/dist/static/images/flags/tw.svg +0 -14
- package/dist/static/images/flags/tz.svg +0 -13
- package/dist/static/images/flags/ua.svg +0 -6
- package/dist/static/images/flags/ug.svg +0 -30
- package/dist/static/images/flags/um.svg +0 -15
- package/dist/static/images/flags/un.svg +0 -16
- package/dist/static/images/flags/us.svg +0 -10
- package/dist/static/images/flags/uy.svg +0 -28
- package/dist/static/images/flags/uz.svg +0 -30
- package/dist/static/images/flags/va.svg +0 -479
- package/dist/static/images/flags/vc.svg +0 -8
- package/dist/static/images/flags/ve.svg +0 -26
- package/dist/static/images/flags/vg.svg +0 -127
- package/dist/static/images/flags/vi.svg +0 -28
- package/dist/static/images/flags/vn.svg +0 -11
- package/dist/static/images/flags/vu.svg +0 -18
- package/dist/static/images/flags/wf.svg +0 -7
- package/dist/static/images/flags/ws.svg +0 -7
- package/dist/static/images/flags/xk.svg +0 -16
- package/dist/static/images/flags/ye.svg +0 -7
- package/dist/static/images/flags/yi.svg +0 -12
- package/dist/static/images/flags/yt.svg +0 -7
- package/dist/static/images/flags/za.svg +0 -17
- package/dist/static/images/flags/zh-HK.svg +0 -30
- package/dist/static/images/flags/zh.svg +0 -11
- package/dist/static/images/flags/zm.svg +0 -27
- package/dist/static/images/flags/zw.svg +0 -21
- package/dist/static/images/flags.png +0 -0
- package/dist/static/images/home.jpg +0 -0
- package/dist/static/images/logo.svg +0 -1
- package/dist/static/images/showIf.png +0 -0
- package/dist/static/images/ui-architecture.png +0 -0
- package/dist/static/images/ui-render-inspect.png +0 -0
- package/dist/static/images/ui-render-version.png +0 -0
- package/static/images/diamonds-dimmed-flipped.png +0 -0
- package/static/images/diamonds-dimmed.png +0 -0
- package/static/images/diamonds.png +0 -0
- package/static/images/flags/ad.svg +0 -150
- package/static/images/flags/ae.svg +0 -6
- package/static/images/flags/af.svg +0 -81
- package/static/images/flags/ag.svg +0 -14
- package/static/images/flags/ai.svg +0 -767
- package/static/images/flags/al.svg +0 -5
- package/static/images/flags/am.svg +0 -5
- package/static/images/flags/ao.svg +0 -13
- package/static/images/flags/aq.svg +0 -6
- package/static/images/flags/ar.svg +0 -31
- package/static/images/flags/as.svg +0 -33
- package/static/images/flags/at.svg +0 -6
- package/static/images/flags/au.svg +0 -9
- package/static/images/flags/aw.svg +0 -186
- package/static/images/flags/ax.svg +0 -18
- package/static/images/flags/az.svg +0 -8
- package/static/images/flags/ba.svg +0 -12
- package/static/images/flags/bb.svg +0 -6
- package/static/images/flags/bd.svg +0 -4
- package/static/images/flags/be.svg +0 -7
- package/static/images/flags/bf.svg +0 -7
- package/static/images/flags/bg.svg +0 -7
- package/static/images/flags/bh.svg +0 -11
- package/static/images/flags/bi.svg +0 -15
- package/static/images/flags/bj.svg +0 -14
- package/static/images/flags/bl.svg +0 -7
- package/static/images/flags/bm.svg +0 -98
- package/static/images/flags/bn.svg +0 -36
- package/static/images/flags/bo.svg +0 -676
- package/static/images/flags/bq.svg +0 -5
- package/static/images/flags/br.svg +0 -45
- package/static/images/flags/bs.svg +0 -13
- package/static/images/flags/bt.svg +0 -89
- package/static/images/flags/bv.svg +0 -13
- package/static/images/flags/bw.svg +0 -7
- package/static/images/flags/by.svg +0 -20
- package/static/images/flags/bz.svg +0 -145
- package/static/images/flags/ca.svg +0 -4
- package/static/images/flags/cc.svg +0 -19
- package/static/images/flags/cd.svg +0 -5
- package/static/images/flags/cf.svg +0 -15
- package/static/images/flags/cg.svg +0 -12
- package/static/images/flags/ch.svg +0 -9
- package/static/images/flags/ci.svg +0 -7
- package/static/images/flags/ck.svg +0 -9
- package/static/images/flags/cl.svg +0 -13
- package/static/images/flags/cm.svg +0 -15
- package/static/images/flags/cn.svg +0 -11
- package/static/images/flags/co.svg +0 -7
- package/static/images/flags/cr.svg +0 -7
- package/static/images/flags/cu.svg +0 -13
- package/static/images/flags/cv.svg +0 -13
- package/static/images/flags/cw.svg +0 -14
- package/static/images/flags/cx.svg +0 -15
- package/static/images/flags/cy.svg +0 -6
- package/static/images/flags/cz.svg +0 -12
- package/static/images/flags/de.svg +0 -5
- package/static/images/flags/dj.svg +0 -13
- package/static/images/flags/dk.svg +0 -5
- package/static/images/flags/dm.svg +0 -152
- package/static/images/flags/do.svg +0 -6745
- package/static/images/flags/dz.svg +0 -5
- package/static/images/flags/ec.svg +0 -138
- package/static/images/flags/ee.svg +0 -7
- package/static/images/flags/eg.svg +0 -38
- package/static/images/flags/eh.svg +0 -15
- package/static/images/flags/el.svg +0 -22
- package/static/images/flags/en.svg +0 -15
- package/static/images/flags/er.svg +0 -8
- package/static/images/flags/es-ct.svg +0 -4
- package/static/images/flags/es.svg +0 -544
- package/static/images/flags/et.svg +0 -14
- package/static/images/flags/eu.svg +0 -28
- package/static/images/flags/fa.svg +0 -219
- package/static/images/flags/fi.svg +0 -5
- package/static/images/flags/fj.svg +0 -120
- package/static/images/flags/fk.svg +0 -89
- package/static/images/flags/fm.svg +0 -11
- package/static/images/flags/fo.svg +0 -12
- package/static/images/flags/fr.svg +0 -7
- package/static/images/flags/ga.svg +0 -7
- package/static/images/flags/gb-eng.svg +0 -5
- package/static/images/flags/gb-nir.svg +0 -131
- package/static/images/flags/gb-sct.svg +0 -4
- package/static/images/flags/gb-wls.svg +0 -9
- package/static/images/flags/gb.svg +0 -15
- package/static/images/flags/gd.svg +0 -27
- package/static/images/flags/ge.svg +0 -6
- package/static/images/flags/gf.svg +0 -5
- package/static/images/flags/gg.svg +0 -9
- package/static/images/flags/gh.svg +0 -6
- package/static/images/flags/gi.svg +0 -32
- package/static/images/flags/gl.svg +0 -4
- package/static/images/flags/gm.svg +0 -14
- package/static/images/flags/gn.svg +0 -7
- package/static/images/flags/gp.svg +0 -7
- package/static/images/flags/gq.svg +0 -23
- package/static/images/flags/gr.svg +0 -22
- package/static/images/flags/gs.svg +0 -201
- package/static/images/flags/gt.svg +0 -204
- package/static/images/flags/gu.svg +0 -39
- package/static/images/flags/gw.svg +0 -13
- package/static/images/flags/gy.svg +0 -9
- package/static/images/flags/he.svg +0 -14
- package/static/images/flags/hk.svg +0 -30
- package/static/images/flags/hm.svg +0 -9
- package/static/images/flags/hn.svg +0 -18
- package/static/images/flags/hr.svg +0 -58
- package/static/images/flags/ht.svg +0 -116
- package/static/images/flags/hu.svg +0 -7
- package/static/images/flags/id.svg +0 -6
- package/static/images/flags/ie.svg +0 -7
- package/static/images/flags/il.svg +0 -14
- package/static/images/flags/im.svg +0 -36
- package/static/images/flags/in.svg +0 -25
- package/static/images/flags/io.svg +0 -138
- package/static/images/flags/iq.svg +0 -10
- package/static/images/flags/ir.svg +0 -219
- package/static/images/flags/is.svg +0 -12
- package/static/images/flags/it.svg +0 -7
- package/static/images/flags/ja.svg +0 -11
- package/static/images/flags/je.svg +0 -29
- package/static/images/flags/jm.svg +0 -8
- package/static/images/flags/jo.svg +0 -16
- package/static/images/flags/jp.svg +0 -11
- package/static/images/flags/ke.svg +0 -23
- package/static/images/flags/kg.svg +0 -15
- package/static/images/flags/kh.svg +0 -61
- package/static/images/flags/ki.svg +0 -36
- package/static/images/flags/km.svg +0 -16
- package/static/images/flags/kn.svg +0 -14
- package/static/images/flags/ko.svg +0 -24
- package/static/images/flags/kp.svg +0 -15
- package/static/images/flags/kr.svg +0 -24
- package/static/images/flags/kw.svg +0 -13
- package/static/images/flags/ky.svg +0 -63
- package/static/images/flags/kz.svg +0 -23
- package/static/images/flags/la.svg +0 -12
- package/static/images/flags/lb.svg +0 -15
- package/static/images/flags/lc.svg +0 -8
- package/static/images/flags/li.svg +0 -43
- package/static/images/flags/lk.svg +0 -22
- package/static/images/flags/lr.svg +0 -14
- package/static/images/flags/ls.svg +0 -8
- package/static/images/flags/lt.svg +0 -7
- package/static/images/flags/lu.svg +0 -5
- package/static/images/flags/lv.svg +0 -6
- package/static/images/flags/ly.svg +0 -13
- package/static/images/flags/ma.svg +0 -4
- package/static/images/flags/mc.svg +0 -6
- package/static/images/flags/md.svg +0 -70
- package/static/images/flags/me.svg +0 -116
- package/static/images/flags/mf.svg +0 -7
- package/static/images/flags/mg.svg +0 -7
- package/static/images/flags/mh.svg +0 -7
- package/static/images/flags/mk.svg +0 -5
- package/static/images/flags/ml.svg +0 -7
- package/static/images/flags/mm.svg +0 -16
- package/static/images/flags/mn.svg +0 -13
- package/static/images/flags/mo.svg +0 -9
- package/static/images/flags/mp.svg +0 -86
- package/static/images/flags/mq.svg +0 -7
- package/static/images/flags/mr.svg +0 -6
- package/static/images/flags/ms.svg +0 -39
- package/static/images/flags/mt.svg +0 -49
- package/static/images/flags/mu.svg +0 -8
- package/static/images/flags/mv.svg +0 -6
- package/static/images/flags/mw.svg +0 -10
- package/static/images/flags/mx.svg +0 -382
- package/static/images/flags/my.svg +0 -15
- package/static/images/flags/mz.svg +0 -21
- package/static/images/flags/na.svg +0 -16
- package/static/images/flags/nc.svg +0 -7
- package/static/images/flags/ne.svg +0 -6
- package/static/images/flags/nf.svg +0 -9
- package/static/images/flags/ng.svg +0 -6
- package/static/images/flags/ni.svg +0 -129
- package/static/images/flags/nl.svg +0 -7
- package/static/images/flags/no.svg +0 -7
- package/static/images/flags/np.svg +0 -14
- package/static/images/flags/nr.svg +0 -12
- package/static/images/flags/nu.svg +0 -26
- package/static/images/flags/nz.svg +0 -41
- package/static/images/flags/om.svg +0 -115
- package/static/images/flags/pa.svg +0 -14
- package/static/images/flags/pe.svg +0 -244
- package/static/images/flags/pf.svg +0 -19
- package/static/images/flags/pg.svg +0 -9
- package/static/images/flags/ph.svg +0 -9
- package/static/images/flags/pk.svg +0 -15
- package/static/images/flags/pl.svg +0 -6
- package/static/images/flags/pm.svg +0 -7
- package/static/images/flags/pn.svg +0 -62
- package/static/images/flags/pr.svg +0 -13
- package/static/images/flags/ps.svg +0 -15
- package/static/images/flags/pt.svg +0 -57
- package/static/images/flags/pw.svg +0 -11
- package/static/images/flags/py.svg +0 -157
- package/static/images/flags/qa.svg +0 -4
- package/static/images/flags/re.svg +0 -7
- package/static/images/flags/ro.svg +0 -7
- package/static/images/flags/rs.svg +0 -292
- package/static/images/flags/ru.svg +0 -7
- package/static/images/flags/rw.svg +0 -13
- package/static/images/flags/sa.svg +0 -26
- package/static/images/flags/sb.svg +0 -13
- package/static/images/flags/sc.svg +0 -14
- package/static/images/flags/sd.svg +0 -13
- package/static/images/flags/se.svg +0 -16
- package/static/images/flags/sg.svg +0 -13
- package/static/images/flags/sh.svg +0 -74
- package/static/images/flags/si.svg +0 -18
- package/static/images/flags/sj.svg +0 -7
- package/static/images/flags/sk.svg +0 -9
- package/static/images/flags/sl.svg +0 -7
- package/static/images/flags/sm.svg +0 -91
- package/static/images/flags/sn.svg +0 -8
- package/static/images/flags/so.svg +0 -11
- package/static/images/flags/sr.svg +0 -6
- package/static/images/flags/ss.svg +0 -8
- package/static/images/flags/st.svg +0 -16
- package/static/images/flags/sv.svg +0 -601
- package/static/images/flags/sx.svg +0 -56
- package/static/images/flags/sy.svg +0 -6
- package/static/images/flags/sz.svg +0 -45
- package/static/images/flags/tc.svg +0 -67
- package/static/images/flags/td.svg +0 -7
- package/static/images/flags/tf.svg +0 -15
- package/static/images/flags/tg.svg +0 -14
- package/static/images/flags/th.svg +0 -7
- package/static/images/flags/tj.svg +0 -22
- package/static/images/flags/tk.svg +0 -5
- package/static/images/flags/tl.svg +0 -13
- package/static/images/flags/tm.svg +0 -206
- package/static/images/flags/tn.svg +0 -13
- package/static/images/flags/to.svg +0 -10
- package/static/images/flags/tr.svg +0 -8
- package/static/images/flags/tt.svg +0 -5
- package/static/images/flags/tv.svg +0 -27
- package/static/images/flags/tw.svg +0 -14
- package/static/images/flags/tz.svg +0 -13
- package/static/images/flags/ua.svg +0 -6
- package/static/images/flags/ug.svg +0 -30
- package/static/images/flags/um.svg +0 -15
- package/static/images/flags/un.svg +0 -16
- package/static/images/flags/us.svg +0 -10
- package/static/images/flags/uy.svg +0 -28
- package/static/images/flags/uz.svg +0 -30
- package/static/images/flags/va.svg +0 -479
- package/static/images/flags/vc.svg +0 -8
- package/static/images/flags/ve.svg +0 -26
- package/static/images/flags/vg.svg +0 -127
- package/static/images/flags/vi.svg +0 -28
- package/static/images/flags/vn.svg +0 -11
- package/static/images/flags/vu.svg +0 -18
- package/static/images/flags/wf.svg +0 -7
- package/static/images/flags/ws.svg +0 -7
- package/static/images/flags/xk.svg +0 -16
- package/static/images/flags/ye.svg +0 -7
- package/static/images/flags/yi.svg +0 -12
- package/static/images/flags/yt.svg +0 -7
- package/static/images/flags/za.svg +0 -17
- package/static/images/flags/zh-HK.svg +0 -30
- package/static/images/flags/zh.svg +0 -11
- package/static/images/flags/zm.svg +0 -27
- package/static/images/flags/zw.svg +0 -21
- package/static/images/flags.png +0 -0
- package/static/images/home.jpg +0 -0
- package/static/images/logo.svg +0 -1
- package/static/images/showIf.png +0 -0
- package/static/images/ui-architecture.png +0 -0
- package/static/images/ui-render-inspect.png +0 -0
- package/static/images/ui-render-version.png +0 -0
package/dist/static/font.css
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
src: url('./fonts/icons/fonts/iconsOpenL.eot?pn33hl');
|
|
4
|
-
src: url('./fonts/icons/fonts/iconsOpenL.eot?pn33hl#iefix') format('embedded-opentype'), url('./fonts/icons/fonts/iconsOpenL.ttf?pn33hl') format('truetype'), url('./fonts/icons/fonts/iconsOpenL.woff?pn33hl') format('woff'), url('./fonts/icons/fonts/iconsOpenL.svg?pn33hl#iconsOpenL') format('svg');
|
|
5
|
-
font-weight: normal;
|
|
6
|
-
font-style: normal;
|
|
7
|
-
font-display: block;
|
|
8
|
-
}
|
|
1
|
+
/* Re-export: the real stylesheet and its assets ship once in the package root static/ folder. */
|
|
2
|
+
@import '../../static/font.css';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
GENERATED FILE — DO NOT EDIT. Run `npm run docs:phrases` to regenerate.
|
|
3
|
+
The ids, English texts and places come from BUILT_IN_PHRASES in src/core/utils/phrases.ts.
|
|
4
|
+
Generator: scripts/generate-phrase-reference.js.
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Built-in phrases
|
|
8
|
+
|
|
9
|
+
The texts UI Render writes itself, as opposed to the labels a `meta.json` gives it. Your `translate`
|
|
10
|
+
prop is asked for each as `ui-render:<ID>`: register a `ui-render` namespace in your i18n, with the
|
|
11
|
+
ids below as its keys. The README's section "Translating the built-in texts (consumer)" shows an
|
|
12
|
+
example.
|
|
13
|
+
|
|
14
|
+
Where your `translate` answers with the key itself (`ui-render:TOTAL`), with the key without its
|
|
15
|
+
namespace (`TOTAL`), or with an empty string, UI Render shows the English text below. Without a
|
|
16
|
+
`ui-render` namespace, every one of them shows in English.
|
|
17
|
+
|
|
18
|
+
A `{name}` in a text is a placeholder that UI Render fills after your translation comes back:
|
|
19
|
+
keep it in single braces where your translation needs the value.
|
|
20
|
+
|
|
21
|
+
**This page is generated.** Run `npm run docs:phrases` after changing `BUILT_IN_PHRASES` in
|
|
22
|
+
`src/core/utils/phrases.ts`. The package's types list the same ids as `UIRender.UIRenderPhraseId`.
|
|
23
|
+
|
|
24
|
+
## Phrases (52)
|
|
25
|
+
|
|
26
|
+
| Id | English text | Where it shows |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `CALENDAR_OK` | OK | The button under a date field's calendar that takes the date picked in it, where its meta gives `needConfirm` or `showTime` |
|
|
29
|
+
| `CHOOSE_A_DECADE` | Choose a decade | The name a screen reader gives the decade over the years of a date field's calendar, a button that shows the decades |
|
|
30
|
+
| `CHOOSE_A_MONTH` | Choose a month | The name a screen reader gives the month over the days of a date field's calendar, a button that shows the months |
|
|
31
|
+
| `CHOOSE_A_YEAR` | Choose a year | The name a screen reader gives the year over the days or the months of a date field's calendar, a button that shows the years |
|
|
32
|
+
| `DOWNLOAD_FAILED` | Download Failed! | The popup a failed download opens, under its title, which is why the download failed |
|
|
33
|
+
| `END_DATE_CANNOT_BE_LESS_THAN_START_DATE` | End date cannot be less than start date | A period's end date, checked by `notWithinRange`, where it is before the start date |
|
|
34
|
+
| `ERROR` | Error | The title of the popup a failed `onApplyPeriods` opens, and of a template popup with no `title` and no `items` |
|
|
35
|
+
| `FILE` | File | What an upload takes, where its meta gives no `label` or `fileType`: in its header, and in its drop zone where it takes one file |
|
|
36
|
+
| `FILES` | Files | What an upload takes, where its meta gives no `label` or `fileType`: in its drop zone, where it takes several files |
|
|
37
|
+
| `FILE_MUST_BE_UNDER` | {file} must be under {size} | The popup a dropped file larger than an upload's `maxSize` opens; `{file}` is the file's name, `{size}` the limit |
|
|
38
|
+
| `FILE_UPLOAD_FAILED` | File Upload Failed! | The title of the popup a dropped file of a type an upload does not take opens |
|
|
39
|
+
| `INVALID_DATE` | Invalid date | A date field left with text that is no date in its format, which it keeps showing |
|
|
40
|
+
| `INVALID_EMAIL_ADDRESS` | Invalid email address | A field with `validate: "email"` that holds no email address |
|
|
41
|
+
| `INVALID_URL` | Invalid URL | A field with `validate: "url"` that holds no URL with a protocol |
|
|
42
|
+
| `LAST_YEAR` | Last year (Control + left) | The name a screen reader gives the button that goes a year back in a date field's calendar: a decade back where the calendar shows years, a century where it shows decades |
|
|
43
|
+
| `MAXIMUM_FILE_SIZE_EXCEEDED` | Maximum File Size Exceeded! | The title of the popup a dropped file larger than an upload's `maxSize` opens |
|
|
44
|
+
| `MUST_BE_LESS_THAN_CHARACTERS` | Must be less than {count} characters | A field with `validate: "maxLength"` that holds more; `{count}` is the limit, 100 |
|
|
45
|
+
| `MUST_BE_MAXIMUM` | Must be maximum {max} | A number field above its `max`; `{max}` is the `max` |
|
|
46
|
+
| `MUST_BE_MINIMUM` | Must be minimum {min} | A number field below its `min`; `{min}` is the `min` |
|
|
47
|
+
| `NEXT_MONTH` | Next month (PageDown) | The name a screen reader gives the button that goes a month forward in a date field's calendar |
|
|
48
|
+
| `NEXT_PAGE` | Next page | The name a screen reader gives the button to a table's next page |
|
|
49
|
+
| `NEXT_YEAR` | Next year (Control + right) | The name a screen reader gives the button that goes a year forward in a date field's calendar: a decade forward where the calendar shows years, a century where it shows decades |
|
|
50
|
+
| `NO` | No | A value of `false`, shown as text |
|
|
51
|
+
| `NOW` | Now | The link under a date field's calendar that picks the current date and time, where its meta gives `showTime` |
|
|
52
|
+
| `OFF` | OFF | A toggle's off side, where it has no label |
|
|
53
|
+
| `OK` | Ok | The button that closes a popup |
|
|
54
|
+
| `ON` | ON | A toggle's on side, where it has no label |
|
|
55
|
+
| `PAGE` | Page {page} | The name a screen reader gives the button to one page of a table; `{page}` is its number |
|
|
56
|
+
| `PAGINATION` | Pagination | The name a screen reader gives a table's page navigation |
|
|
57
|
+
| `PASSWORD_IS_TOO_WEAK` | Password is too weak | A field with `validate: "password"` that holds a weak password |
|
|
58
|
+
| `PERIODS_CANNOT_OVERLAP` | Periods cannot overlap | A period's dates, checked by `notWithinRange`, where the period overlaps another row's |
|
|
59
|
+
| `POPUP` | Popup | The name a screen reader gives a popup with no title and no message |
|
|
60
|
+
| `POPUP_CONTENT_IS_EMPTY` | Popup content is empty | The popup a `popupOpen` opens for a template popup with no `items` |
|
|
61
|
+
| `PREVIOUS_MONTH` | Previous month (PageUp) | The name a screen reader gives the button that goes a month back in a date field's calendar |
|
|
62
|
+
| `PREVIOUS_PAGE` | Previous page | The name a screen reader gives the button to a table's previous page |
|
|
63
|
+
| `REQUIRED` | Required | A required field left empty |
|
|
64
|
+
| `SELECT` | Select | A select's placeholder, where its meta gives none |
|
|
65
|
+
| `SELECT_NAME` | Select {name} | The name a screen reader gives a select with no `label`; `{name}` is its `name` |
|
|
66
|
+
| `SELECT_OR_DROP` | Select or Drop | An upload's drop zone, above what it takes |
|
|
67
|
+
| `SLIDER_MAXIMUM` | {name}, maximum | The name a screen reader gives a range slider's upper handle; `{name}` is the slider's `label`, or else its `name` |
|
|
68
|
+
| `SLIDER_MINIMUM` | {name}, minimum | The name a screen reader gives a range slider's lower handle; `{name}` is the slider's `label`, or else its `name` |
|
|
69
|
+
| `START_AND_END_DATE_CANNOT_BE_THE_SAME` | Start date and end date cannot be the same | A period's two dates, checked by `notWithinRange`, where they are the same |
|
|
70
|
+
| `START_DATE_CANNOT_BE_MORE_THAN_END_DATE` | Start date cannot be more than end date | A period's start date, checked by `notWithinRange`, where it is after the end date |
|
|
71
|
+
| `SYNCING` | Syncing... | An `AutoSubmit` view's loader while it saves, where its meta gives no `loadContent` |
|
|
72
|
+
| `TABLE_HAS_NO_DATA` | Table has no data! | A table with no `headers` and no rows to take them from |
|
|
73
|
+
| `TODAY` | Today | The link under a date field's calendar that picks today |
|
|
74
|
+
| `TOTAL` | Total | A pie chart's centre, under the total of its values |
|
|
75
|
+
| `UPLOAD_FILE` | Upload {file} | An upload's header, and its hover text where it has no `label` or `fileType`; `{file}` is its `label` or `fileType`, or else `FILE` |
|
|
76
|
+
| `UPLOAD_FILES_ONLY` | Upload {formats} files only | The popup a dropped file of a type an upload does not take opens; `{formats}` lists the types it takes |
|
|
77
|
+
| `UPLOAD_LABEL_FILE` | Upload {label} File | An upload's hover text, where it has a `label` or `fileType` and no `labelOnHover`; `{label}` is that label |
|
|
78
|
+
| `WEEK` | Week | The name a screen reader gives the column of week numbers in a date field's calendar, where its meta gives `showWeek` |
|
|
79
|
+
| `YES` | Yes | A value of `true`, shown as text |
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
GENERATED FILE — DO NOT EDIT. Run `npm run docs:props` to regenerate.
|
|
3
|
+
Inventories are derived from the component source, `domProps.ts` and the call sites;
|
|
4
|
+
the prose comes from scripts/wrapper-prop-curation.js. Generator: scripts/generate-wrapper-prop-reference.js.
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Supported props — `Table`, `Tooltip`, `Select` / `Dropdown`
|
|
8
|
+
|
|
9
|
+
Companion to `docs/SUPPORTED-VIEWS.md`, which lists every `view` name a meta may use. This page
|
|
10
|
+
covers the props of the three views the `semantic-ui-react` exit replaces one at a time
|
|
11
|
+
(UPGRADE-PLAN §9.7-F1). It is both the **supported-prop list** for meta authors and the
|
|
12
|
+
**parity checklist** the replacements were judged against.
|
|
13
|
+
|
|
14
|
+
**All 3 done.** `Table`, `Tooltip`, `Dropdown` are in-house, and no file in `src`
|
|
15
|
+
reaches `semantic-ui-react` by any mechanism — see *Isolation invariant* below. Every
|
|
16
|
+
section is therefore the in-house shape: what the component **emits**, and what it no
|
|
17
|
+
longer **accepts**. The **forwarded** tables are gone with the dependency, because
|
|
18
|
+
"forwarded" meant "handed to semantic-ui-react"; the props still travel, but now into
|
|
19
|
+
code in this repository, so they are described as what they are rather than ranked by
|
|
20
|
+
how urgently a replacement owed them.
|
|
21
|
+
|
|
22
|
+
**This page is generated.** Editing it by hand is pointless — the contract test regenerates
|
|
23
|
+
it and fails on any difference. Run `npm run docs:props` after changing one of these
|
|
24
|
+
components, and edit prose in `scripts/wrapper-prop-curation.js`.
|
|
25
|
+
|
|
26
|
+
## The outcomes, and why they are not one list
|
|
27
|
+
|
|
28
|
+
"A prop appears in a meta" is not "a prop reaches semantic-ui-react". Each prop on one of
|
|
29
|
+
these views has exactly one of these fates, and they are different promises:
|
|
30
|
+
|
|
31
|
+
| Outcome | What it means | What the §9.7-F1 swap does to it |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| **consumed** | the component, or its caller in the engine, reads it | nothing — we already own the behaviour |
|
|
34
|
+
| **stripped** | removed at the DOM boundary by `src/core/components/domProps.ts` | only the boundary moves |
|
|
35
|
+
| ~~**forwarded**~~ | ~~handed to semantic-ui-react, which decides what happens~~ | **no longer a fate.** The exit completed, so nothing is handed anywhere but to code in this repository |
|
|
36
|
+
| **dropped** | semantic-ui-react handled it; the in-house component deliberately does not | already happened — this is the semver record for that step |
|
|
37
|
+
|
|
38
|
+
A checklist that mixed them would be full of props that never mattered. Each section below
|
|
39
|
+
is split that way.
|
|
40
|
+
|
|
41
|
+
The forwarded set **was** tiered, because "supported" and "used" are different facts: tier 1
|
|
42
|
+
meant a node in the tracked corpus or an audited consumer meta exercised it, tier 2 that it
|
|
43
|
+
was published but unexercised. Both are retired with the set itself — tiers ranked a PARITY
|
|
44
|
+
CHECKLIST, and there is no second implementation left to reach parity with. The distinction
|
|
45
|
+
they encoded did its job: every tier-2 prop on the dropdown was resolved as a deliberate
|
|
46
|
+
removal rather than a silent one, which is what the `Dropped` tables below record.
|
|
47
|
+
|
|
48
|
+
## Isolation invariant
|
|
49
|
+
|
|
50
|
+
**The table below is empty, and that is the point.** This scan reads `src` for every
|
|
51
|
+
`import`, `import()`, `require` and `jest.mock` of `semantic-ui-react`; it started at 7
|
|
52
|
+
files and reached zero at §9.7-F1 step 3 part 2, when `Dropdown` moved onto the
|
|
53
|
+
in-house `Listbox`. No file in `src` references the package by any mechanism, so the
|
|
54
|
+
isolation invariant ("only inside the components pack") now holds in the stronger form
|
|
55
|
+
"nowhere at all". Every remaining mention in the tree is prose — comments recording what
|
|
56
|
+
the package used to do, and the docs you are reading.
|
|
57
|
+
|
|
58
|
+
The scan is kept rather than deleted because zero is a value worth defending: it is what
|
|
59
|
+
fails if the dependency comes back. What it can no longer do is tell you the scan itself
|
|
60
|
+
still works, so the contract test proves the four patterns against a synthetic source.
|
|
61
|
+
|
|
62
|
+
An `eslint` `no-restricted-imports` entry (in `eslint.config.js`) fails `npm run lint:js` on a
|
|
63
|
+
static `import` or `export … from` of the package from anywhere in `src`, `src/core/components` included,
|
|
64
|
+
including deep imports such as `semantic-ui-react/dist/...`. A static import is *all* it sees:
|
|
65
|
+
it cannot see `require()`, `jest.mock()`, or a dynamic `import('semantic-ui-react')` — measured
|
|
66
|
+
on ESLint 9.39, the rule does not visit `ImportExpression`. It does cover TypeScript: `lint:js`
|
|
67
|
+
lints every `.js`, `.jsx`, `.ts` and `.tsx` file under `src`.
|
|
68
|
+
|
|
69
|
+
The scan above closes every one of those gaps — dynamic imports, double-quoted specifiers and
|
|
70
|
+
TypeScript files included — which is why both halves run. Neither is sufficient alone.
|
|
71
|
+
|
|
72
|
+
## In-house — the exit
|
|
73
|
+
|
|
74
|
+
### `Table` — in-house, no semantic-ui-react
|
|
75
|
+
|
|
76
|
+
`src/core/components/Table.tsx`, 176 lines. Replaced the wrapper in §9.7-F1 step 1.
|
|
77
|
+
|
|
78
|
+
Seven components over the seven native table elements — markup and className composition, which is all `semantic-ui-react` was contributing here. Semantic's own table CSS was never loaded (its `collections/table` import in `src/style/override/_semantic.less` was commented out, and went at step 4), so every table style in the product was already in-house LESS and the swap changed no styling.
|
|
79
|
+
|
|
80
|
+
**What it emits.** The root always emits `ui <modifiers> table <className>` — `ui` first, `table` second-to-last, the caller's `className` last. The six subcomponents emit the caller's `className` and nothing else.
|
|
81
|
+
|
|
82
|
+
| Component | Element | Notes |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| `Table.Header` | `<thead>` | Rendered unconditionally by `TableView`, and empty in the five `vertical` tables — an empty `<thead>` must still render, because the behaviour contract counts `rowgroup: 2` per table. |
|
|
85
|
+
| `Table.HeaderCell` | `<th>` | Rendered as `th` wherever it sits. The `vertical` layout puts header cells inside `<tbody>`, which both `table.no-header.vertical > tbody > tr > th` and the role census (`columnheader`) depend on. No `scope` is added: `scope="row"` would reclassify those cells as `rowheader`. A meta header's `classNameHeader` and `styleHeader` go on this cell, and its `className` and `style` on the `Row` inside it, which holds the label. So a header's background belongs in `classNameHeader`: `table.less` gives the cell the header colour as specifically as `th` alone (`:where(table:not(.as-layout)) th`), and a background class there, such as `bg-primary-light2`, paints the whole cell. In `className` it paints the `Row` only, which is as tall as its own label, so beside a label on two lines it is a band with the header colour above and below it. Until 2026-10-23 the header colour outweighed every background class, and `classNameHeader` could not set one. |
|
|
86
|
+
| `Table.Row` | `<tr>` | Takes the meta `itemClassNames` result, which is `undefined` for every row in the tracked corpus. |
|
|
87
|
+
| `Table.Cell` | `<td>` | The one boundary that matters: `mapper.tsx:154` spreads a `TableCells` node's whole rest bag onto it, so this is where `ENGINE_PROPS` and `FIELD_ONLY_PROPS` are applied. |
|
|
88
|
+
| `Table.Body` | `<tbody>` | Also rendered unconditionally, including when the table has no rows. |
|
|
89
|
+
| `Table.Footer` | `<tfoot>` | Part of the API and never used: zero `<tfoot>` in the 38-example baseline and no call site in `src`. |
|
|
90
|
+
|
|
91
|
+
CSS contract: `src/style/components/table.less` hangs EVERY cell's padding off `.ui.table` (`.ui.table td > :not(.button)` / `th > :not(.button)`), so the root has to keep emitting both tokens even though no Semantic table CSS is loaded: drop either and every table in the product loses its cell padding. `table:not(.as-layout).inverted` and `table.striped tr:nth-child(2n)` are why `inverted`/`striped` survived as props. The element names and the `table > thead|tbody > tr > th|td` nesting are load-bearing too — the border-radius rules and `table.no-header.vertical > tbody > tr > th` select on structure, not on classes.
|
|
92
|
+
|
|
93
|
+
**Consumed by the root (3).** Read by `Table` itself; everything else rides the rest spread onto the element.
|
|
94
|
+
|
|
95
|
+
| Prop | Meaning |
|
|
96
|
+
| --- | --- |
|
|
97
|
+
| `className` | Appended last, after `table`. `TableView` builds it from `full-width`, the meta `styles` (which arrive as `className`) and `vertical`; `fill` goes to the scroll container around the table instead. Consumer metas add `as-layout`, `no-header`, `highlight-N-last` and the sticky-column tokens through the same channel. |
|
|
98
|
+
| `inverted` | Dark table. Emitted as the `inverted` class, which `table.less` and `expand.less` both select on. **KEPT — decided at §9.9-H1 (2026-09-17), which is where step 1 left the call.** Its one in-repo caller was `ErrorTable.js`, and H1 deleted it, so the "Attributes at the call sites" table below no longer lists this prop — that table reports what the CODEBASE passes, not what the component accepts. The prop itself is untouched: `Table.tsx` still destructures it and still emits the class, the CSS still selects on it, and a consumer meta can still set it. Dropping it because our own last caller went away would have been a breaking change bought for nothing. |
|
|
99
|
+
| `striped` | Zebra rows, emitted as the `striped` class. Same story as `inverted` exactly: genuinely styled (`table.striped tr:nth-child(2n)`), which is why neither was dropped with the rest, and still accepted after H1 removed their shared call site. |
|
|
100
|
+
|
|
101
|
+
**Consumed by every subcomponent (1).** All 6 share one implementation, so this list applies to each of them identically.
|
|
102
|
+
|
|
103
|
+
| Prop | Meaning |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `className` | Passed through verbatim, or the attribute is omitted entirely when it is absent or empty. Semantic ran its own `cx()` and printed `class=""` regardless: 317 empty class attributes in the 38-example baseline were its, on `tbody` (24), `tr` (94) and `td` (199), and they are gone. |
|
|
106
|
+
|
|
107
|
+
**Stripped at the DOM boundary.** `src/core/components/Table.tsx` applies `ENGINE_PROPS`, `FIELD_ONLY_PROPS` from `src/core/components/domProps.ts` in all 7 components, so these never become attributes: `view`, `index`, `data`, `_data`, `symbol`, `_comment`, `expanded`, `translate`, `onDataChanged`, `currencyCode`, `meta`, `@class`, `name`, `label`, `readonly`.
|
|
108
|
+
|
|
109
|
+
**Passthrough.** `style`, `colSpan`, `scope`, `id`, `data-*` and every event handler still reach the element untouched — they always did, because Semantic did not handle them either, so they ride the rest spread exactly as before. There is no `forwardRef`: nothing in `src` passes a ref to a table element, so the parameter would have had no caller.
|
|
110
|
+
|
|
111
|
+
**Dropped (4) — the semver record.** Props semantic-ui-react handled that this implementation deliberately does not. All of them remain REACHABLE from a consumer meta: the component is rendered with open spreads (`...omitProps(rest, ENGINE_PROPS, FIELD_ONLY_PROPS)`, `...rest`), so an attribute nobody anticipated on a meta node still arrives here as a prop. That is why the component strips them explicitly. It warns once per prop only when this repository runs the source in development; the published bundle is built for production and strips them without a word. Stripping matters because the value would otherwise reach a real element as an attribute — a string-valued one lands lowercase (`verticalAlign="top"` rendered `verticalalign="top"`) and a boolean draws React's "Received `true` for a non-boolean attribute" warning, both of them junk the DOM contract's tripwires exist to keep out. A meta still carrying one learns nothing from the published bundle, so check it against the table below. And React's own unknown-prop warning cannot be relied on: it is silent for a lowercase name.
|
|
112
|
+
|
|
113
|
+
| Prop | Why it is gone |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `verticalAlign` | Was accepted on the cell and turned into the classes `top aligned`. NO loaded CSS selects on `aligned` (0 occurrences in `static/all.css` and in `src/style`), and no `.top` rule can match either — every one of them needs a second class on the same element — so the 15 cells that asked for it rendered at the `<td>` default anyway. Both call sites (`LocalDraftTableRow`) were removed with the prop. A cell that must align does it with `style={{verticalAlign}}`, which is what the metas that actually align already use. |
|
|
116
|
+
| `as` | Element override. No call site, no meta occurrence; the element per component is now fixed, which is what the structural CSS selectors assume anyway. |
|
|
117
|
+
| `celled` | Semantic border modifier. Emitted a class no loaded CSS selects on, so it was inert markup even when passed — and nothing passed it. |
|
|
118
|
+
| `textAlign` | Emitted `<value> aligned`, the same dead token family as `verticalAlign`. Use a `className` or a `style`. |
|
|
119
|
+
|
|
120
|
+
Those four were the *published* ones — they had curated entries on this page while it was a wrapper. Semantic's `Table` handled 29 props and its `Table.Cell` 17, and the rest of that surface was reachable only by passthrough and never documented here: `collapsing`, `color`, `columns`, `compact`, `definition`, `fixed`, `padded`, `attached`, `basic`, `selectable`, `singleLine`, `size`, `sortable`, `stackable`, `structured`, `unstackable`, `width`, `fullWidth`, `sorted`, the row/cell state modifiers (`active`/`disabled`/`error`/`negative`/`positive`/`warning`), the `content`/`icon` shorthands, `cells`/`cellAs`, and the nil-children shorthand engine (`headerRow`/`headerRows`/`renderBodyRow`/`tableData`/`footerRow`). None occurs in either corpus and none is selected by loaded CSS. Step 5 records the semver call for the whole set; on the evidence here it is minor.
|
|
121
|
+
|
|
122
|
+
**Call sites.** What the codebase puts on the family, derived from the source. This was the step-1 parity surface and it is kept afterwards, because it is what any future change to the family is measured against:
|
|
123
|
+
|
|
124
|
+
| Component | Attributes at the call sites | Spreads | Rendered by |
|
|
125
|
+
| --- | --- | --- | --- |
|
|
126
|
+
| `Table` | `className` | `...omitProps(rest, ENGINE_PROPS, FIELD_ONLY_PROPS)` | `core/engine/components/TableView.tsx` |
|
|
127
|
+
| `Table.Header` | `className` | — | `core/engine/components/TableView.tsx` |
|
|
128
|
+
| `Table.HeaderCell` | `aria-sort`, `className`, `colSpan`, `key`, `style` | — | `core/engine/components/TableView.tsx` |
|
|
129
|
+
| `Table.Row` | `className`, `key` | — | `core/engine/components/TableView.tsx` |
|
|
130
|
+
| `Table.Cell` | `className`, `colSpan`, `key`, `style` | `...rest` | `core/engine/components/LocalDraftTableRow.tsx`, `core/engine/components/TableView.tsx`, `core/engine/mapper.tsx` |
|
|
131
|
+
| `Table.Body` | — | — | `core/engine/components/TableView.tsx` |
|
|
132
|
+
| `Table.Footer` | — | — | *nothing* |
|
|
133
|
+
|
|
134
|
+
`mapper.tsx`'s spread onto `Table.Cell` is a meta node's whole rest bag and is still unfiltered at the call site — the filter is now inside the cell, which is why it is safe. All three unfiltered boundaries on this surface are now closed inside the component: the table cell at step 1, the tooltip at step 2 part 3, and the dropdown at step 3 part 2, which strips twice — once in the wrapper and once in `Listbox` at the element.
|
|
135
|
+
|
|
136
|
+
### `Tooltip` — in-house, no semantic-ui-react
|
|
137
|
+
|
|
138
|
+
`src/core/components/Tooltip.tsx`, 576 lines. Replaced the wrapper in §9.7-F1 step 2 part 3.
|
|
139
|
+
|
|
140
|
+
The hover tooltip, over the same inline `<span>` `components/TooltipBubble.tsx` has shipped for years (as `components/Tooltip.tsx` until §9.9-H6, when this component, `TooltipPop`, took that name). Reached two live ways: a `view: "Tooltip"` node (`mapper.tsx`, which maps `label` to `content`) and the `tooltip` attribute on ANY node (`Render.tsx`, which wraps the rendered node and spreads an object `tooltip` — still an unfiltered passthrough, but into 13 accepted names now instead of 45). This was a FIX, not a trade: measured in real Chrome on the production build, the SUIR bubble rendered at the document origin at every use site a meta can declare (~730 px from its trigger on `buttonIcon`, 2538-3006 px on `all`) and every open raised an uncaught `TypeError` from popper's flip modifier, because SUIR clones the trigger with a `ref` and nothing a meta can declare can hold one. There was no working positioning to lose.
|
|
141
|
+
|
|
142
|
+
**What it emits.** Host: `tooltip-host <classWrap>`, always, open or closed. Bubble, only while open: `tooltip no-wrap <resolved placement words> show [inverted] <className>` — the same class string `TooltipBubble.tsx` emits, so the two converge on one CSS contract. The placement words are the REQUESTED position, not a resolved one: nothing measures, so there is no flip to rewrite them. Closed, the component renders the trigger byte-for-byte as it renders without a tooltip, and nothing is added to `document.body`. THE MARKUP IS NOT UNCHANGED, THOUGH, and two earlier drafts of this row implied it was: the trigger is now WRAPPED in `<span class="tooltip-host">`, which is new markup and shows up in this step's own snapshot diff at the one tooltip site the 38 examples render at mount. So: the trigger element itself is untouched when closed; the box around it is new. What the baseline still cannot see is the BUBBLE, which exists only while open, and therefore anything about opening, placement or dismissal.
|
|
143
|
+
|
|
144
|
+
**What opens and closes it.** Opens on hover after `delay` (500 ms) and on focus, immediately. Closes 70 ms after the pointer leaves (unless the trigger has focus, which keeps it open until blur), on blur, on a click anywhere outside it, and on Escape. Leaving before the delay elapses cancels the pending open, and a pending open never fires against an unmounted tree. The bubble is NOT hoverable — measured in Chrome, moving the pointer onto it closes the tooltip, exactly as SUIR did without `hoverable`. That is not an oversight and it is not fixable here: the bubble must keep `pointer-events: none` (see cssContract), so the pointer over the bubble is really over whatever is behind it, `mouseleave` fires on the host, and it closes. Hoverable text and a non-interactive bubble are mutually exclusive; the bubble stays non-interactive. THIS IS A KNOWN WCAG NON-CONFORMANCE and is named here rather than left for a reader to derive: SC 1.4.13 "Content on Hover or Focus" requires hovered content to be HOVERABLE, and this bubble is not (Dismissable via Escape and Persistent are met). It is kept because the alternative measured worse — without `pointer-events: none` the bubble swallows the pointer over its own trigger and the control stops responding at all — and because `Slider` depends on it as well: its handle drags on `pointerdown`, so a press inside the value bubble used to move the slider. ARIA: the bubble carries `role="tooltip"` and an `id`, and the trigger points at it with `aria-describedby`; SUIR had none of that. CLICK-TO-OPEN IS GONE — see `dropped.on`. The trigger may be any children, including several or none: `React.Children.only` is gone with the portal, so the `items` form of `view: "Tooltip"` renders instead of throwing the engine's error diagnostic. Pinned on React 16.14/17.0.2/18.3/19.3.0 by `components/__tests__/Tooltip.behavior.test.js` and `UIRender.overlay-behavior.test.js`, and in real Chrome by `e2e/corpus.tooltip.pw.js`.
|
|
145
|
+
|
|
146
|
+
CSS contract: The bubble is now mounted INSIDE `.ui-render`, which is what makes our own CSS apply to it at all — the SUIR bubble portaled into `document.body`, outside the prefixwrap scope, so not one of the 13 `.ui.popup` rules could paint it and the live tooltip was unstyled text. It draws its bubble with `TooltipBubble.tsx`, sharing `src/style/components/tooltip.less` with `Slider`, `Upload` and the validation tooltip, so `tooltip`, `no-wrap`, the four placement words and `show` are all load-bearing, and `.show` must keep beating the `*:hover > &` reveal — which it does on source order at equal specificity, not by outranking it. THE HAZARD THIS STEP CARRIES: `tooltip.less` sets `pointer-events: none` on the bubble, and without it the bubble swallows the pointer over its own trigger — Playwright measured the trigger as unhoverable. That declaration is ALSO what makes the pointer over the bubble land on whatever is behind it, so `mouseleave` fires on the host and the bubble is not hoverable; removing it would invert both, giving a hoverable bubble and a broken trigger. `css.tooltip-contract.test.js` joins the emitted markup to the loaded CSS in both directions.
|
|
147
|
+
|
|
148
|
+
**Consumed by the root (13).** Read by `Tooltip` itself; everything else rides the rest spread onto the element.
|
|
149
|
+
|
|
150
|
+
| Prop | Meaning |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `title` | The tooltip body, rendered as the bubble's children. A function value is called and its result rendered — the SUIR-#4029 workaround is gone, but the calling convention it produced is kept, because two metas in the corpus rely on it. Overridden by `content` when both are given. |
|
|
153
|
+
| `children` | The trigger, rendered inside the host `<span>`. NO `ref` is required of it, which is the whole bug fix — `semantic-ui-react` cloned it for one, and nothing a meta can declare can hold a ref. Its own handlers are never wrapped or replaced either. It IS cloned, though, and an earlier draft of this row said otherwise: while the tooltip is open the trigger is cloned once to carry `aria-describedby`, which is APPENDED to whatever the trigger already pointed at rather than replacing it — a form control keeps the link to its own validation message. Closed, there is no clone and no attribute. |
|
|
154
|
+
| `delay` <br>*(has a default)* | Milliseconds before a HOVER opens the tooltip; default 500, deliberately slower than Semantic's 50 ms, and a UX decision pinned to the millisecond in three suites. Focus ignores it. |
|
|
155
|
+
| `inverted` | Dark colour scheme, emitted as the `inverted` class. Always true from both engine entry points. |
|
|
156
|
+
| `content` | Alias for `title`, and it wins. Was only reachable through the rest spread before, which is how a caller-supplied `content` used to override `title` by accident of ordering; now that precedence is explicit. |
|
|
157
|
+
| `position` <br>*(has a default)* | Placement words (`"top left"`, `"bottom"`, …), default `"top"`. Emitted as classes for our CSS to position with; there is no measuring, so an unknown word is simply not emitted. |
|
|
158
|
+
| `open` | Controlled open state. When given, the component renders it and stops managing its own — hover, focus, Escape and click-outside still call `onOpen`/`onClose` so a controlled host can respond, but they do not move the bubble themselves. |
|
|
159
|
+
| `disabled` | Suppresses opening entirely; the trigger still renders. |
|
|
160
|
+
| `className` | Appended last on the BUBBLE. |
|
|
161
|
+
| `classWrap` | Appended on the HOST span. Kept under the old name because both engine entry points pass it. |
|
|
162
|
+
| `id` | Overrides the generated bubble id. Given one, `aria-describedby` points at it; otherwise a per-instance `ui-render-tooltip-N` is generated. |
|
|
163
|
+
| `onOpen` | Called when the bubble opens, controlled or not. |
|
|
164
|
+
| `onClose` | Called when it closes, controlled or not. |
|
|
165
|
+
|
|
166
|
+
**Stripped at the DOM boundary.** `src/core/components/Tooltip.tsx` applies `ENGINE_PROPS`, `FIELD_ONLY_PROPS` from `src/core/components/domProps.ts`, so these never become attributes: `view`, `index`, `data`, `_data`, `symbol`, `_comment`, `expanded`, `translate`, `onDataChanged`, `currencyCode`, `meta`, `@class`, `name`, `label`, `readonly`.
|
|
167
|
+
|
|
168
|
+
**Passthrough.** `style`, `data-*`, `aria-*` and every event handler still reach the bubble untouched through `omitProps(…, ENGINE_PROPS, FIELD_ONLY_PROPS)` — the same DOM boundary every other component uses, which is new here: SUIR's `Popup` applied no such filter, so `§9.7-F1` step 2 also closed the engine-prop leak on this path. There is no `forwardRef`: nothing in `src` passes a ref to a tooltip, and the host `<span>` holds the only ref the component itself needs.
|
|
169
|
+
|
|
170
|
+
**Dropped (19) — the semver record.** Props semantic-ui-react handled that this implementation deliberately does not. All of them remain REACHABLE from a consumer meta: the component is rendered with open spreads (`...props`), so an attribute nobody anticipated on a meta node still arrives here as a prop. That is why the component strips them explicitly. It warns once per prop only when this repository runs the source in development; the published bundle is built for production and strips them without a word. Stripping matters because the value would otherwise reach a real element as an attribute — a string-valued one lands lowercase (`verticalAlign="top"` rendered `verticalalign="top"`) and a boolean draws React's "Received `true` for a non-boolean attribute" warning, both of them junk the DOM contract's tripwires exist to keep out. A meta still carrying one learns nothing from the published bundle, so check it against the table below. And React's own unknown-prop warning cannot be relied on: it is silent for a lowercase name.
|
|
171
|
+
|
|
172
|
+
| Prop | Why it is gone |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `on` | CLICK-TO-OPEN. SUIR ran `on: ['click', 'hover']`; every tooltipped node in the corpus already owns its `onClick`, so one gesture fired both the action and the tooltip and the tooltip arrived after the action had run. Dropped deliberately and recorded — on this page, in the step PR, in UPGRADE-PLAN §9.7-F1 step 2 and in the changelog, whose entry ("The tooltip is settled") points here for the per-prop record. Focus-to-open, `role="tooltip"` and `aria-describedby` were added BECAUSE of this removal: with click gone and hover unavailable to a keyboard there would otherwise be no keyboard path to the content at all. AND THAT PATH ONLY EXISTS FOR A FOCUSABLE TRIGGER, which is the part this row owes a reader and did not say. Focus-open reaches a `<button>`, a link or an input; it does not reach a `<span>`, a `<div>` or an `<i>`, and no `tabindex` is added to make it. A tooltip on a non-focusable trigger is therefore HOVER-ONLY now: reachable with a mouse, unreachable by keyboard, and unreachable by touch. Every tooltipped node in the tracked corpus is a `<button>`, so the corpus does not exercise this — but a consumer meta can put `tooltip` on any node at all, and `Render.tsx` will wrap it. If that content matters, the node has to be focusable; the tooltip will not make it so. |
|
|
175
|
+
| `hoverable` | Was what let the pointer travel onto the bubble. Now unconditional, so the prop has nothing left to turn on. |
|
|
176
|
+
| `closeOnDocumentClick` | Closing on an outside click is unconditional. Nothing passed this, and a tooltip that survives a click elsewhere is a popover, which this is not. |
|
|
177
|
+
| `closeOnEscape` | Same: Escape always dismisses. |
|
|
178
|
+
| `mouseEnterDelay` | THE OLD NAME FOR `delay`, and the one silently-dropped prop with a real chance of appearing in a consumer meta: it was `Popup`'s own name for the hover-open delay, and the wrapper forwarded `delay` to it. Listed here — and therefore warned about — precisely so it is not ignored without a word. Use `delay`, which means the same thing and is the name the component has always published. |
|
|
179
|
+
| `mouseLeaveDelay` | The 70 ms close delay is fixed. NOT for the reason an earlier draft of this row gave — "so the pointer can cross the gap onto the bubble" is impossible here, because the bubble is `pointer-events: none` and travelling onto it closes the tooltip anyway. What it actually buys is tolerance for a pointer that clips the EDGE of the trigger on its way somewhere else, and for the sub-pixel gaps between a trigger and its own padding: without it a fast diagonal exit flickers the bubble. That is a layout constant rather than a caller's choice. |
|
|
180
|
+
| `mountNode` | Portal target. There is no portal — the bubble is a sibling of the trigger, which is what brings it inside the prefixwrap scope. |
|
|
181
|
+
| `popper` | Popper.js configuration. No popper. |
|
|
182
|
+
| `offset` | Popper offset, in px. Positioning is CSS now; use `className`. |
|
|
183
|
+
| `pinned` | Popper flip/shift suppression. Nothing flips. |
|
|
184
|
+
| `hideOnScroll` | Closed the bubble on window scroll, to hide a bubble that no longer tracked its trigger. A bubble positioned by CSS moves WITH its trigger, so the problem it worked around is gone. |
|
|
185
|
+
| `defaultOpen` | Uncontrolled initial state. Use `open` with `onClose`. |
|
|
186
|
+
| `trigger` | SUIR took the trigger as a prop; this component takes `children`. |
|
|
187
|
+
| `header` | Bolded first line inside the bubble. Zero occurrences in either corpus; put it in `title` as an element. |
|
|
188
|
+
| `as` | Element override for the bubble. The element is fixed at `<span>`, which the CSS assumes. |
|
|
189
|
+
| `basic` | Semantic style modifier (no arrow). Emitted a class no loaded rule selects. |
|
|
190
|
+
| `flowing` | Removed Semantic's width cap. Ours does not cap width — `no-wrap` is the contract instead — so there is nothing to remove. |
|
|
191
|
+
| `size` | Semantic size modifier. Inert class; the bubble takes its type scale from `tooltip.less`. |
|
|
192
|
+
| `wide` | Semantic `wide`/`very wide` width steps. Same — no loaded rule selects them. |
|
|
193
|
+
|
|
194
|
+
THE ARITHMETIC, derived from the installed `semantic-ui-react` rather than estimated — an earlier version of this note said "the remaining ~14" and did not add up. Because SUIR's rest spread landed last, a caller reached `Popup.handledProps` (29) ∪ `Portal.handledProps` (22) = 45 distinct names, 16 of them Portal-only and absent from `Popup`'s own propTypes (`closeOnPortalMouseLeave`, `closeOnTrigger*`, `openOnTrigger*`, `eventPool`, `triggerRef`, …). Those 45 split exactly three ways: 9 are still accepted under the same name (`content`, `children`, `inverted`, `position`, `open`, `disabled`, `className`, `onOpen`, `onClose`); 19 are DROPPED by name, with a warning that only a development run of the source in this repository prints; and 17 are dropped SILENTLY. 9 + 19 + 17 = 45. Every one of the 19 warned names really was in that surface — checked, none is invented. The silent 17 are Semantic's own internals (`context`, `onMount`/`onUnmount`, `openOnTrigger*`, `popperModifiers`, `positionFixed`, the transition plumbing) and warning on them would be noise, with one exception worth naming rather than hiding: `style` still reaches the bubble through the rest spread, so it was never really dropped. `mouseEnterDelay` used to be in this silent group and was MOVED into the warned one for the same reason — it was SUIR's name for what this component calls `delay`, so a meta spelling it the old way was ignored without a word. The component's own accepted surface is 13 names, four of which (`title`, `delay`, `classWrap`, `id`) were never SUIR props at all. Step 5 records the semver call for the whole set; on this evidence it is a minor with a changelog entry for `on`.
|
|
195
|
+
|
|
196
|
+
**Call sites.** What the codebase puts on the family, derived from the source. This was the step-1 parity surface and it is kept afterwards, because it is what any future change to the family is measured against:
|
|
197
|
+
|
|
198
|
+
| Component | Attributes at the call sites | Spreads | Rendered by |
|
|
199
|
+
| --- | --- | --- | --- |
|
|
200
|
+
| `Tooltip` | `inverted`, `title` | `...props` | `core/engine/mapper.tsx`, `demo/pages/TooltipHarness.jsx` |
|
|
201
|
+
|
|
202
|
+
`mapper.tsx`'s spread onto `Table.Cell` is a meta node's whole rest bag and is still unfiltered at the call site — the filter is now inside the cell, which is why it is safe. All three unfiltered boundaries on this surface are now closed inside the component: the table cell at step 1, the tooltip at step 2 part 3, and the dropdown at step 3 part 2, which strips twice — once in the wrapper and once in `Listbox` at the element.
|
|
203
|
+
|
|
204
|
+
### `Dropdown` — in-house, no semantic-ui-react
|
|
205
|
+
|
|
206
|
+
`src/core/components/Dropdown.tsx`, 387 lines. Replaced the wrapper in §9.7-F1 step 3 part 2.
|
|
207
|
+
|
|
208
|
+
The wrapper already owned the external API: the `onChange(value, name, event)` signature, option sanitisation and the cascading reset are all wrapper code, and none of it moved (the case-insensitive dedup on addition went with `allowAdditions` at part 2). Only the `<DropDown/>` element at the bottom changed — it is now the in-house `Listbox`, under the same import alias. Two entry points, and they differ: `mapper.tsx` imports the memoised default export for `view: "Dropdown"`, while `modules/form/inputs/DropdownField.ts` imports the NAMED export for `view: "Select"` — which is the majority path.
|
|
209
|
+
|
|
210
|
+
**What it emits.** THE WRAPPER emits `input--wrapper` plus `{float, done, labeled, fill-width, required}` and the caller's `className`, unchanged by the swap. THE CONTROL, one level down in `Listbox.tsx`, emits `ui`, then the `{active, visible, error, disabled, compact, upward}` modifiers, then `selection`, then `dropdown`, then the wrapper-derived `{info, readonly}` — the same token SET Semantic built. `upward` comes from the prop when it is given; unset, the list is measured as it opens and goes up when it does not fit below and there is more room above. Order is not the contract (no loaded selector depends on it); PRESENCE is, and `src/style/__tests__/css.dropdown-contract.test.js` pins what each token is worth: `ui` and `dropdown` reach all 13 scoped rules that can match the control, `selection` 12 of them, `active` 4, `visible` 1. The four inner nodes are pinned the same way — `.text.divider[.default]` (7 rules), `<i class="icon dropdown">` (13), `.menu.transition[.visible]` (11), and each option as `.item[.selected][.active]` (6). `selected` is the CURSOR and `active` the committed value, which is Semantic's own split and why both survive.
|
|
211
|
+
|
|
212
|
+
**What opens and closes it.** The WAI-ARIA select-only combobox pattern — the `combobox` takes focus and its options sit in a `listbox` beside it — which is a deliberate change from what the library did: arrows move a cursor conveyed by `aria-activedescendant`, Enter or Space commits, Escape closes having reported nothing, and the cursor wraps at both ends and skips `disabled` options. Semantic committed as the arrows moved (`selectOnNavigation` defaults true) and on blur (`selectOnBlur`), so a user who arrowed past an option had already changed the form with no keyboard way back; `UIRender.listbox-behavior.test.js` pinned that as it WAS and now pins the replacement, which is the visible record of the change. Home/End jump to the ends, PageUp/PageDown move a page, and typeahead builds a prefix within 700 ms while a REPEATED single character cycles through the options starting with it. Focus does NOT open the list; ArrowDown on a closed control opens it and advances one step. Also gone with Semantic: the `role="alert" aria-live` node it announced the selected value through — the corpus role census dropped 12 `alert` entries to zero in this step.
|
|
213
|
+
|
|
214
|
+
CSS contract: Semantic's `modules/dropdown` CSS, vendored at step 4 as `src/style/vendor/semantic-dropdown.less`, is the largest single semantic module in the compiled CSS and is keyed almost entirely on `.ui.selection.dropdown`, so the coupling between steps 3 and 4 is real and step 3 paid it rather than deferring it: `Listbox` keeps emitting Semantic's token vocabulary verbatim, including the `menu transition visible` node and the per-option `item selected active`, because the vendored CSS and our own LESS beside it still select on every one of those. The token-by-token measurement is in `css.dropdown-contract.test.js`, which is what made step 4 a bounded change instead of a guess. Two modifiers Semantic emitted are gone with their features (`search`, `multiple`); nothing in the loaded CSS selects on either without also requiring markup the control no longer renders.
|
|
215
|
+
|
|
216
|
+
**Consumed by the root (21).** Read by `Dropdown` itself; everything else rides the rest spread onto the element.
|
|
217
|
+
|
|
218
|
+
| Prop | Meaning |
|
|
219
|
+
| --- | --- |
|
|
220
|
+
| `options` <br>*(bound as `opts`)* | Option list: strings, numbers, or `{text, value, key, content, disabled}` objects. Held in wrapper state and sanitised into a fresh array (translation, `value`-from-`text` defaulting, `optionsLabel` appended) whenever there is something to change: an empty list, or objects with numeric values and no `optionsLabel`, reach the control as given. A `null` options prop is tolerated as an empty list — it used to reach Semantic and crash. |
|
|
221
|
+
| `onChange` | Called as `onChange(value, name, event)` — the wrapper's own signature, not Semantic's `(event, data)`. The case-insensitive duplicate collapsing that used to live here went with `allowAdditions`: it could only ever fire for a TYPED value. |
|
|
222
|
+
| `onSelect` | Called on close with the last committed value, same `(value, name, event)` shape. Implemented by handing the control an `onClose`. |
|
|
223
|
+
| `label` | Visible label text, rendered by the wrapper as its own `<Text>` before or after the control depending on `float`, and handed to the combobox as its `aria-label`, which a meta's own `aria-label` or `aria-labelledby` overrides. CONSUMED, not stripped: it is destructured out at the top of the wrapper, so it can never be in the rest bag that `omitProps` filters. |
|
|
224
|
+
| `placeholder` | Placeholder text, translated by the wrapper and then forwarded. Without one, the control shows the built-in phrase `SELECT` (`docs/BUILT-IN-PHRASES.md`). |
|
|
225
|
+
| `done` | Adds a `done` class to the wrapper, the completed state the stylesheet selects on. Unless given, it is true for a value and no error. Until 2026-10-01 the default read `props.value`, always `undefined` once `value` was destructured out, so a `float` label sat over the selection it named (`Dropdown.done-state.test.js`). |
|
|
226
|
+
| `error` | Message shown under the control, in a `${id}-help` block the control points at with `aria-describedby`. The wrapper renders the text itself, a validator's built-in phrase in the language of `translate`, and forwards only `error={!!error}` for the class. |
|
|
227
|
+
| `info` | Explanatory message under the control. Also adds an `info` class. |
|
|
228
|
+
| `float` | Renders the label after the control (float-label layout). |
|
|
229
|
+
| `className` | Composed by the wrapper onto its own `input--wrapper` element; only the derived `{info, readonly}` classes go to the control. |
|
|
230
|
+
| `classNameIcon` | Class for the icon node the wrapper builds when `onClickIcon` is given. |
|
|
231
|
+
| `style` | Inline style, applied to the wrapper element, not to the control. |
|
|
232
|
+
| `fill` <br>*(has a default)* | Adds `fill-width` unless `compact`. Default true. |
|
|
233
|
+
| `lazyLoad` <br>*(has a default)* | Defer rendering options until opened; default true, and `mapper.tsx` passes false on the `view: "Dropdown"` path. Forwarded unchanged, and `Listbox` implements it the same way — the role census counts `option` only where it is false. |
|
|
234
|
+
| `optionsLabel` | Extra disabled option appended to the bottom of the list. |
|
|
235
|
+
| `initialValues` | Accepted and discarded — it exists only to keep the form stack's `initialValues` off the DOM. |
|
|
236
|
+
| `readonly` | Translated to the control's `disabled` plus a `readonly` class, because neither Semantic's Dropdown nor the `role="combobox"` div has a `readOnly`. `disabled` has to be said three ways on a div: `aria-disabled`, `tabIndex={-1}`, and the open guards. |
|
|
237
|
+
| `onClickIcon` | Replaces the icon with a clickable `<Icon>` node. `Listbox` renders a caller's `icon` node in place of its own `<i class="icon dropdown">`. |
|
|
238
|
+
| `required` | Adds the wrapper's `required` class. Newly DESTRUCTURED at step 3 part 2 rather than read off the rest bag: Semantic consumed `required` as a handled prop, so once the control became an open `<div role="listbox">` the same prop rendered as `required=""` on a div. Measured, then fixed. |
|
|
239
|
+
| `translate` <br>*(has a default)* | The i18n function. Engine-owned, applied to option text, `label`, `placeholder` and `error`, and asked for the built-in phrases `SELECT` and `SELECT_NAME`. CONSUMED, not stripped — destructured out at the top of the wrapper. It is also in ENGINE_PROPS, which is what catches it at other boundaries. |
|
|
240
|
+
| `value` <br>*(bound as `valueFromParent`)* | Selected value. Held in wrapper state, synced from the prop, and array values are joined before being forwarded — so what the control sees is not always what the caller passed. |
|
|
241
|
+
|
|
242
|
+
**Stripped at the DOM boundary.** `src/core/components/Dropdown.tsx` applies `ENGINE_PROPS`, `FIELD_ONLY_PROPS` from `src/core/components/domProps.ts`, so these never become attributes: `view`, `index`, `data`, `_data`, `symbol`, `_comment`, `expanded`, `translate`, `onDataChanged`, `currencyCode`, `meta`, `@class`, `name`, `label`, `readonly`.
|
|
243
|
+
|
|
244
|
+
**Passthrough.** `id`, `style`, `data-*` and every event handler still reach the dropdown element untouched, including the `onFocus`/`onBlur` the react-final-form adapter supplies — as real DOM handlers rather than as Semantic props, and they fire for the combobox inside it, because React's focus events bubble. `aria-*` reaches the combobox, the element that takes focus. `ENGINE_PROPS` and `FIELD_ONLY_PROPS` are stripped twice on the way: once by the wrapper, once by `Listbox` at the element itself.
|
|
245
|
+
|
|
246
|
+
**Dropped (48) — the semver record.** Props semantic-ui-react handled that this implementation deliberately does not. All of them remain REACHABLE from a consumer meta: the component is rendered with open spreads (`...dropdown`), so an attribute nobody anticipated on a meta node still arrives here as a prop. That is why the component strips them explicitly. It warns once per prop only when this repository runs the source in development; the published bundle is built for production and strips them without a word. Stripping matters because the value would otherwise reach a real element as an attribute — a string-valued one lands lowercase (`verticalAlign="top"` rendered `verticalalign="top"`) and a boolean draws React's "Received `true` for a non-boolean attribute" warning, both of them junk the DOM contract's tripwires exist to keep out. A meta still carrying one learns nothing from the published bundle, so check it against the table below. And React's own unknown-prop warning cannot be relied on: it is silent for a lowercase name.
|
|
247
|
+
|
|
248
|
+
| Prop | Why it is gone |
|
|
249
|
+
| --- | --- |
|
|
250
|
+
| `search` | Type-to-filter. Removed at §9.7-F1 step 3 part 2, with `multiple` and `allowAdditions`, on the maintainers' decision: NO tracked example meta and no consumer meta declares it. That second half is not an assumption — this repo records consumer-only attributes separately (`CONSUMER_ONLY_ATTRIBUTES`), and for `Select` the list is `disabled`, `upward`, `validate`; for `Dropdown` it is empty. The changelog had also invited consumers to report using exactly these props, and no report came. Removing it is what makes a hand-rolled replacement tractable — filtering, diacritics-insensitive matching and a search input are the bulk of what the library was doing. |
|
|
251
|
+
| `multiple` | Multi-selection, with the value as an array. Same decision and same evidence as `search`. Every `multiple` in the tracked corpus is on a FILE UPLOAD input, not on a select — checked, not assumed. Note the array-VALUE path survives untouched: a colour option carries `[r, g, b]` and is still joined to a string, which is a different feature that happened to share this branch. |
|
|
252
|
+
| `allowAdditions` | Free-text entry of new options, with `additionLabel`, `additionPosition` and `onAddItem`. Same decision and evidence. Its removal also made a part-1 fix unnecessary: `onAddItem` used to write the option list back into state including the appended `optionsLabel`, so every addition appended another label — nothing writes options back now. |
|
|
253
|
+
| `onSearch` | The callback for `search`, gone with it. It had zero occurrences in product code and in both corpora. |
|
|
254
|
+
| `onAddItem` | The callback for `allowAdditions`, gone with it. Also zero occurrences. |
|
|
255
|
+
| `searchInput` | Semantic's prop for the search `<input>`, which the wrapper generated as `{autoFocus: true}` for `autofocus`. There is no such input. |
|
|
256
|
+
| `searchQuery` | The controlled filter text. Nothing to filter. |
|
|
257
|
+
| `onSearchChange` | Semantic's own filter-text callback, generated by the wrapper from `onSearch`. |
|
|
258
|
+
| `deburr` | Diacritics-insensitive matching for the filter. Part of what made a hand-rolled search expensive, and pure cost once there is no search. |
|
|
259
|
+
| `additionLabel` | The prefix on the "add this" option. Belonged to `allowAdditions`. |
|
|
260
|
+
| `additionPosition` | Where that option sat in the list. Also `allowAdditions`. |
|
|
261
|
+
| `noResultsMessage` | Shown when the filter matched nothing. Only reachable while filtering. |
|
|
262
|
+
| `clearable` | Semantic's clear-selection icon. Never wrapper API — reachable only through the old rest spread, and curated on this page as tier 2 with no occurrences in either corpus. Listed rather than forgotten because it is exactly the kind of prop that goes from "quietly handled" to "invalid DOM attribute" at a swap like this: it produced React's "Received `true` for a non-boolean attribute" warning until the strip was added. |
|
|
263
|
+
| `autofocus` | Went with `search` because it could not outlive it: the wrapper turned it into `searchInput={{autoFocus: true}}`, which does nothing on a control with no search input. Removing search left it dead rather than merely unused. |
|
|
264
|
+
| `closeOnBlur` | Closed the list when the dropdown lost focus; on by default. The list always closes when focus leaves it now, as the WAI-ARIA select-only combobox pattern this control follows asks. |
|
|
265
|
+
| `closeOnChange` | Closed the list after a choice. A choice always closes it now. |
|
|
266
|
+
| `closeOnEscape` | Closed the list on Escape. Escape always closes it now, and chooses nothing. |
|
|
267
|
+
| `defaultOpen` | Rendered the list open at first. The list opens only when the user opens it. |
|
|
268
|
+
| `open` | Controlled whether the list was open. The control keeps that state itself; a host cannot drive it. |
|
|
269
|
+
| `openOnFocus` | Opened the list when the dropdown took focus; on by default. Focus does not open it now: a click or the keyboard does. |
|
|
270
|
+
| `selectOnBlur` | Chose the highlighted option when focus left; on by default. Focus leaving the open list still chooses the option under the cursor, Tab included. Escape and a click elsewhere choose nothing. |
|
|
271
|
+
| `selectOnNavigation` | Chose each option as the arrows reached it; on by default. The arrows move a cursor now, and Enter, Space or Tab chooses the option under it. |
|
|
272
|
+
| `wrapSelection` | Let the arrows wrap from the last option to the first; on by default. They always wrap. |
|
|
273
|
+
| `defaultUpward` | Opened the list upward at first. `upward` still decides the direction; without it, the list opens upward when it does not fit below and there is more room above. |
|
|
274
|
+
| `direction` | Aligned Semantic's menu to the left or the right edge. The listbox has one alignment. |
|
|
275
|
+
| `tabIndex` | Set the tab order of the dropdown, the element that took focus in Semantic. The control inside the dropdown takes focus now, so a `tabIndex` on the dropdown would add a second tab stop. |
|
|
276
|
+
| `basic` | A Semantic style variant, which Semantic added as the `basic` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
277
|
+
| `button` | A Semantic style variant, which Semantic added as the `button` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
278
|
+
| `floating` | A Semantic style variant, which Semantic added as the `floating` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
279
|
+
| `fluid` | A Semantic style variant, which Semantic added as the `fluid` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
280
|
+
| `inline` | A Semantic style variant, which Semantic added as the `inline` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
281
|
+
| `item` | A Semantic style variant, which Semantic added as the `item` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
282
|
+
| `labeled` | A Semantic style variant, which Semantic added as the `labeled` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
283
|
+
| `loading` | A Semantic style variant, which Semantic added as the `loading` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
284
|
+
| `pointing` | A Semantic style variant, which Semantic added as the `pointing` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
285
|
+
| `scrolling` | A Semantic style variant, which Semantic added as the `scrolling` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
286
|
+
| `simple` | A Semantic style variant, which Semantic added as the `simple` class. The listbox does not add it, so the variant has not applied since §9.7-F1 step 3 part 2; until 2026-10-09 the name reached the dropdown element as an attribute. |
|
|
287
|
+
| `defaultSearchQuery` | The text the search filter started with, gone with `search`. |
|
|
288
|
+
| `minCharacters` | How many characters the search needed before it filtered, gone with `search`. |
|
|
289
|
+
| `defaultSelectedLabel` | Which of the chips a multiple selection shows was selected at first, gone with `multiple`. |
|
|
290
|
+
| `selectedLabel` | Which of the chips a multiple selection shows was selected, gone with `multiple`. |
|
|
291
|
+
| `renderLabel` | How each chip of a multiple selection rendered, gone with `multiple`. |
|
|
292
|
+
| `onLabelClick` | Called when a chip of a multiple selection was clicked, gone with `multiple`. |
|
|
293
|
+
| `as` | Rendered the dropdown as another element or component. The listbox renders its own markup. |
|
|
294
|
+
| `header` | A header line at the top of the menu. The listbox shows options only. |
|
|
295
|
+
| `trigger` | Replaced what the closed dropdown shows with another element. The control shows the chosen option's text, or the `placeholder`. |
|
|
296
|
+
| `text` | Overrode the text the closed dropdown shows. The control shows the chosen option's text, or the `placeholder`. |
|
|
297
|
+
| `defaultValue` | The value an uncontrolled dropdown started with. The listbox shows `value`. A form field still honours a meta `defaultValue`: the form reads it before the field renders, so it never reaches this list. |
|
|
298
|
+
|
|
299
|
+
Six names by DECISION and eight more that could not outlive them, which is why this list is longer than the changelog's. The decision half is `search`, `multiple`, `allowAdditions`, `onSearch`, `onAddItem`, `autofocus`; the rest are Semantic's own names for the machinery behind them, plus `clearable`. THE MECHANISM MATTERS AS MUCH AS THE LIST: Semantic DECLARED every one of these, so passing one used to be harmless, while `Listbox` spreads what it does not destructure onto its element — a dropped prop would have become a DOM attribute. `Dropdown.tsx` strips them instead, the same mechanism `Tooltip` uses, and warns once per name only when this repository runs the source in development: the published bundle is built for production and strips them without a word. Six names, one decision. The evidence is that nothing declares them: not the tracked examples, not the consumer-only record, and no answer to the changelog entry that asked. This is a BREAKING change for anyone who did and did not say so, which is why it is on this page rather than only in the swap PR. THE SEMVER CALL IS MADE: the owners chose to ship the exit as a MINOR (2026-09-11). The analysis here argued for a major — dropping a published propType is breaking even when nothing observed uses it — and it is left standing rather than rewritten, because the evidence and the decision are different things and a reader is entitled to both. What does not change either way is this table: it is where a consumer finds out a prop stopped working. THE OTHER 34, added on 2026-10-09. semantic-ui-react's `Dropdown` declared 65 props. The listbox reads 16 of them, 12 are among the 14 above (the other two, `onSearch` and `autofocus`, were the wrapper's own), `onClick` and `onFocus` still reach the dropdown element and work there, and `children` is ignored. The remaining 34 reached the element as attributes, a boolean one with React's warning, until the 2026-10-08 audit counted them. They are dropped the same way now, each with what it did in the table. Neither corpus sets any of them.
|
|
300
|
+
|
|
301
|
+
**Call sites.** What the codebase puts on the family, derived from the source. This was the step-1 parity surface and it is kept afterwards, because it is what any future change to the family is measured against:
|
|
302
|
+
|
|
303
|
+
| Component | Attributes at the call sites | Spreads | Rendered by |
|
|
304
|
+
| --- | --- | --- | --- |
|
|
305
|
+
| `Dropdown` | `lazyLoad`, `onChange`, `translate` | `...dropdown` | `core/engine/mapper.tsx` |
|
|
306
|
+
|
|
307
|
+
`mapper.tsx`'s spread onto `Table.Cell` is a meta node's whole rest bag and is still unfiltered at the call site — the filter is now inside the cell, which is why it is safe. All three unfiltered boundaries on this surface are now closed inside the component: the table cell at step 1, the tooltip at step 2 part 3, and the dropdown at step 3 part 2, which strips twice — once in the wrapper and once in `Listbox` at the element.
|
|
308
|
+
|
|
309
|
+
## Wrappers — what is left
|
|
310
|
+
|
|
311
|
+
None. The heading is kept so that a component reacquiring a `semantic-ui-react`
|
|
312
|
+
dependency would appear here rather than blending into the sections above.
|
|
313
|
+
|
|
314
|
+
## What the meta corpus actually uses
|
|
315
|
+
|
|
316
|
+
Every attribute name the **tracked** example corpus puts on a node of each of these views.
|
|
317
|
+
This is the "discovered set" §9.7-F1 step 0 asked for, and it is enforced total in both
|
|
318
|
+
directions by `scripts/__tests__/wrapper-prop-reference.contract.test.js`: add an example
|
|
319
|
+
that uses a new attribute, and the test names it.
|
|
320
|
+
|
|
321
|
+
Read it as an inventory, not a forwarding claim — most of these are consumed by
|
|
322
|
+
`mapper.tsx` / `TableView.tsx` and never reached the component behind them. Cross-reference
|
|
323
|
+
the per-wrapper tables above for the fate of each.
|
|
324
|
+
|
|
325
|
+
| View | Attributes in the tracked corpus | Found only in consumer metas |
|
|
326
|
+
| --- | --- | --- |
|
|
327
|
+
| `Dropdown` | `@class`, `compact`, `mapOptions`, `name`, `onChange`, `options`, `placeholder`, `style`, `styles`, `value`, `view` | — |
|
|
328
|
+
| `Select` | `compact`, `label`, `mapOptions`, `name`, `onChange`, `options`, `placeholder`, `styles`, `view` | `disabled`, `upward`, `validate` |
|
|
329
|
+
| `Table` | `@class`, `extraHeaders`, `extraItems`, `filterItems`, `group`, `headers`, `itemClassNames`, `itemsExpanded`, `name`, `relativeData`, `renderExtraItem`, `renderItem`, `renderItemCells`, `rowsPerPage`, `showIf`, `sorts`, `styles`, `usePagination`, `vertical`, `view` | `colGroup` |
|
|
330
|
+
| `Table headers[]` | `@class`, `className`, `classNameCell`, `classNameCellWrap`, `classNameHeader`, `id`, `label`, `renderCell`, `renderHeader`, `styleHeader` | `renderLabel` |
|
|
331
|
+
| `Tooltip` | `children`, `label`, `view` | — |
|
|
332
|
+
|
|
333
|
+
The last column is a step-0 audit finding, not a CI-checked fact: consumer metas are
|
|
334
|
+
untracked working files (UPGRADE-PLAN §0.8) and CI never sees them. It was recorded because
|
|
335
|
+
two of those props reached semantic-ui-react and were styled while it was the implementation —
|
|
336
|
+
a checklist derived from the demo corpus alone would have been wrong.
|
|
337
|
+
|
|
338
|
+
## Obligations per step
|
|
339
|
+
|
|
340
|
+
What each step owes beyond "the props above still work".
|
|
341
|
+
|
|
342
|
+
### Step 1 — `Table` — SHIPPED
|
|
343
|
+
|
|
344
|
+
**Effort: S, and it came in at the small end — the audit's estimate held.**
|
|
345
|
+
|
|
346
|
+
- SHIPPED: native `<table>/<thead>/<tbody>/<tfoot>/<tr>/<th>/<td>`, seven components, no `semantic-ui-react` import. The subcomponent API is unchanged, so no call site moved.
|
|
347
|
+
- DONE — the root still emits `ui` and `table`, in that position, and all 24 `<table>` class strings in the 38-example baseline are byte-identical. This was the highest-risk detail in the step and it is pinned by a unit test as well as by the snapshots.
|
|
348
|
+
- DONE — `omitProps(props, ENGINE_PROPS, FIELD_ONLY_PROPS)` is applied in all seven components, closing the `mapper.tsx:154` spread onto `Table.Cell`. Zero-diff on today's corpus (no example puts an engine prop on a `TableCells` node), so it is a latent-boundary net rather than a visible fix; `domProps.ts` now names the family.
|
|
349
|
+
- DECIDED — `verticalAlign` DROPPED, and its two call sites in `LocalDraftTableRow` with it. SUIR emitted `top aligned`; no loaded CSS selects on `aligned`, and no `.top` rule can match a `<td class="top aligned">`, so those 15 cells already rendered at the `<td>` default. Pixel-identical, and it leaves one way to align a cell instead of two, one of which never worked.
|
|
350
|
+
- DECIDED — `inverted`/`striped` KEPT. They are the only SUIR modifiers any call site passes and, unlike `celled`, they ARE styled (`table:not(.as-layout).inverted`, `table.striped tr:nth-child(2n)`). §9.9-H1 still owns whether `ErrorTable`/`ErrorContent` survive; this step deliberately did not pre-empt that.
|
|
351
|
+
- DECIDED — `fixedHeader` DELETED with its test. Unused by every call site and every meta, AND non-functional: `app__table__container--fixed-header` and its inner class have zero occurrences in `static/all.css` and in `src/style`, so it rendered two unstyled `<div>`s. Keeping it would have meant reimplementing a feature that never worked.
|
|
352
|
+
- DONE — `jest.config.js` gained a per-file threshold for `Table.tsx` at 100/100/100/100, measured from a real `--coverage` run, alongside the existing `TableView.tsx` entry.
|
|
353
|
+
- DONE — `TableView.tsx`'s `sellStyles` discard is gone (a typo for a prop that does not exist; nothing passes `cellStyles` either), and the `class=""` comment it carried is rewritten, because suppressing that attribute is now the cell's job.
|
|
354
|
+
- EXPECTED AND VERIFIED — 332 changed snapshot lines in four shapes and no others: 24 `<tbody class="">`, 94 `<tr class="">` and 199 `<td class="">` lose an empty attribute, and 15 `<td class="top aligned">` lose a dead class. Nothing else moved: same element counts per tag, same class strings on `<table>`/`<thead>`/`<th>`, same `id`/`style`/`colspan`, same visible text, and the behavioural layer green throughout.
|
|
355
|
+
|
|
356
|
+
### Step 2 — the tooltip (`TooltipPop`, `Tooltip` since §9.9-H6) — SHIPPED
|
|
357
|
+
|
|
358
|
+
**Effort: S–M as estimated, and the estimate held for the component. The specs cost more than the component did: 23 of the 38 browser tests were reference facts about the wrapper and had to be re-measured and rewritten, which is the price of having pinned the old behaviour honestly rather than loosely..**
|
|
359
|
+
|
|
360
|
+
- OBLIGATION 1 of 3 — DISCHARGED, in JavaScript. The 500 ms survives to the millisecond. What made it possible is that the bubble is MOUNTED ONLY WHILE OPEN: a bubble that is in the DOM is revealed instantly by `*:hover > .tooltip`, a rule shared with `Slider`, `Upload` and the validation tooltip whose reveal has no delay to inherit at all, at equal specificity, so mount-on-open is what buys the delay, focus-open, Escape and click-outside all at once. Measured in Chrome, not merely in jsdom: nothing is in the DOM at 0/100/300/450 ms and the bubble is there after 500. `transition-delay` was rejected — it would have meant editing a rule shared with `Slider`, `Upload` and the validation tooltip.
|
|
361
|
+
- OBLIGATION 2 of 3 — DISCHARGED AS A REMOVAL, on the maintainers' instruction, and recorded: the `dropped.on` row on this page is the per-prop record, and the changelog's entry points to it. The reason is the collision: every tooltipped node in the corpus already owns its `onClick`, so one gesture fired both the action and the tooltip and the tooltip arrived after the action had run. TWO MORE ROUTES HAD TO BE CLOSED BEFORE THE REMOVAL MEANT ANYTHING, and both were found by the browser leg, not by reasoning: (a) clicking a `<button>` FOCUSES it, and focus-open then showed the bubble instantly — suppressed by reading `onPointerDown`; (b) a touch TAP synthesises the compatibility mouse sequence, nothing follows to move the pointer away, so the emulated hover stuck and the bubble appeared 500 ms after every tap — suppressed by reading `event.pointerType`. Neither would have been FOUND in jsdom — nothing there focuses on click, and a tap has no compatibility mouse sequence — though both are pinned there now: `pointerType` needs a hand-built event to survive, because jsdom implements no `PointerEvent` and RTL's `fireEvent.pointerOver(el, {pointerType})` therefore delivers `null` (measured). The consequence, stated plainly rather than sold: a touch-only device now has no way to see a tooltip at all.
|
|
362
|
+
- OBLIGATION 3 of 3 — DISCHARGED. Escape and click-outside both dismiss, from listeners attached to `document` ONLY while open, and the Escape-from-an-unrelated-native-input case is asserted in the browser leg where it is the only place it can be asserted. Focus-to-open, `role="tooltip"`, the bubble `id` and `aria-describedby` came in as a CONSEQUENCE of obligation 2 rather than as separate features: with click gone and hover unavailable to a keyboard there would otherwise be no keyboard path to the content at all.
|
|
363
|
+
- HAZARD — HANDLED, and it turned out to bind one behaviour we would otherwise have claimed. `pointer-events: none` is set and pinned in `css.tooltip-contract.test.js`; without it the bubble swallows the pointer over its own trigger, which Playwright measured as an unhoverable trigger — and it is that same declaration which makes the pointer over the bubble land on whatever is BEHIND it, firing `mouseleave` on the host. (Not the reverse: the bubble is a child of the host, and `mouseleave` ignores descendants, so REMOVING it would make the bubble hoverable and the trigger unusable.) The consequence is that the bubble CANNOT be hoverable: the pointer over a `pointer-events: none` bubble is really over whatever is behind it. Hoverable text and a non-interactive bubble are mutually exclusive, and the bubble stays non-interactive — the same behaviour the wrapper had without `hoverable`. It also invalidated an INSTRUMENT: `document.elementFromPoint` skips such elements, so every "is the bubble painted here" assertion silently inverted. `e2e/fixtures.js` grew `paintedTopmostAt` for that, which re-enables pointer events for the probe alone.
|
|
364
|
+
- A SECOND POSITIONING DEFECT, FOUND AND FIXED ONLY BECAUSE THE BROWSER LEG EXISTS: with the component correct, the bubble still landed 559 px from its trigger. `.tooltip-host` was `inline-flex`, but a flex item is BLOCKIFIED (`inline-flex` -> `flex`, a used value with no rule to blame) and then stretched by the container's `align-items: stretch`, so inside `div.flex--col` the host came out 1222 px wide around a 35 px button and the bubble followed the host. Fixed with `width: fit-content`, which is a definite cross size so `stretch` stops applying; `width` only, because `height: fit-content` would also stop the host stretching vertically in a ROW container, which is how a wrapped button gets its height today. This is the clearest case in the step for why a CSS-positioned tooltip needs a browser gate: every jsdom suite was green while the shipped tooltip was unusable.
|
|
365
|
+
- FINDING 4 OF THE REFERENCE — CLOSED, and it took two independent fixes. `tooltip.less`'s four corner placements did put the bubble on its own trigger (`.tooltip.left`/`.right` set `top: 50%` at the same specificity as `.top`/`.bottom`, so a corner class string matched both and the axis came out over-constrained); all four are fixed by writing the losing offset back per corner rather than by raising specificity, and the retained measurement (`PLACEMENTS_OVERLAPPING_HOST`), which recorded both TOP corners sitting on their own host, is empty now. The second fix was to the VERDICT, which required every corner to align to its host's LEFT edge — something `top right` and `bottom right` cannot do, so those two would have stayed red after the CSS was right. An earlier draft of this note claimed they had been placing correctly all along; they had not. 8 of 8 now. The component still asks for `top` rather than the wrapper's `top left`: `top left` was semantic-ui-react's own default, not something a meta requested, so the bubble is centred above its trigger instead of left-aligned above it.
|
|
366
|
+
- SHIPPED — the gate. 63 tooltip tests across four files where there were 10, only 5 of which could fail if the tooltip broke (the other 5 asserted the props handed to a mock): `components/__tests__/Tooltip.test.js` (written in part 1 against the REAL `semantic-ui-react`, no `jest.mock`, and rewritten in part 3 against the in-house component), `components/__tests__/Tooltip.behavior.test.js` (new — the interaction contract), `engine/__tests__/UIRender.overlay-behavior.test.js` (extended to all three meta entry points) and `style/__tests__/css.tooltip-contract.test.js` (new — joins the emitted class string to the compiled CSS rules), plus the browser leg — 39 Playwright tests, of which 23 were reference facts about the wrapper that part 3 had to re-measure and rewrite. THE POSITIONING-PRIMITIVE DECISION, which part 1 left to the maintainers, resolved as: CSS placement off the host box, no measuring, no popper. Its costs are named where they are measured — no flip, no viewport shift, no 250 px wrap, the bubble clipped by an `overflow: hidden` ancestor, and a trigger taken OUT of normal flow leaves the host collapsed so the bubble follows the host (its own harness section). The first three were reachable only on the harness page: from a meta, popper threw before writing a coordinate, so nothing in the product ever flipped.
|
|
367
|
+
- CORRECTION to the step-0 note above: the gate was never "the SUIR-mocked wrapper unit test" alone. `UIRender.overlay-behavior.test.js` already drove the real component through the real engine for 5 clauses (delay boundary, close on leave, delay override, two a11y tripwires). What was genuinely missing was everything markup-shaped: no class pin, no portal-location pin, no click path, no Escape, no click-outside, no close delay, no object-`tooltip` passthrough, no prop-leak boundary. Part 1 extended that file rather than founding it.
|
|
368
|
+
- CORRECTION to "the corpus renders zero tooltips": true of THIS component only. The corpus renders 5 tooltips today, all in the `slider` example and all snapshot-gated — they come from a second, separate component, `components/TooltipBubble.tsx` (`components/Tooltip.tsx` until §9.9-H6): a few lines, CSS-only, an inline `<span>`, no portal and no JS positioning, used by `Slider`, `modules/upload/views/Upload.tsx` and `withFormSetup`'s validation-error tooltip, and styled by 41 rules in `style/components/tooltip.less`. It is evidence for the positioning decision, and it was a naming trap until §9.9-H6 renamed both: `form/utils.tsx` imported BOTH.
|
|
369
|
+
- CORRECTION — the biggest finding, and it invalidates an instruction this step was given: "keep emitting `ui popup`-compatible classNames so the current CSS continues to apply" rests on a false premise. No `.ui.popup` rule applies today, because the portal mounts outside `.ui-render`. See the CSS contract in the `Tooltip` section above; measured twice, by selector matching and by real-Chrome computed style.
|
|
370
|
+
- DONE (was STILL OWED) — the unfiltered DOM boundary is closed. Part 1 pinned it as a DEFECT rather than as a contract: `view`, `index` and `symbol` all reached the bubble as HTML attributes (`view="Tooltip"` on every `view: "Tooltip"` node, via the `mapper.tsx` spread). Part 3 applies `omitProps(props, ENGINE_PROPS, FIELD_ONLY_PROPS)` and that assertion is now `toEqual([])`.
|
|
371
|
+
- DECIDED (was STILL OWED) — `on` is DROPPED, on the maintainers' instruction. SUIR's default was `['click', 'hover']`, so every tooltip was also a click target and none opened on focus. Hover and focus are the triggers now; the removal and its two guards are recorded in OBLIGATION 2 above and per-prop under `dropped.on`.
|
|
372
|
+
- DECIDED (was STILL OWED) — the trigger may be anything. `React.Children.only` went with the portal, so the `items` form of `view: "Tooltip"`, which threw and made the engine draw its error diagnostic in place of the node (losing the trigger too), now renders the trigger AND the tooltip. `UIRender.overlay-behavior.test.js` pins the new behaviour, in the test that pinned the old failure until it was flipped, and `docs/SUPPORTED-VIEWS.md` records the flip.
|
|
373
|
+
- THE POSITIONING DECISION — RESOLVED as zero-dep CSS placement off the host box (see the SHIPPED entry above for the costs). The data it was decided on, kept because it is what made the decision defensible: flip was ACTIVE (`enabled: !pinned`, and the placement class carried Popper's resolved placement, so a flip is observable in the DOM); overflow clamping is OFF (`preventOverflow` is `enabled: !!offset` and nothing sets `offset`); the arrow is CSS `:before`, not a positioned element; and scroll/resize repositioning is on. So parity is **flip yes, shift no** — §9.7-F1.2's claim that the zero-dep option loses "flip AND overflow handling" is half right. Coordinates are unavoidable while the bubble portals out of the tree; an inline tooltip needs none (and the in-house `TooltipBubble.tsx`, `Tooltip.tsx` until §9.9-H6, proves the pattern ships) but would be clipped at the corpus's own use sites, which sit inside `Expand` → `AnimateHeight`'s `overflow: hidden`. Neither option is ruled in; "no positioning code" and "inline only" are ruled out.
|
|
374
|
+
- WHAT THE GATE CANNOT SAY, so the replacement is not judged on it: everything positional. jsdom reports 0×0 for every rect, so flip, the resulting placement-class change, shift, the arrow geometry, the 250 px wrap, clipping, stacking, painted style, real pointer travel and screen-reader announcement are all inexpressible. They are named one by one against the §9.5 Playwright item, which now blocks THIS step's completion rather than only F1's.
|
|
375
|
+
- DONE (was FREE CLEANUP) — the `TooltipPop` chain in `modules/form/utils.tsx` was dead at four sites — the import, `withForm`'s `Tooltip = TooltipPop` default parameter, the pass-through into `withFormSetup({… Tooltip})`, and the destructure that never used it — and all four are gone. The import beside it, which the validation-error tooltip uses, stays: it is `TooltipBubble` since §9.9-H6.
|
|
376
|
+
|
|
377
|
+
### Step 3 — `Dropdown` — SHIPPED
|
|
378
|
+
|
|
379
|
+
**Effort: L (came in at the L; the matrix was the cost, as predicted).**
|
|
380
|
+
|
|
381
|
+
- The L was NOT in `search`/`multiple`/`allowAdditions`/`clearable` — nothing used them, and they were REMOVED rather than reimplemented. It was in the keyboard/a11y matrix, which had to be built rather than ported: `Home`/`End`, `PageUp`/`PageDown` and typeahead were measured ABSENT from the library, so there was nothing to preserve and everything to write.
|
|
382
|
+
- MET: `displayName = 'Dropdown'` and the named-vs-default export split both survive — `modules/form/utils.tsx` still branches on `InputComponent.displayName`, and only the named export carries it.
|
|
383
|
+
- MET, and one addition: `role="listbox"`, `aria-expanded`, `aria-disabled` and `tabIndex=-1` when disabled are all emitted. `aria-disabled` was MISSING in the first draft and caught by the behavioural suite — a `role="listbox"` div cannot carry the native attribute, so being unavailable has to be said three ways. Added beyond the library: `aria-activedescendant`, which is how the keyboard cursor is announced now that moving no longer commits.
|
|
384
|
+
- DECIDED: tier 2 was resolved as REMOVAL, on the evidence that nothing in either corpus or the consumer-only record declares any of them. The removed names are stripped at the boundary. They warn once each only when this repository runs the source in development; the published bundle strips them silently, so the `Dropped` table below is the record a host has.
|
|
385
|
+
- DELIVERED: both `classContract` and `behaviourContract` are measured and present above. The class contract is pinned token by token in `src/style/__tests__/css.dropdown-contract.test.js` (what each class is worth in scoped rules), and the behaviour contract is the WAI-ARIA listbox model — arrows move a cursor, Enter commits, Escape reports nothing. The same keys work in the select-only combobox pattern the control follows now.
|
|
386
|
+
|
|
387
|
+
## What this page does and does not guarantee
|
|
388
|
+
|
|
389
|
+
Guaranteed, because it is derived from source and checked in CI: the import inventory; each
|
|
390
|
+
component's consumed set and its line count; which boundary lists each one applies; the
|
|
391
|
+
attributes and spreads written on the semantic-ui-react element; the native element behind
|
|
392
|
+
every in-house subcomponent, and that no in-house file reaches semantic-ui-react by import,
|
|
393
|
+
`require`, `jest.mock` or dynamic `import`; every attribute the codebase puts on the `Table`
|
|
394
|
+
family; that no call site passes a prop the page says was dropped; and that every one of
|
|
395
|
+
those has a curated description.
|
|
396
|
+
|
|
397
|
+
Also guaranteed: the tracked-corpus attribute inventory, enforced total by the contract
|
|
398
|
+
test against the real `EXAMPLES` manifest.
|
|
399
|
+
|
|
400
|
+
Not guaranteed, and deliberately so:
|
|
401
|
+
|
|
402
|
+
- **the rest spread is still open.** A rest spread cannot be closed by static analysis, so a
|
|
403
|
+
meta may pass a name nobody anticipated. What changed with the exit is where it lands: not
|
|
404
|
+
into semantic-ui-react, but onto a DOM element, or into a component's own dropped-prop
|
|
405
|
+
list where it is stripped and warned about once. The inventories below are what was found,
|
|
406
|
+
not a proof of what is possible.
|
|
407
|
+
- **the emitted className strings.** The generator reads which props a component consumes,
|
|
408
|
+
not what it composes them into. `ui table` surviving on the root is asserted by
|
|
409
|
+
`src/core/components/__tests__/Table.test.js` and by the 38-example DOM baseline, not here.
|
|
410
|
+
- **the dropped list is not proof of absence.** It names the props that had a curated entry
|
|
411
|
+
while the component was a wrapper, plus the wider semantic-ui-react surface recorded in
|
|
412
|
+
prose. A caller could always pass an undocumented semantic prop; those now land on the
|
|
413
|
+
element or draw a React warning, and no static check can enumerate them.
|
|
414
|
+
- **corpus evidence is initial-render only.** The step-0 instrumented render recorded the
|
|
415
|
+
props reaching semantic-ui-react on first paint, so props that only appear once a
|
|
416
|
+
control is interacted with — opening a dropdown, switching a tab — were never observed.
|
|
417
|
+
Separately, a node inside an unrendered branch contributes nothing at all, which is why
|
|
418
|
+
the corpus produced no tooltip evidence: both declarations sit in a `Tabs` panel that is
|
|
419
|
+
not the active one. The tooltip rows above are read off the wrapper source and a direct
|
|
420
|
+
probe instead.
|
|
421
|
+
- **consumer metas are not re-scanned.** They are untracked by design.
|
|
422
|
+
- **the prose.** Curated sentences are reviewed documentation, not machine-checked facts.
|