@0001-labs/design-system-1 0.3.0-alpha.28 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DS1/0-face/button-label.ts +28 -0
- package/DS1/0-face/calendar.ts +6 -4
- package/DS1/0-face/carousel.ts +70 -0
- package/DS1/0-face/constraint-panel.ts +443 -0
- package/DS1/0-face/constraint-site.ts +201 -0
- package/DS1/0-face/constraints.ts +308 -0
- package/DS1/0-face/copy-text.ts +1 -1
- package/DS1/0-face/cut-fade.ts +312 -0
- package/DS1/0-face/define.ts +30 -2
- package/DS1/0-face/face-correction.ts +96 -0
- package/DS1/0-face/failures.ts +32 -0
- package/DS1/0-face/fault-lines.ts +159 -0
- package/DS1/0-face/feedback-overlays.ts +5 -3
- package/DS1/0-face/feedback.ts +3 -0
- package/DS1/0-face/focus-vision.swift +31 -0
- package/DS1/0-face/focus.ts +181 -0
- package/DS1/0-face/google-face-metrics.json +102 -0
- package/DS1/0-face/grid.ts +61 -4
- package/DS1/0-face/i18n.ts +36 -18
- package/DS1/0-face/layout-inspector.ts +124 -98
- package/DS1/0-face/preference-options.ts +4 -0
- package/DS1/0-face/scaling.ts +21 -3
- package/DS1/0-face/shape.ts +43 -0
- package/DS1/0-face/text-contrast.ts +164 -0
- package/DS1/0-face/theme-bootstrap.js +43 -0
- package/DS1/0-face/toast-queue.ts +7 -1
- package/DS1/0-face/translations/da.json +10 -1
- package/DS1/0-face/translations/de.json +10 -1
- package/DS1/0-face/translations/en.json +10 -1
- package/DS1/0-face/translations/es.json +10 -1
- package/DS1/0-face/translations/fi.json +10 -1
- package/DS1/0-face/translations/fr.json +10 -1
- package/DS1/0-face/translations/is.json +10 -1
- package/DS1/0-face/translations/it.json +10 -1
- package/DS1/0-face/translations/ja.json +10 -1
- package/DS1/0-face/translations/ko.json +10 -1
- package/DS1/0-face/translations/nb.json +10 -1
- package/DS1/0-face/translations/pt-BR.json +10 -1
- package/DS1/0-face/translations/pt.json +10 -1
- package/DS1/0-face/translations/sv.json +10 -1
- package/DS1/0-face/translations/zh.json +10 -1
- package/DS1/0-face/word-wrap.ts +113 -0
- package/DS1/1-root/card.css +47 -20
- package/DS1/1-root/carousel.css +7 -0
- package/DS1/1-root/cjk.css +1 -1
- package/DS1/1-root/component-tokens.css +3 -2
- package/DS1/1-root/context.css +44 -6
- package/DS1/1-root/controls.css +99 -8
- package/DS1/1-root/document.css +9 -1
- package/DS1/1-root/empty.css +46 -5
- package/DS1/1-root/figures.css +50 -3
- package/DS1/1-root/fonts.css +1 -1
- package/DS1/1-root/footer.css +147 -16
- package/DS1/1-root/foundation.ts +60 -0
- package/DS1/1-root/guide.css +35 -0
- package/DS1/1-root/header.css +30 -9
- package/DS1/1-root/material.css +67 -0
- package/DS1/1-root/notice.css +10 -2
- package/DS1/1-root/one.css +15 -7
- package/DS1/1-root/progress.css +9 -1
- package/DS1/1-root/row.css +68 -2
- package/DS1/1-root/table.css +47 -4
- package/DS1/1-root/text.css +26 -0
- package/DS1/2-core/button-split.ts +10 -5
- package/DS1/2-core/chart/chart.css +71 -2
- package/DS1/2-core/chart/grid-chart.ts +2 -1
- package/DS1/2-core/ds-activity.ts +32 -0
- package/DS1/2-core/ds-app-chrome.ts +1 -0
- package/DS1/2-core/ds-avatar.ts +75 -7
- package/DS1/2-core/ds-badge.ts +8 -1
- package/DS1/2-core/ds-button.ts +7 -1
- package/DS1/2-core/ds-chart.ts +184 -49
- package/DS1/2-core/ds-cycle.ts +27 -186
- package/DS1/2-core/ds-device-bezel.ts +1 -0
- package/DS1/2-core/ds-empty.ts +6 -4
- package/DS1/2-core/ds-input.ts +23 -3
- package/DS1/2-core/ds-message.ts +22 -0
- package/DS1/2-core/ds-number.ts +349 -0
- package/DS1/2-core/ds-progress.ts +3 -0
- package/DS1/2-core/ds-radio.ts +3 -0
- package/DS1/2-core/ds-stat.ts +3 -0
- package/DS1/2-core/ds-switch.ts +5 -1
- package/DS1/2-core/ds-tag.ts +9 -2
- package/DS1/2-core/ds-text.ts +7 -0
- package/DS1/2-core/ds-token.ts +3 -0
- package/DS1/2-core/ds-tooltip.ts +17 -2
- package/DS1/2-core/ds-window.ts +1 -0
- package/DS1/2-core/generated/ds-icon-map.ts +47 -5
- package/DS1/2-core/generated/icons-extra.ts +24 -3
- package/DS1/2-core/generated/icons-immediate.ts +3 -3
- package/DS1/2-core/number-expression.ts +64 -0
- package/DS1/2-core/styles/ds-activity.css +16 -0
- package/DS1/2-core/styles/ds-badge.css +4 -1
- package/DS1/2-core/styles/ds-button-host.css +47 -13
- package/DS1/2-core/styles/ds-button-split.css +8 -0
- package/DS1/2-core/styles/ds-button.css +94 -20
- package/DS1/2-core/styles/ds-card.css +6 -0
- package/DS1/2-core/styles/ds-checkbox.css +20 -8
- package/DS1/2-core/styles/ds-image.css +2 -1
- package/DS1/2-core/styles/ds-input.css +37 -4
- package/DS1/2-core/styles/ds-number.css +127 -0
- package/DS1/2-core/styles/ds-radio.css +4 -1
- package/DS1/2-core/styles/ds-switch.css +34 -4
- package/DS1/2-core/styles/ds-tag.css +34 -6
- package/DS1/2-core/styles/ds-text.css +13 -4
- package/DS1/2-core/styles/ds-token.css +4 -1
- package/DS1/2-core/styles/ds-tooltip.css +13 -7
- package/DS1/3-unit/calendar-base.ts +5 -2
- package/DS1/3-unit/context-trigger.ts +29 -2
- package/DS1/3-unit/ds-calendar.ts +711 -37
- package/DS1/3-unit/ds-carousel.ts +13 -1
- package/DS1/3-unit/ds-context.ts +40 -2
- package/DS1/3-unit/ds-form.ts +47 -11
- package/DS1/3-unit/ds-list.ts +31 -3
- package/DS1/3-unit/ds-matrix.ts +3 -0
- package/DS1/3-unit/ds-menu.ts +9 -5
- package/DS1/3-unit/ds-row.ts +17 -2
- package/DS1/3-unit/ds-select.ts +1 -1
- package/DS1/3-unit/ds-sidebar.ts +18 -3
- package/DS1/3-unit/ds-table-of-contents.ts +166 -0
- package/DS1/3-unit/ds-table.ts +2 -1
- package/DS1/3-unit/ds-tabs.ts +40 -2
- package/DS1/3-unit/styles/ds-calendar.css +356 -42
- package/DS1/3-unit/styles/ds-context.css +38 -0
- package/DS1/3-unit/styles/ds-list.css +26 -1
- package/DS1/3-unit/styles/ds-matrix.css +4 -1
- package/DS1/3-unit/styles/ds-row.css +39 -0
- package/DS1/3-unit/styles/ds-select.css +22 -12
- package/DS1/3-unit/styles/ds-sidebar.css +16 -2
- package/DS1/3-unit/styles/ds-table-of-contents.css +40 -0
- package/DS1/3-unit/styles/ds-tabs.css +95 -0
- package/DS1/4-page/ds-container.ts +2 -1
- package/DS1/4-page/ds-document.ts +3 -0
- package/DS1/4-page/ds-footer.ts +93 -18
- package/DS1/4-page/ds-header.ts +5 -1
- package/DS1/4-page/ds-overlay.ts +8 -3
- package/DS1/4-page/ds-page.ts +22 -1
- package/DS1/4-page/email.ts +7 -4
- package/DS1/4-page/styles/ds-container.css +0 -1
- package/DS1/4-page/styles/ds-overlay.css +7 -0
- package/DS1/4-page/styles/ds-page.css +10 -0
- package/DS1/5-visual-kit/app-chrome.ts +129 -0
- package/DS1/5-visual-kit/bezels.ts +394 -0
- package/DS1/5-visual-kit/browser-icons.LICENSE +53 -0
- package/DS1/5-visual-kit/browser-icons.ts +47 -0
- package/DS1/5-visual-kit/browser-styles.ts +53 -0
- package/DS1/5-visual-kit/device-bezel.ts +55 -0
- package/DS1/5-visual-kit/instagram-frame.ts +15 -0
- package/DS1/5-visual-kit/instagram.ts +41 -0
- package/DS1/5-visual-kit/mobile-chrome.ts +25 -0
- package/DS1/5-visual-kit/native-icon-paths.ts +145 -0
- package/DS1/5-visual-kit/window.ts +22 -0
- package/DS1/components.ts +1 -0
- package/DS1/index.ts +14 -1
- package/DS1/react/choice.ts +4 -2
- package/DS1/react/context.ts +11 -6
- package/DS1/react/empty.ts +2 -2
- package/DS1/react/footer.ts +5 -5
- package/DS1/react/header.ts +1 -1
- package/DS1/react/message.ts +4 -2
- package/DS1/react/number.ts +53 -0
- package/DS1/react/sidebar.ts +4 -2
- package/DS1/react/table-of-contents.ts +28 -0
- package/DS1/x-flag/LICENSE.md +26 -0
- package/DS1/x-flag/ac.svg +1 -0
- package/DS1/x-flag/ad.svg +1 -0
- package/DS1/x-flag/ae.svg +1 -0
- package/DS1/x-flag/af.svg +1 -0
- package/DS1/x-flag/ag.svg +1 -0
- package/DS1/x-flag/ai.svg +1 -0
- package/DS1/x-flag/al.svg +1 -0
- package/DS1/x-flag/am.svg +1 -0
- package/DS1/x-flag/ao.svg +1 -0
- package/DS1/x-flag/aq.svg +1 -0
- package/DS1/x-flag/ar.svg +1 -0
- package/DS1/x-flag/as.svg +1 -0
- package/DS1/x-flag/at.svg +1 -0
- package/DS1/x-flag/au.svg +1 -0
- package/DS1/x-flag/aw.svg +1 -0
- package/DS1/x-flag/ax.svg +1 -0
- package/DS1/x-flag/az.svg +1 -0
- package/DS1/x-flag/ba.svg +1 -0
- package/DS1/x-flag/bb.svg +1 -0
- package/DS1/x-flag/bd.svg +1 -0
- package/DS1/x-flag/be.svg +1 -0
- package/DS1/x-flag/bf.svg +1 -0
- package/DS1/x-flag/bg.svg +1 -0
- package/DS1/x-flag/bh.svg +1 -0
- package/DS1/x-flag/bi.svg +1 -0
- package/DS1/x-flag/bj.svg +1 -0
- package/DS1/x-flag/bl.svg +1 -0
- package/DS1/x-flag/bm.svg +1 -0
- package/DS1/x-flag/bn.svg +1 -0
- package/DS1/x-flag/bo.svg +1 -0
- package/DS1/x-flag/bq-bo.svg +1 -0
- package/DS1/x-flag/bq-sa.svg +1 -0
- package/DS1/x-flag/bq-se.svg +1 -0
- package/DS1/x-flag/bq.svg +1 -0
- package/DS1/x-flag/br.svg +1 -0
- package/DS1/x-flag/bs.svg +1 -0
- package/DS1/x-flag/bt.svg +1 -0
- package/DS1/x-flag/bv.svg +1 -0
- package/DS1/x-flag/bw.svg +1 -0
- package/DS1/x-flag/by.svg +1 -0
- package/DS1/x-flag/bz.svg +1 -0
- package/DS1/x-flag/ca.svg +1 -0
- package/DS1/x-flag/cc.svg +1 -0
- package/DS1/x-flag/cd.svg +1 -0
- package/DS1/x-flag/cf.svg +1 -0
- package/DS1/x-flag/cg.svg +1 -0
- package/DS1/x-flag/ch.svg +1 -0
- package/DS1/x-flag/ci.svg +1 -0
- package/DS1/x-flag/ck.svg +1 -0
- package/DS1/x-flag/cl.svg +1 -0
- package/DS1/x-flag/cm.svg +1 -0
- package/DS1/x-flag/cn.svg +1 -0
- package/DS1/x-flag/co.svg +1 -0
- package/DS1/x-flag/cr.svg +1 -0
- package/DS1/x-flag/cu.svg +1 -0
- package/DS1/x-flag/cv.svg +1 -0
- package/DS1/x-flag/cw.svg +1 -0
- package/DS1/x-flag/cx.svg +1 -0
- package/DS1/x-flag/cy.svg +1 -0
- package/DS1/x-flag/cz.svg +1 -0
- package/DS1/x-flag/de.svg +1 -0
- package/DS1/x-flag/dj.svg +1 -0
- package/DS1/x-flag/dk.svg +1 -0
- package/DS1/x-flag/dm.svg +1 -0
- package/DS1/x-flag/do.svg +1 -0
- package/DS1/x-flag/dz.svg +1 -0
- package/DS1/x-flag/ec.svg +1 -0
- package/DS1/x-flag/ee.svg +1 -0
- package/DS1/x-flag/eg.svg +1 -0
- package/DS1/x-flag/eh.svg +1 -0
- package/DS1/x-flag/er.svg +1 -0
- package/DS1/x-flag/es-ct.svg +1 -0
- package/DS1/x-flag/es.svg +1 -0
- package/DS1/x-flag/et.svg +1 -0
- package/DS1/x-flag/eu.svg +1 -0
- package/DS1/x-flag/fi.svg +1 -0
- package/DS1/x-flag/fj.svg +1 -0
- package/DS1/x-flag/fk.svg +1 -0
- package/DS1/x-flag/fm.svg +1 -0
- package/DS1/x-flag/fo.svg +1 -0
- package/DS1/x-flag/fr.svg +1 -0
- package/DS1/x-flag/ga.svg +1 -0
- package/DS1/x-flag/gb-eng.svg +1 -0
- package/DS1/x-flag/gb-nir.svg +1 -0
- package/DS1/x-flag/gb-sct.svg +1 -0
- package/DS1/x-flag/gb-wls.svg +1 -0
- package/DS1/x-flag/gb.svg +1 -0
- package/DS1/x-flag/gd.svg +1 -0
- package/DS1/x-flag/ge.svg +1 -0
- package/DS1/x-flag/gf.svg +1 -0
- package/DS1/x-flag/gg.svg +1 -0
- package/DS1/x-flag/gh.svg +1 -0
- package/DS1/x-flag/gi.svg +1 -0
- package/DS1/x-flag/gl.svg +1 -0
- package/DS1/x-flag/gm.svg +1 -0
- package/DS1/x-flag/gn.svg +1 -0
- package/DS1/x-flag/gp.svg +1 -0
- package/DS1/x-flag/gq.svg +1 -0
- package/DS1/x-flag/gr.svg +1 -0
- package/DS1/x-flag/gs.svg +1 -0
- package/DS1/x-flag/gt.svg +1 -0
- package/DS1/x-flag/gu.svg +1 -0
- package/DS1/x-flag/gw.svg +1 -0
- package/DS1/x-flag/gy.svg +1 -0
- package/DS1/x-flag/hk.svg +1 -0
- package/DS1/x-flag/hm.svg +1 -0
- package/DS1/x-flag/hn.svg +1 -0
- package/DS1/x-flag/hr.svg +1 -0
- package/DS1/x-flag/ht.svg +1 -0
- package/DS1/x-flag/hu.svg +1 -0
- package/DS1/x-flag/ic.svg +1 -0
- package/DS1/x-flag/id.svg +1 -0
- package/DS1/x-flag/ie.svg +1 -0
- package/DS1/x-flag/il.svg +1 -0
- package/DS1/x-flag/im.svg +1 -0
- package/DS1/x-flag/in.svg +1 -0
- package/DS1/x-flag/io.svg +1 -0
- package/DS1/x-flag/iq.svg +1 -0
- package/DS1/x-flag/ir.svg +1 -0
- package/DS1/x-flag/is.svg +1 -0
- package/DS1/x-flag/it.svg +1 -0
- package/DS1/x-flag/je.svg +1 -0
- package/DS1/x-flag/jm.svg +1 -0
- package/DS1/x-flag/jo.svg +1 -0
- package/DS1/x-flag/jp.svg +1 -0
- package/DS1/x-flag/ke.svg +1 -0
- package/DS1/x-flag/kg.svg +1 -0
- package/DS1/x-flag/kh.svg +1 -0
- package/DS1/x-flag/ki.svg +1 -0
- package/DS1/x-flag/km.svg +1 -0
- package/DS1/x-flag/kn.svg +1 -0
- package/DS1/x-flag/kp.svg +1 -0
- package/DS1/x-flag/kr.svg +1 -0
- package/DS1/x-flag/kw.svg +1 -0
- package/DS1/x-flag/ky.svg +1 -0
- package/DS1/x-flag/kz.svg +1 -0
- package/DS1/x-flag/la.svg +1 -0
- package/DS1/x-flag/lb.svg +1 -0
- package/DS1/x-flag/lc.svg +1 -0
- package/DS1/x-flag/li.svg +1 -0
- package/DS1/x-flag/lk.svg +1 -0
- package/DS1/x-flag/lr.svg +1 -0
- package/DS1/x-flag/ls.svg +1 -0
- package/DS1/x-flag/lt.svg +1 -0
- package/DS1/x-flag/lu.svg +1 -0
- package/DS1/x-flag/lv.svg +1 -0
- package/DS1/x-flag/ly.svg +1 -0
- package/DS1/x-flag/ma.svg +1 -0
- package/DS1/x-flag/mc.svg +1 -0
- package/DS1/x-flag/md.svg +1 -0
- package/DS1/x-flag/me.svg +1 -0
- package/DS1/x-flag/mf.svg +1 -0
- package/DS1/x-flag/mg.svg +1 -0
- package/DS1/x-flag/mh.svg +1 -0
- package/DS1/x-flag/mk.svg +1 -0
- package/DS1/x-flag/ml.svg +1 -0
- package/DS1/x-flag/mm.svg +1 -0
- package/DS1/x-flag/mn.svg +1 -0
- package/DS1/x-flag/mo.svg +1 -0
- package/DS1/x-flag/mp.svg +1 -0
- package/DS1/x-flag/mq.svg +1 -0
- package/DS1/x-flag/mr.svg +1 -0
- package/DS1/x-flag/ms.svg +1 -0
- package/DS1/x-flag/mt.svg +1 -0
- package/DS1/x-flag/mu.svg +1 -0
- package/DS1/x-flag/mv.svg +1 -0
- package/DS1/x-flag/mw.svg +1 -0
- package/DS1/x-flag/mx.svg +1 -0
- package/DS1/x-flag/my.svg +1 -0
- package/DS1/x-flag/mz.svg +1 -0
- package/DS1/x-flag/na.svg +1 -0
- package/DS1/x-flag/nc.svg +1 -0
- package/DS1/x-flag/ne.svg +1 -0
- package/DS1/x-flag/nf.svg +1 -0
- package/DS1/x-flag/ng.svg +1 -0
- package/DS1/x-flag/ni.svg +1 -0
- package/DS1/x-flag/nl.svg +1 -0
- package/DS1/x-flag/no.svg +1 -0
- package/DS1/x-flag/np.svg +1 -0
- package/DS1/x-flag/nr.svg +1 -0
- package/DS1/x-flag/nu.svg +1 -0
- package/DS1/x-flag/nz.svg +1 -0
- package/DS1/x-flag/om.svg +1 -0
- package/DS1/x-flag/pa.svg +1 -0
- package/DS1/x-flag/pe.svg +1 -0
- package/DS1/x-flag/pf.svg +1 -0
- package/DS1/x-flag/pg.svg +1 -0
- package/DS1/x-flag/ph.svg +1 -0
- package/DS1/x-flag/pk.svg +1 -0
- package/DS1/x-flag/pl.svg +1 -0
- package/DS1/x-flag/pm.svg +1 -0
- package/DS1/x-flag/pn.svg +1 -0
- package/DS1/x-flag/pr.svg +1 -0
- package/DS1/x-flag/ps.svg +1 -0
- package/DS1/x-flag/pt.svg +1 -0
- package/DS1/x-flag/pw.svg +1 -0
- package/DS1/x-flag/py.svg +1 -0
- package/DS1/x-flag/qa.svg +1 -0
- package/DS1/x-flag/re.svg +1 -0
- package/DS1/x-flag/ro.svg +1 -0
- package/DS1/x-flag/rs.svg +1 -0
- package/DS1/x-flag/ru.svg +1 -0
- package/DS1/x-flag/rw.svg +1 -0
- package/DS1/x-flag/sa.svg +1 -0
- package/DS1/x-flag/sb.svg +1 -0
- package/DS1/x-flag/sc.svg +1 -0
- package/DS1/x-flag/sd.svg +1 -0
- package/DS1/x-flag/se.svg +1 -0
- package/DS1/x-flag/sg.svg +1 -0
- package/DS1/x-flag/sh.svg +1 -0
- package/DS1/x-flag/si.svg +1 -0
- package/DS1/x-flag/sj.svg +1 -0
- package/DS1/x-flag/sk.svg +1 -0
- package/DS1/x-flag/sl.svg +1 -0
- package/DS1/x-flag/sm.svg +1 -0
- package/DS1/x-flag/sn.svg +1 -0
- package/DS1/x-flag/so.svg +1 -0
- package/DS1/x-flag/sr.svg +1 -0
- package/DS1/x-flag/ss.svg +1 -0
- package/DS1/x-flag/st.svg +1 -0
- package/DS1/x-flag/sv.svg +1 -0
- package/DS1/x-flag/sx.svg +1 -0
- package/DS1/x-flag/sy.svg +1 -0
- package/DS1/x-flag/sz.svg +1 -0
- package/DS1/x-flag/ta.svg +1 -0
- package/DS1/x-flag/tc.svg +1 -0
- package/DS1/x-flag/td.svg +1 -0
- package/DS1/x-flag/tf.svg +1 -0
- package/DS1/x-flag/tg.svg +1 -0
- package/DS1/x-flag/th.svg +1 -0
- package/DS1/x-flag/tj.svg +1 -0
- package/DS1/x-flag/tk.svg +1 -0
- package/DS1/x-flag/tl.svg +1 -0
- package/DS1/x-flag/tm.svg +1 -0
- package/DS1/x-flag/tn.svg +1 -0
- package/DS1/x-flag/to.svg +1 -0
- package/DS1/x-flag/tr.svg +1 -0
- package/DS1/x-flag/tt.svg +1 -0
- package/DS1/x-flag/tv.svg +1 -0
- package/DS1/x-flag/tw.svg +1 -0
- package/DS1/x-flag/tz.svg +1 -0
- package/DS1/x-flag/ua.svg +1 -0
- package/DS1/x-flag/ug.svg +1 -0
- package/DS1/x-flag/um.svg +1 -0
- package/DS1/x-flag/us.svg +1 -0
- package/DS1/x-flag/uy.svg +1 -0
- package/DS1/x-flag/uz.svg +1 -0
- package/DS1/x-flag/va.svg +1 -0
- package/DS1/x-flag/vc.svg +1 -0
- package/DS1/x-flag/ve.svg +1 -0
- package/DS1/x-flag/vg.svg +1 -0
- package/DS1/x-flag/vi.svg +1 -0
- package/DS1/x-flag/vn.svg +1 -0
- package/DS1/x-flag/vu.svg +1 -0
- package/DS1/x-flag/wf.svg +1 -0
- package/DS1/x-flag/ws.svg +1 -0
- package/DS1/x-flag/xk.svg +1 -0
- package/DS1/x-flag/ye.svg +1 -0
- package/DS1/x-flag/yt.svg +1 -0
- package/DS1/x-flag/za.svg +1 -0
- package/DS1/x-flag/zm.svg +1 -0
- package/DS1/x-flag/zw.svg +1 -0
- package/DS1/x-icon/android.svg +9 -0
- package/DS1/x-icon/arrange-check.svg +1 -1
- package/DS1/x-icon/arrange-page.svg +1 -1
- package/DS1/x-icon/chrome.svg +7 -0
- package/DS1/x-icon/edge-brand.svg +6 -0
- package/DS1/x-icon/firefox.svg +4 -0
- package/DS1/x-icon/health.svg +3 -0
- package/DS1/x-icon/left.svg +2 -3
- package/DS1/x-icon/linux.svg +1 -0
- package/DS1/x-icon/material.svg +1 -0
- package/DS1/x-icon/milestone-planned.svg +3 -0
- package/DS1/x-icon/milestone.svg +3 -0
- package/DS1/x-icon/more.svg +1 -5
- package/DS1/x-icon/network.svg +3 -0
- package/DS1/x-icon/opera.svg +4 -0
- package/DS1/x-icon/prediction.svg +3 -0
- package/DS1/x-icon/priority-high.svg +3 -0
- package/DS1/x-icon/priority-low.svg +3 -0
- package/DS1/x-icon/priority-medium.svg +3 -0
- package/DS1/x-icon/project.svg +3 -0
- package/DS1/x-icon/redo.svg +2 -2
- package/DS1/x-icon/repeat-small.svg +3 -0
- package/DS1/x-icon/safari.svg +4 -0
- package/DS1/x-icon/scaling.svg +3 -0
- package/DS1/x-icon/tabs.svg +4 -0
- package/DS1/x-icon/windows.svg +5 -0
- package/README.md +3 -3
- package/dist/0-face/button-label.d.ts +5 -0
- package/dist/0-face/button-label.d.ts.map +1 -0
- package/dist/0-face/button-label.js +31 -0
- package/dist/0-face/calendar.d.ts +1 -1
- package/dist/0-face/calendar.d.ts.map +1 -1
- package/dist/0-face/calendar.js +6 -3
- package/dist/0-face/carousel.d.ts +9 -0
- package/dist/0-face/carousel.d.ts.map +1 -1
- package/dist/0-face/carousel.js +80 -0
- package/dist/0-face/constraint-panel.d.ts +43 -0
- package/dist/0-face/constraint-panel.d.ts.map +1 -0
- package/dist/0-face/constraint-panel.js +451 -0
- package/dist/0-face/constraint-site.d.ts +73 -0
- package/dist/0-face/constraint-site.d.ts.map +1 -0
- package/dist/0-face/constraint-site.js +186 -0
- package/dist/0-face/constraints.d.ts +47 -0
- package/dist/0-face/constraints.d.ts.map +1 -0
- package/dist/0-face/constraints.js +274 -0
- package/dist/0-face/copy-text.js +1 -1
- package/dist/0-face/cut-fade.d.ts +112 -0
- package/dist/0-face/cut-fade.d.ts.map +1 -0
- package/dist/0-face/cut-fade.js +274 -0
- package/dist/0-face/define.d.ts.map +1 -1
- package/dist/0-face/define.js +24 -3
- package/dist/0-face/face-correction.d.ts +51 -0
- package/dist/0-face/face-correction.d.ts.map +1 -0
- package/dist/0-face/face-correction.js +80 -0
- package/dist/0-face/failures.d.ts +16 -0
- package/dist/0-face/failures.d.ts.map +1 -0
- package/dist/0-face/failures.js +21 -0
- package/dist/0-face/fault-lines.d.ts +20 -0
- package/dist/0-face/fault-lines.d.ts.map +1 -0
- package/dist/0-face/fault-lines.js +172 -0
- package/dist/0-face/feedback-overlays.d.ts.map +1 -1
- package/dist/0-face/feedback-overlays.js +5 -3
- package/dist/0-face/feedback.d.ts +2 -0
- package/dist/0-face/feedback.d.ts.map +1 -1
- package/dist/0-face/feedback.js +1 -0
- package/dist/0-face/focus.d.ts +71 -0
- package/dist/0-face/focus.d.ts.map +1 -0
- package/dist/0-face/focus.js +196 -0
- package/dist/0-face/grid.d.ts +11 -1
- package/dist/0-face/grid.d.ts.map +1 -1
- package/dist/0-face/grid.js +90 -4
- package/dist/0-face/i18n.d.ts.map +1 -1
- package/dist/0-face/i18n.js +38 -16
- package/dist/0-face/layout-inspector.d.ts +5 -1
- package/dist/0-face/layout-inspector.d.ts.map +1 -1
- package/dist/0-face/layout-inspector.js +130 -104
- package/dist/0-face/preference-options.d.ts +4 -0
- package/dist/0-face/preference-options.d.ts.map +1 -1
- package/dist/0-face/scaling.d.ts +8 -1
- package/dist/0-face/scaling.d.ts.map +1 -1
- package/dist/0-face/scaling.js +19 -2
- package/dist/0-face/shape.d.ts +35 -0
- package/dist/0-face/shape.d.ts.map +1 -0
- package/dist/0-face/shape.js +23 -0
- package/dist/0-face/text-contrast.d.ts +22 -0
- package/dist/0-face/text-contrast.d.ts.map +1 -0
- package/dist/0-face/text-contrast.js +178 -0
- package/dist/0-face/theme-bootstrap.js +56 -0
- package/dist/0-face/toast-queue.d.ts +4 -0
- package/dist/0-face/toast-queue.d.ts.map +1 -1
- package/dist/0-face/toast-queue.js +4 -1
- package/dist/0-face/translations/da.json +10 -1
- package/dist/0-face/translations/de.json +10 -1
- package/dist/0-face/translations/en.json +10 -1
- package/dist/0-face/translations/es.json +10 -1
- package/dist/0-face/translations/fi.json +10 -1
- package/dist/0-face/translations/fr.json +10 -1
- package/dist/0-face/translations/is.json +10 -1
- package/dist/0-face/translations/it.json +10 -1
- package/dist/0-face/translations/ja.json +10 -1
- package/dist/0-face/translations/ko.json +10 -1
- package/dist/0-face/translations/nb.json +10 -1
- package/dist/0-face/translations/pt-BR.json +10 -1
- package/dist/0-face/translations/pt.json +10 -1
- package/dist/0-face/translations/sv.json +10 -1
- package/dist/0-face/translations/zh.json +10 -1
- package/dist/0-face/word-wrap.d.ts +6 -0
- package/dist/0-face/word-wrap.d.ts.map +1 -0
- package/dist/0-face/word-wrap.js +119 -0
- package/dist/1-root/foundation.d.ts +12 -0
- package/dist/1-root/foundation.d.ts.map +1 -0
- package/dist/1-root/foundation.js +59 -0
- package/dist/2-core/button-split.d.ts +1 -0
- package/dist/2-core/button-split.d.ts.map +1 -1
- package/dist/2-core/button-split.js +9 -4
- package/dist/2-core/chart/grid-chart.d.ts +2 -0
- package/dist/2-core/chart/grid-chart.d.ts.map +1 -1
- package/dist/2-core/chart/grid-chart.js +2 -1
- package/dist/2-core/ds-activity.d.ts +25 -0
- package/dist/2-core/ds-activity.d.ts.map +1 -0
- package/dist/2-core/ds-activity.js +28 -0
- package/dist/2-core/ds-app-chrome.d.ts +2 -0
- package/dist/2-core/ds-app-chrome.d.ts.map +1 -0
- package/dist/2-core/ds-app-chrome.js +1 -0
- package/dist/2-core/ds-avatar.d.ts +12 -0
- package/dist/2-core/ds-avatar.d.ts.map +1 -1
- package/dist/2-core/ds-avatar.js +86 -7
- package/dist/2-core/ds-badge.d.ts +7 -1
- package/dist/2-core/ds-badge.d.ts.map +1 -1
- package/dist/2-core/ds-badge.js +8 -1
- package/dist/2-core/ds-button.d.ts +12 -0
- package/dist/2-core/ds-button.d.ts.map +1 -1
- package/dist/2-core/ds-button.js +4 -0
- package/dist/2-core/ds-chart.d.ts +28 -3
- package/dist/2-core/ds-chart.d.ts.map +1 -1
- package/dist/2-core/ds-chart.js +110 -130
- package/dist/2-core/ds-cycle.d.ts +2 -2
- package/dist/2-core/ds-cycle.d.ts.map +1 -1
- package/dist/2-core/ds-cycle.js +36 -171
- package/dist/2-core/ds-device-bezel.d.ts +2 -0
- package/dist/2-core/ds-device-bezel.d.ts.map +1 -0
- package/dist/2-core/ds-device-bezel.js +1 -0
- package/dist/2-core/ds-empty.d.ts +2 -2
- package/dist/2-core/ds-empty.d.ts.map +1 -1
- package/dist/2-core/ds-empty.js +6 -4
- package/dist/2-core/ds-input.d.ts +7 -0
- package/dist/2-core/ds-input.d.ts.map +1 -1
- package/dist/2-core/ds-input.js +23 -3
- package/dist/2-core/ds-message.d.ts +11 -0
- package/dist/2-core/ds-message.d.ts.map +1 -1
- package/dist/2-core/ds-message.js +18 -0
- package/dist/2-core/ds-number.d.ts +86 -0
- package/dist/2-core/ds-number.d.ts.map +1 -0
- package/dist/2-core/ds-number.js +326 -0
- package/dist/2-core/ds-progress.d.ts +3 -0
- package/dist/2-core/ds-progress.d.ts.map +1 -1
- package/dist/2-core/ds-progress.js +3 -0
- package/dist/2-core/ds-radio.d.ts +3 -0
- package/dist/2-core/ds-radio.d.ts.map +1 -1
- package/dist/2-core/ds-radio.js +10 -1
- package/dist/2-core/ds-stat.d.ts +3 -0
- package/dist/2-core/ds-stat.d.ts.map +1 -1
- package/dist/2-core/ds-stat.js +3 -0
- package/dist/2-core/ds-switch.d.ts +14 -1
- package/dist/2-core/ds-switch.d.ts.map +1 -1
- package/dist/2-core/ds-switch.js +3 -1
- package/dist/2-core/ds-tag.d.ts +8 -1
- package/dist/2-core/ds-tag.d.ts.map +1 -1
- package/dist/2-core/ds-tag.js +12 -2
- package/dist/2-core/ds-text.d.ts +7 -0
- package/dist/2-core/ds-text.d.ts.map +1 -1
- package/dist/2-core/ds-text.js +7 -0
- package/dist/2-core/ds-token.d.ts +3 -0
- package/dist/2-core/ds-token.d.ts.map +1 -1
- package/dist/2-core/ds-token.js +3 -0
- package/dist/2-core/ds-tooltip.d.ts.map +1 -1
- package/dist/2-core/ds-tooltip.js +23 -2
- package/dist/2-core/ds-window.d.ts +2 -0
- package/dist/2-core/ds-window.d.ts.map +1 -0
- package/dist/2-core/ds-window.js +1 -0
- package/dist/2-core/generated/ds-icon-map.d.ts +27 -6
- package/dist/2-core/generated/ds-icon-map.d.ts.map +1 -1
- package/dist/2-core/generated/ds-icon-map.js +47 -5
- package/dist/2-core/generated/icons-extra.d.ts.map +1 -1
- package/dist/2-core/generated/icons-extra.js +24 -3
- package/dist/2-core/generated/icons-immediate.d.ts +1 -1
- package/dist/2-core/generated/icons-immediate.d.ts.map +1 -1
- package/dist/2-core/generated/icons-immediate.js +3 -3
- package/dist/2-core/number-expression.d.ts +12 -0
- package/dist/2-core/number-expression.d.ts.map +1 -0
- package/dist/2-core/number-expression.js +82 -0
- package/dist/3-unit/calendar-base.d.ts +5 -0
- package/dist/3-unit/calendar-base.d.ts.map +1 -1
- package/dist/3-unit/calendar-base.js +3 -2
- package/dist/3-unit/context-trigger.d.ts.map +1 -1
- package/dist/3-unit/context-trigger.js +32 -2
- package/dist/3-unit/ds-calendar.d.ts +197 -4
- package/dist/3-unit/ds-calendar.d.ts.map +1 -1
- package/dist/3-unit/ds-calendar.js +687 -45
- package/dist/3-unit/ds-carousel.d.ts +3 -0
- package/dist/3-unit/ds-carousel.d.ts.map +1 -1
- package/dist/3-unit/ds-carousel.js +13 -1
- package/dist/3-unit/ds-context.d.ts +18 -1
- package/dist/3-unit/ds-context.d.ts.map +1 -1
- package/dist/3-unit/ds-context.js +37 -1
- package/dist/3-unit/ds-form.d.ts +9 -0
- package/dist/3-unit/ds-form.d.ts.map +1 -1
- package/dist/3-unit/ds-form.js +52 -11
- package/dist/3-unit/ds-list.d.ts +20 -1
- package/dist/3-unit/ds-list.d.ts.map +1 -1
- package/dist/3-unit/ds-list.js +31 -3
- package/dist/3-unit/ds-matrix.d.ts +3 -0
- package/dist/3-unit/ds-matrix.d.ts.map +1 -1
- package/dist/3-unit/ds-matrix.js +3 -0
- package/dist/3-unit/ds-menu.d.ts.map +1 -1
- package/dist/3-unit/ds-menu.js +17 -1
- package/dist/3-unit/ds-row.d.ts +13 -0
- package/dist/3-unit/ds-row.d.ts.map +1 -1
- package/dist/3-unit/ds-row.js +15 -2
- package/dist/3-unit/ds-select.js +1 -1
- package/dist/3-unit/ds-sidebar.d.ts +17 -0
- package/dist/3-unit/ds-sidebar.d.ts.map +1 -1
- package/dist/3-unit/ds-sidebar.js +14 -3
- package/dist/3-unit/ds-table-of-contents.d.ts +68 -0
- package/dist/3-unit/ds-table-of-contents.d.ts.map +1 -0
- package/dist/3-unit/ds-table-of-contents.js +190 -0
- package/dist/3-unit/ds-table.d.ts.map +1 -1
- package/dist/3-unit/ds-table.js +2 -1
- package/dist/3-unit/ds-tabs.d.ts +32 -1
- package/dist/3-unit/ds-tabs.d.ts.map +1 -1
- package/dist/3-unit/ds-tabs.js +39 -1
- package/dist/4-page/ds-container.d.ts.map +1 -1
- package/dist/4-page/ds-container.js +2 -1
- package/dist/4-page/ds-document.d.ts +3 -0
- package/dist/4-page/ds-document.d.ts.map +1 -1
- package/dist/4-page/ds-document.js +3 -0
- package/dist/4-page/ds-footer.d.ts +47 -7
- package/dist/4-page/ds-footer.d.ts.map +1 -1
- package/dist/4-page/ds-footer.js +58 -14
- package/dist/4-page/ds-header.d.ts +6 -0
- package/dist/4-page/ds-header.d.ts.map +1 -1
- package/dist/4-page/ds-header.js +4 -1
- package/dist/4-page/ds-overlay.d.ts +2 -2
- package/dist/4-page/ds-overlay.d.ts.map +1 -1
- package/dist/4-page/ds-overlay.js +8 -3
- package/dist/4-page/ds-page.d.ts +12 -0
- package/dist/4-page/ds-page.d.ts.map +1 -1
- package/dist/4-page/ds-page.js +19 -1
- package/dist/4-page/email.d.ts +2 -0
- package/dist/4-page/email.d.ts.map +1 -1
- package/dist/4-page/email.js +5 -4
- package/dist/5-visual-kit/app-chrome.d.ts +98 -0
- package/dist/5-visual-kit/app-chrome.d.ts.map +1 -0
- package/dist/5-visual-kit/app-chrome.js +119 -0
- package/dist/5-visual-kit/bezels.d.ts +30 -0
- package/dist/5-visual-kit/bezels.d.ts.map +1 -0
- package/dist/5-visual-kit/bezels.js +388 -0
- package/dist/5-visual-kit/browser-icons.d.ts +5 -0
- package/dist/5-visual-kit/browser-icons.d.ts.map +1 -0
- package/dist/5-visual-kit/browser-icons.js +51 -0
- package/dist/5-visual-kit/browser-styles.d.ts +3 -0
- package/dist/5-visual-kit/browser-styles.d.ts.map +1 -0
- package/dist/5-visual-kit/browser-styles.js +52 -0
- package/dist/5-visual-kit/device-bezel.d.ts +84 -0
- package/dist/5-visual-kit/device-bezel.d.ts.map +1 -0
- package/dist/5-visual-kit/device-bezel.js +56 -0
- package/dist/5-visual-kit/instagram-frame.d.ts +8 -0
- package/dist/5-visual-kit/instagram-frame.d.ts.map +1 -0
- package/dist/5-visual-kit/instagram-frame.js +13 -0
- package/dist/5-visual-kit/instagram.d.ts +18 -0
- package/dist/5-visual-kit/instagram.d.ts.map +1 -0
- package/dist/5-visual-kit/instagram.js +39 -0
- package/dist/5-visual-kit/mobile-chrome.d.ts +4 -0
- package/dist/5-visual-kit/mobile-chrome.d.ts.map +1 -0
- package/dist/5-visual-kit/mobile-chrome.js +24 -0
- package/dist/5-visual-kit/native-icon-paths.d.ts +146 -0
- package/dist/5-visual-kit/native-icon-paths.d.ts.map +1 -0
- package/dist/5-visual-kit/native-icon-paths.js +145 -0
- package/dist/5-visual-kit/window.d.ts +51 -0
- package/dist/5-visual-kit/window.d.ts.map +1 -0
- package/dist/5-visual-kit/window.js +20 -0
- package/dist/browser-icons-BFbS1tIx.js +56 -0
- package/dist/browser-icons-BFbS1tIx.js.map +1 -0
- package/dist/browser-icons-CT8qU77Z.js +48 -0
- package/dist/browser-icons-CT8qU77Z.js.map +1 -0
- package/dist/components.d.ts +1 -0
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +1 -0
- package/dist/design-system-1.bundle.js +5874 -2097
- package/dist/design-system-1.bundle.js.map +1 -1
- package/dist/design-system-1.bundle.min.js +7332 -4682
- package/dist/design-system-1.bundle.min.js.map +1 -1
- package/dist/design-system-1.css +1 -1
- package/dist/feedback.js +197 -167
- package/dist/feedback.js.map +1 -1
- package/dist/{icons-extra-CRxxWFjX.js → icons-extra-BMPvmQPI.js} +25 -4
- package/dist/icons-extra-BMPvmQPI.js.map +1 -0
- package/dist/{icons-extra-H5pqCM_R.js → icons-extra-BfYOw-cR.js} +83 -5
- package/dist/icons-extra-BfYOw-cR.js.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/instagram-CKofs55A.js +50 -0
- package/dist/instagram-CKofs55A.js.map +1 -0
- package/dist/instagram-CcYf5oiM.js +48 -0
- package/dist/instagram-CcYf5oiM.js.map +1 -0
- package/dist/lit-Ce_uWYM4.js +612 -0
- package/dist/lit-Ce_uWYM4.js.map +1 -0
- package/dist/lit-DGUVm1Ce.js +557 -0
- package/dist/lit-DGUVm1Ce.js.map +1 -0
- package/dist/native-icon-paths-CB9evXBM.js +93 -0
- package/dist/native-icon-paths-CB9evXBM.js.map +1 -0
- package/dist/native-icon-paths-zay-3g_n.js +150 -0
- package/dist/native-icon-paths-zay-3g_n.js.map +1 -0
- package/dist/react/avatar.d.ts +1 -1
- package/dist/react/choice.d.ts +4 -0
- package/dist/react/choice.d.ts.map +1 -1
- package/dist/react/choice.js +2 -2
- package/dist/react/context.d.ts +19 -4
- package/dist/react/context.d.ts.map +1 -1
- package/dist/react/context.js +4 -4
- package/dist/react/empty.d.ts +2 -2
- package/dist/react/empty.d.ts.map +1 -1
- package/dist/react/empty.js +1 -1
- package/dist/react/footer.d.ts +5 -5
- package/dist/react/footer.d.ts.map +1 -1
- package/dist/react/footer.js +2 -2
- package/dist/react/header.d.ts +2 -2
- package/dist/react/header.d.ts.map +1 -1
- package/dist/react/message.d.ts +4 -0
- package/dist/react/message.d.ts.map +1 -1
- package/dist/react/message.js +2 -2
- package/dist/react/number.d.ts +53 -0
- package/dist/react/number.d.ts.map +1 -0
- package/dist/react/number.js +25 -0
- package/dist/react/page.d.ts +1 -1
- package/dist/react/sidebar.d.ts +4 -0
- package/dist/react/sidebar.d.ts.map +1 -1
- package/dist/react/sidebar.js +2 -2
- package/dist/react/table-of-contents.d.ts +19 -0
- package/dist/react/table-of-contents.d.ts.map +1 -0
- package/dist/react/table-of-contents.js +28 -0
- package/dist/{shared-words-CdMDVtXx.js → shared-words-C5cjxMjZ.js} +151 -16
- package/dist/shared-words-C5cjxMjZ.js.map +1 -0
- package/dist/{shared-words-BtRee8xR.js → shared-words-Cdm7xd-_.js} +163 -28
- package/dist/shared-words-Cdm7xd-_.js.map +1 -0
- package/package.json +25 -12
- package/DS1/3-unit/ds-calendar-large.ts +0 -353
- package/DS1/3-unit/styles/ds-calendar-large.css +0 -178
- package/dist/3-unit/ds-calendar-large.d.ts +0 -142
- package/dist/3-unit/ds-calendar-large.d.ts.map +0 -1
- package/dist/3-unit/ds-calendar-large.js +0 -308
- package/dist/icons-extra-CRxxWFjX.js.map +0 -1
- package/dist/icons-extra-H5pqCM_R.js.map +0 -1
- package/dist/shared-words-BtRee8xR.js.map +0 -1
- package/dist/shared-words-CdMDVtXx.js.map +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Finding } from './constraints';
|
|
2
|
+
|
|
3
|
+
export function labelledButtons(root: ParentNode): HTMLElement[] {
|
|
4
|
+
const result = [...root.querySelectorAll<HTMLElement>('ds-button:not([icon]):not([split]),button:not(ds-button button),a[role="button"]')];
|
|
5
|
+
return result.filter(button => button.getBoundingClientRect().width && (button.textContent?.trim() || button.getAttribute('text')));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Inspect actual labels, including a component's shadow face and slotted words. */
|
|
9
|
+
export function inspectButtonLabels(root: ParentNode): Finding[] {
|
|
10
|
+
const findings: Finding[] = [];
|
|
11
|
+
for (const button of labelledButtons(root)) {
|
|
12
|
+
const face = button.shadowRoot?.querySelector<HTMLElement>('[part="control"]') ?? button.querySelector<HTMLElement>(':scope > button,:scope > a') ?? button;
|
|
13
|
+
const rect = face.getBoundingClientRect();
|
|
14
|
+
const nodes = [button, face, ...button.querySelectorAll<HTMLElement>('*'), ...face.querySelectorAll<HTMLElement>('*')];
|
|
15
|
+
let faded = false, clipped = false;
|
|
16
|
+
for (const node of new Set(nodes)) {
|
|
17
|
+
const style = (node.ownerDocument.defaultView ?? window).getComputedStyle(node);
|
|
18
|
+
if (node.hasAttribute('data-cut') || (style.maskImage && style.maskImage !== 'none') || (/text/.test(style.backgroundClip) && /gradient/.test(style.backgroundImage))) faded = true;
|
|
19
|
+
for (const child of node.childNodes) {
|
|
20
|
+
if (child.nodeType !== Node.TEXT_NODE || !child.textContent?.trim()) continue;
|
|
21
|
+
const range = node.ownerDocument.createRange(); range.selectNodeContents(child);
|
|
22
|
+
for (const text of range.getClientRects()) if (text.width && (text.left < rect.left - 1 || text.right > rect.right + 1)) clipped = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (faded || clipped) findings.push({ element: button, message: faded ? 'Button text must not fade or use a gradient mask.' : 'Give the button enough grid-aligned width to show its complete label.' });
|
|
26
|
+
}
|
|
27
|
+
return findings;
|
|
28
|
+
}
|
package/DS1/0-face/calendar.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Days as the calendars count them: a day is written `YYYY-MM-DD` and read on
|
|
3
3
|
// its own date in every zone, a month is the whole weeks that hold it, and the
|
|
4
4
|
// week starts where the language starts it. Shared by ds-calendar (its
|
|
5
|
-
// picker too)
|
|
5
|
+
// picker too); no Lit, so a page can use it alone.
|
|
6
6
|
|
|
7
7
|
import { currentLanguage } from "./i18n";
|
|
8
8
|
import { dateFormatter, localeTag } from "./format";
|
|
@@ -144,9 +144,11 @@ export const monthTitle = (day: Day, width: "long" | "short" = "long", language?
|
|
|
144
144
|
export const monthName = (day: Day, width: "long" | "short" = "long", language?: string) =>
|
|
145
145
|
dateFormatter({ month: width, timeZone: "UTC", language }).format(noon(day));
|
|
146
146
|
|
|
147
|
-
/** The date's number in the language's digits: "18". */
|
|
148
|
-
export const dateNumber = (day: Day, language?: string) =>
|
|
149
|
-
dateFormatter({ day: "numeric", timeZone: "UTC", language }).
|
|
147
|
+
/** The date's number alone, in the language's digits: "18", never Danish's "18." or Japanese's "18日". */
|
|
148
|
+
export const dateNumber = (day: Day, language?: string) => {
|
|
149
|
+
const parts = dateFormatter({ day: "numeric", timeZone: "UTC", language }).formatToParts(noon(day));
|
|
150
|
+
return parts.find(part => part.type === "day")?.value ?? parts.map(part => part.value).join("");
|
|
151
|
+
};
|
|
150
152
|
|
|
151
153
|
/** The whole day, for a day's accessible name: "Sunday, 18 October 2026". */
|
|
152
154
|
export const dayLabel = (day: Day, language?: string) =>
|
package/DS1/0-face/carousel.ts
CHANGED
|
@@ -192,6 +192,73 @@ export function nearestSlide(track: HTMLElement, slides: readonly HTMLElement[],
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* A strip under the pointer. A finger, a pen or a trackpad scrolls the track
|
|
197
|
+
* natively; a mouse drags it the same way (snapping held off while it drags),
|
|
198
|
+
* and on letting go `settle` puts it on a slide. A press that ends a drag or a
|
|
199
|
+
* scroll, by any pointer, never presses what it started on, so a person can
|
|
200
|
+
* swipe across cards that open something without choosing one. Returns the
|
|
201
|
+
* function that stops it.
|
|
202
|
+
*/
|
|
203
|
+
export function dragTrack(track: HTMLElement, settle: () => void): () => void {
|
|
204
|
+
let held: { id: number; x: number; left: number; mouse: boolean } | null = null;
|
|
205
|
+
let moved = false;
|
|
206
|
+
let quietUntil = 0;
|
|
207
|
+
const down = (event: PointerEvent) => {
|
|
208
|
+
if (!event.isPrimary || (event.pointerType === "mouse" && event.button !== 0)) return;
|
|
209
|
+
held = { id: event.pointerId, x: event.clientX, left: track.scrollLeft, mouse: event.pointerType === "mouse" };
|
|
210
|
+
moved = false;
|
|
211
|
+
};
|
|
212
|
+
const move = (event: PointerEvent) => {
|
|
213
|
+
if (!held || event.pointerId !== held.id) return;
|
|
214
|
+
const dx = event.clientX - held.x;
|
|
215
|
+
if (!moved && Math.abs(dx) < 6) return;
|
|
216
|
+
if (!moved && held.mouse) {
|
|
217
|
+
try { track.setPointerCapture(event.pointerId); } catch { /* a pointer already gone */ }
|
|
218
|
+
track.setAttribute("data-dragging", "");
|
|
219
|
+
}
|
|
220
|
+
moved = true;
|
|
221
|
+
if (held.mouse) track.scrollLeft = held.left - dx;
|
|
222
|
+
};
|
|
223
|
+
const up = (event: PointerEvent) => {
|
|
224
|
+
if (!held || event.pointerId !== held.id) return;
|
|
225
|
+
const mouse = held.mouse;
|
|
226
|
+
held = null;
|
|
227
|
+
if (!moved) return;
|
|
228
|
+
quietUntil = performance.now() + 400;
|
|
229
|
+
if (mouse) {
|
|
230
|
+
track.removeAttribute("data-dragging");
|
|
231
|
+
settle();
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
// A native scroll while a finger is down is a swipe: the press it ends is not a choice.
|
|
235
|
+
const scrolled = () => { if (held) moved = true; };
|
|
236
|
+
const click = (event: MouseEvent) => {
|
|
237
|
+
if (performance.now() > quietUntil) return;
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
event.stopPropagation();
|
|
240
|
+
};
|
|
241
|
+
// A picture in a slide would be dragged out of the page instead of the strip.
|
|
242
|
+
const dragstart = (event: DragEvent) => event.preventDefault();
|
|
243
|
+
track.addEventListener("pointerdown", down);
|
|
244
|
+
track.addEventListener("pointermove", move);
|
|
245
|
+
track.addEventListener("pointerup", up);
|
|
246
|
+
track.addEventListener("pointercancel", up);
|
|
247
|
+
track.addEventListener("scroll", scrolled, { passive: true });
|
|
248
|
+
track.addEventListener("click", click, true);
|
|
249
|
+
track.addEventListener("dragstart", dragstart);
|
|
250
|
+
return () => {
|
|
251
|
+
track.removeEventListener("pointerdown", down);
|
|
252
|
+
track.removeEventListener("pointermove", move);
|
|
253
|
+
track.removeEventListener("pointerup", up);
|
|
254
|
+
track.removeEventListener("pointercancel", up);
|
|
255
|
+
track.removeEventListener("scroll", scrolled);
|
|
256
|
+
track.removeEventListener("click", click, true);
|
|
257
|
+
track.removeEventListener("dragstart", dragstart);
|
|
258
|
+
track.removeAttribute("data-dragging");
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
195
262
|
/** Where a slide starts along the track, from the track's own start, in its scroll's terms. */
|
|
196
263
|
function startOf(track: HTMLElement, slide: HTMLElement): number {
|
|
197
264
|
const box = track.getBoundingClientRect();
|
|
@@ -588,6 +655,8 @@ export function startCarousel(element: HTMLElement, options: StartCarouselOption
|
|
|
588
655
|
|
|
589
656
|
track.addEventListener("scroll", scrolled, { passive: true });
|
|
590
657
|
track.addEventListener("scrollend", ended);
|
|
658
|
+
// A loop's drive settles the strip itself; every other strip settles on the nearest slide.
|
|
659
|
+
const undrag = dragTrack(track, () => (loop ? undefined : go(nearestSlide(track, slides(), current), true)));
|
|
591
660
|
previousButton?.addEventListener("click", previous);
|
|
592
661
|
nextButton?.addEventListener("click", next);
|
|
593
662
|
observer?.observe(track, { childList: true });
|
|
@@ -601,6 +670,7 @@ export function startCarousel(element: HTMLElement, options: StartCarouselOption
|
|
|
601
670
|
stop() {
|
|
602
671
|
track.removeEventListener("scroll", scrolled);
|
|
603
672
|
track.removeEventListener("scrollend", ended);
|
|
673
|
+
undrag();
|
|
604
674
|
previousButton?.removeEventListener("click", previous);
|
|
605
675
|
nextButton?.removeEventListener("click", next);
|
|
606
676
|
observer?.disconnect();
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { paintFaultLines } from './fault-lines';
|
|
2
|
+
import { measureConstraints, type Constraint, type Finding } from './constraints';
|
|
3
|
+
import { VIEWPORT_WIDTHS, checkSite, findSitePages, inspectInFrame, ruleLine, summarizePages, summarizeRules, type PageResult } from './constraint-site';
|
|
4
|
+
|
|
5
|
+
// appendChild, not append: a Worker project's types redefine append for its HTML rewriter.
|
|
6
|
+
|
|
7
|
+
/** The presses of C, each within 800ms of the last, that toggle the panel. */
|
|
8
|
+
export const CONSTRAINT_PRESSES = 5;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A panel at the page's end edge listing every small rule the page breaks
|
|
12
|
+
* (constraints.ts), each with its code, what is wrong and the element ringed
|
|
13
|
+
* on the page; pressing one scrolls to it. It measures the page as drawn when
|
|
14
|
+
* it opens and again with Page. Site measures every page of the site at every
|
|
15
|
+
* phone width (constraint-site.ts) and lists what each breaks, with a link to
|
|
16
|
+
* the page. Under what is broken it says what each rule measured and kept,
|
|
17
|
+
* and after a Site check every page it checked. It draws over the page and
|
|
18
|
+
* changes nothing in it.
|
|
19
|
+
*/
|
|
20
|
+
export function createConstraintPanel() {
|
|
21
|
+
const panel = document.createElement('div');
|
|
22
|
+
panel.setAttribute('data-ds-constraint-panel', '');
|
|
23
|
+
panel.hidden = true;
|
|
24
|
+
const shadow = panel.attachShadow({ mode: 'open' });
|
|
25
|
+
shadow.innerHTML = `<style>
|
|
26
|
+
:host {
|
|
27
|
+
all: initial !important;
|
|
28
|
+
display: block !important;
|
|
29
|
+
position: fixed !important;
|
|
30
|
+
inset: 0 !important;
|
|
31
|
+
z-index: 2147483645 !important;
|
|
32
|
+
pointer-events: none !important;
|
|
33
|
+
color-scheme: inherit !important;
|
|
34
|
+
--u: calc(20px * var(--sf, 1));
|
|
35
|
+
--paper: var(--ds-background-color, light-dark(#f9f6ef, #1e1e1e));
|
|
36
|
+
--ink: var(--ds-text-color, light-dark(#2a2a2a, #e8e8e8));
|
|
37
|
+
--muted: var(--ds-text-color-muted, light-dark(#797979, #a0a0a0));
|
|
38
|
+
--line: var(--ds-border-color, light-dark(#e8e8e8, #3c3c3c));
|
|
39
|
+
--danger: var(--ds-danger-color, light-dark(#de0331, #ff5f5f));
|
|
40
|
+
}
|
|
41
|
+
:host([hidden]) { display: none !important; }
|
|
42
|
+
.fault-lines { z-index: 0 !important; }
|
|
43
|
+
.rings { z-index: 1; position: absolute; inset: 0; overflow: hidden; }
|
|
44
|
+
.frames { position: absolute; width: 0; height: 0; overflow: hidden; }
|
|
45
|
+
.ring {
|
|
46
|
+
position: absolute;
|
|
47
|
+
box-sizing: border-box;
|
|
48
|
+
border: 2px solid var(--danger);
|
|
49
|
+
}
|
|
50
|
+
.ring[data-current] { background: color-mix(in srgb, var(--danger) 12%, transparent); }
|
|
51
|
+
.ring span {
|
|
52
|
+
position: absolute;
|
|
53
|
+
top: -2px;
|
|
54
|
+
left: -2px;
|
|
55
|
+
min-width: var(--u);
|
|
56
|
+
padding: 0 4px;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
background: var(--danger);
|
|
59
|
+
color: #fff;
|
|
60
|
+
font: 400 12px/16px var(--ds-typeface-regular, sans-serif);
|
|
61
|
+
font-variant-numeric: tabular-nums;
|
|
62
|
+
text-align: center;
|
|
63
|
+
}
|
|
64
|
+
aside {
|
|
65
|
+
z-index: 2;
|
|
66
|
+
position: absolute;
|
|
67
|
+
inset-block: 0;
|
|
68
|
+
inset-inline-end: 0;
|
|
69
|
+
box-sizing: border-box;
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
width: min(calc(16 * var(--u)), 100vw);
|
|
73
|
+
padding: var(--u);
|
|
74
|
+
overflow: auto;
|
|
75
|
+
background: var(--paper);
|
|
76
|
+
box-shadow: -1px 0 0 var(--line);
|
|
77
|
+
color: var(--ink);
|
|
78
|
+
font: 400 14px/var(--u) var(--ds-typeface-regular, sans-serif);
|
|
79
|
+
pointer-events: auto;
|
|
80
|
+
}
|
|
81
|
+
header { display: flex; align-items: flex-end; gap: var(--u); height: var(--u); margin-bottom: var(--u); }
|
|
82
|
+
header strong { flex: 1; font-weight: 400; font-family: var(--ds-typeface-medium, inherit); }
|
|
83
|
+
button {
|
|
84
|
+
all: unset;
|
|
85
|
+
height: var(--u);
|
|
86
|
+
color: var(--muted);
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
}
|
|
89
|
+
button:hover { color: var(--ink); }
|
|
90
|
+
button:focus-visible { outline: 2px solid var(--ds-focus-ring, var(--ink)); outline-offset: -2px; }
|
|
91
|
+
ol { margin: 0; padding: 0; list-style: none; }
|
|
92
|
+
li + li { border-top: 1px solid var(--line); }
|
|
93
|
+
li > :is(button, a, div) { display: block; width: 100%; height: auto; padding-block: calc(var(--u) / 2); color: var(--ink); text-decoration: none; }
|
|
94
|
+
li > a:hover .page { color: var(--ink); }
|
|
95
|
+
li > a:focus-visible { outline: 2px solid var(--ds-focus-ring, var(--ink)); outline-offset: -2px; }
|
|
96
|
+
.page { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
|
|
97
|
+
.element { color: var(--muted); overflow-wrap: anywhere; }
|
|
98
|
+
[data-status] { color: var(--muted); margin-bottom: calc(var(--u) / 2); }
|
|
99
|
+
section { margin-top: var(--u); }
|
|
100
|
+
section[hidden] { display: none; }
|
|
101
|
+
h3 { margin: 0; height: var(--u); font: inherit; font-family: var(--ds-typeface-medium, inherit); border-bottom: 1px solid var(--line); }
|
|
102
|
+
li.rule-row > div { padding-block: calc(var(--u) / 2); }
|
|
103
|
+
li.page-row > a { display: flex; justify-content: space-between; align-items: flex-end; gap: calc(var(--u) / 2); padding-block: 0; min-height: var(--u); }
|
|
104
|
+
li.page-row .page { text-decoration: none; }
|
|
105
|
+
li.page-row > a:hover .page { text-decoration: underline; }
|
|
106
|
+
.kept { color: var(--muted); white-space: nowrap; }
|
|
107
|
+
.broke { color: var(--danger); white-space: nowrap; }
|
|
108
|
+
.code { display: flex; gap: calc(var(--u) / 2); color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
109
|
+
.code b { color: var(--danger); font-weight: 400; }
|
|
110
|
+
.rule { color: var(--muted); }
|
|
111
|
+
p { margin: 0; }
|
|
112
|
+
:host([data-lines-only]) aside { inset-block: 0 auto; width: auto; padding: calc(var(--u) / 2); }
|
|
113
|
+
:host([data-lines-only]) aside > :not(header), :host([data-lines-only]) header > :not([data-lines], [data-close]) { display: none; }
|
|
114
|
+
:host([data-lines-only]) header { margin: 0; }
|
|
115
|
+
@media print { :host { display: none !important; } }
|
|
116
|
+
</style><svg class="fault-lines" aria-hidden="true"></svg><div class="rings"></div><div class="frames"></div><aside aria-label="Constraints">
|
|
117
|
+
<header><strong>Constraints</strong><button type="button" data-run>Page</button><button type="button" data-site>Site</button><button type="button" data-lines>Lines</button><button type="button" data-close aria-label="Close">Close</button></header>
|
|
118
|
+
<p data-status aria-live="polite"></p><p class="rule">Fault lines: dashed reference · red drift</p>
|
|
119
|
+
<ol data-findings></ol>
|
|
120
|
+
<section data-rules hidden><h3>Rules</h3><ol></ol></section>
|
|
121
|
+
<section data-pages hidden><h3>Pages</h3><ol></ol></section>
|
|
122
|
+
</aside>`;
|
|
123
|
+
const faultLines = shadow.querySelector<SVGSVGElement>('.fault-lines')!;
|
|
124
|
+
const rings = shadow.querySelector<HTMLDivElement>('.rings')!;
|
|
125
|
+
const list = shadow.querySelector<HTMLOListElement>('[data-findings]')!;
|
|
126
|
+
const rulesSection = shadow.querySelector<HTMLElement>('[data-rules]')!;
|
|
127
|
+
const rulesList = rulesSection.querySelector('ol')!;
|
|
128
|
+
const pagesSection = shadow.querySelector<HTMLElement>('[data-pages]')!;
|
|
129
|
+
const pagesList = pagesSection.querySelector('ol')!;
|
|
130
|
+
const status = shadow.querySelector<HTMLElement>('[data-status]')!;
|
|
131
|
+
const title = shadow.querySelector('strong')!;
|
|
132
|
+
const frames = shadow.querySelector<HTMLDivElement>('.frames')!;
|
|
133
|
+
const linesButton = shadow.querySelector<HTMLButtonElement>('[data-lines]')!;
|
|
134
|
+
const setLinesOnly = (enabled: boolean) => { panel.toggleAttribute('data-lines-only', enabled); linesButton.textContent = enabled ? 'Results' : 'Lines'; };
|
|
135
|
+
linesButton.addEventListener('click', () => setLinesOnly(!panel.hasAttribute('data-lines-only')));
|
|
136
|
+
const siteButton = shadow.querySelector<HTMLButtonElement>('[data-site]')!;
|
|
137
|
+
let site: AbortController | null = null;
|
|
138
|
+
let findings: (Finding & { constraint: Constraint })[] = [];
|
|
139
|
+
let current = -1;
|
|
140
|
+
let frame = 0;
|
|
141
|
+
|
|
142
|
+
const place = () => {
|
|
143
|
+
frame = 0;
|
|
144
|
+
paintFaultLines(document, faultLines);
|
|
145
|
+
rings.replaceChildren(...findings.map(({ element }, index) => {
|
|
146
|
+
const rect = element.getBoundingClientRect();
|
|
147
|
+
const ring = document.createElement('div');
|
|
148
|
+
ring.className = 'ring';
|
|
149
|
+
ring.toggleAttribute('data-current', index === current);
|
|
150
|
+
ring.style.cssText = `left:${rect.left}px;top:${rect.top}px;width:${rect.width}px;height:${rect.height}px`;
|
|
151
|
+
const number = document.createElement('span');
|
|
152
|
+
number.textContent = String(index + 1);
|
|
153
|
+
ring.appendChild(number);
|
|
154
|
+
return ring;
|
|
155
|
+
}));
|
|
156
|
+
};
|
|
157
|
+
const schedule = () => { if (!frame) frame = requestAnimationFrame(place); };
|
|
158
|
+
const layoutChanges = new MutationObserver(schedule);
|
|
159
|
+
const sizeChanges = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(schedule);
|
|
160
|
+
|
|
161
|
+
const stopSite = () => {
|
|
162
|
+
site?.abort();
|
|
163
|
+
site = null;
|
|
164
|
+
siteButton.textContent = 'Site';
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/** What each rule measured and kept, over `total` page views (one: this page). */
|
|
168
|
+
const showRules = (summaries: ReturnType<typeof summarizeRules>, total: number) => {
|
|
169
|
+
rulesSection.hidden = false;
|
|
170
|
+
rulesList.replaceChildren(...summaries.map(summary => {
|
|
171
|
+
const item = document.createElement('li');
|
|
172
|
+
item.className = 'rule-row';
|
|
173
|
+
const box = document.createElement('div');
|
|
174
|
+
const code = document.createElement('span');
|
|
175
|
+
code.className = 'code';
|
|
176
|
+
code.textContent = summary.constraint.code;
|
|
177
|
+
const line = document.createElement('p');
|
|
178
|
+
line.textContent = ruleLine(summary, total);
|
|
179
|
+
const rule = document.createElement('p');
|
|
180
|
+
rule.className = 'rule';
|
|
181
|
+
rule.textContent = summary.constraint.rule;
|
|
182
|
+
for (const part of [code, line, rule]) box.appendChild(part);
|
|
183
|
+
item.appendChild(box);
|
|
184
|
+
return item;
|
|
185
|
+
}));
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/** Every page the Site check opened, a row each: kept at every width, or how much it broke and where. */
|
|
189
|
+
const showPages = (results: PageResult[]) => {
|
|
190
|
+
const pages = summarizePages(results);
|
|
191
|
+
pagesSection.hidden = !pages.length;
|
|
192
|
+
pagesList.replaceChildren(...pages.map(({ url, widths }) => {
|
|
193
|
+
const item = document.createElement('li');
|
|
194
|
+
item.className = 'page-row';
|
|
195
|
+
const link = document.createElement('a');
|
|
196
|
+
const address = new URL(url);
|
|
197
|
+
address.searchParams.set('constraints', '1');
|
|
198
|
+
link.href = address.href;
|
|
199
|
+
const path = document.createElement('span');
|
|
200
|
+
path.className = 'page';
|
|
201
|
+
path.textContent = decodeURI(new URL(url).pathname);
|
|
202
|
+
const state = document.createElement('span');
|
|
203
|
+
const failed = widths.filter(width => width.broken || width.error);
|
|
204
|
+
state.className = failed.length ? 'broke' : 'kept';
|
|
205
|
+
state.textContent = failed.length
|
|
206
|
+
? failed.map(({ width, broken, error }) => (error ? `${width}px not checked` : `${broken} at ${width}px`)).join(', ')
|
|
207
|
+
: `kept at ${widths.length} widths`;
|
|
208
|
+
link.appendChild(path);
|
|
209
|
+
link.appendChild(state);
|
|
210
|
+
item.appendChild(link);
|
|
211
|
+
return item;
|
|
212
|
+
}));
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const run = () => {
|
|
216
|
+
stopSite();
|
|
217
|
+
const measured = measureConstraints(document);
|
|
218
|
+
findings = measured.flatMap(({ constraint, findings: found }) => found.map(finding => ({ ...finding, constraint })));
|
|
219
|
+
showRules(measured.map(({ constraint, measured: count, findings: found }) => ({ constraint, measured: count, views: count ? 1 : 0, broken: found.length })), 1);
|
|
220
|
+
pagesSection.hidden = true;
|
|
221
|
+
current = -1;
|
|
222
|
+
title.textContent = findings.length ? `Constraints · ${findings.length} broken` : 'Constraints';
|
|
223
|
+
status.textContent = findings.length ? `This page at ${Math.round(document.documentElement.clientWidth)}px.` : 'This page keeps every constraint.';
|
|
224
|
+
list.replaceChildren(...findings.map(({ constraint, message, element }, index) => {
|
|
225
|
+
const item = document.createElement('li');
|
|
226
|
+
const button = document.createElement('button');
|
|
227
|
+
button.type = 'button';
|
|
228
|
+
const code = document.createElement('span');
|
|
229
|
+
code.className = 'code';
|
|
230
|
+
const number = document.createElement('b');
|
|
231
|
+
number.textContent = String(index + 1);
|
|
232
|
+
code.appendChild(number);
|
|
233
|
+
code.appendChild(document.createTextNode(constraint.code));
|
|
234
|
+
const what = document.createElement('p');
|
|
235
|
+
what.textContent = message;
|
|
236
|
+
const rule = document.createElement('p');
|
|
237
|
+
rule.className = 'rule';
|
|
238
|
+
rule.textContent = constraint.rule;
|
|
239
|
+
for (const part of [code, what, rule]) button.appendChild(part);
|
|
240
|
+
button.addEventListener('click', () => {
|
|
241
|
+
current = index;
|
|
242
|
+
element.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
|
243
|
+
schedule();
|
|
244
|
+
});
|
|
245
|
+
item.appendChild(button);
|
|
246
|
+
return item;
|
|
247
|
+
}));
|
|
248
|
+
place();
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/** One broken rule on another page: its number, code and width, what is wrong, and a link to the page. */
|
|
252
|
+
const siteItem = (index: number, { url, width }: PageResult, code: string, message: string, detail: string) => {
|
|
253
|
+
const item = document.createElement('li');
|
|
254
|
+
const link = document.createElement('a');
|
|
255
|
+
const address = new URL(url);
|
|
256
|
+
address.searchParams.set('constraints', '1');
|
|
257
|
+
link.href = address.href;
|
|
258
|
+
const head = document.createElement('span');
|
|
259
|
+
head.className = 'code';
|
|
260
|
+
const number = document.createElement('b');
|
|
261
|
+
number.textContent = String(index);
|
|
262
|
+
head.appendChild(number);
|
|
263
|
+
head.appendChild(document.createTextNode(`${code} · ${width}px`));
|
|
264
|
+
const what = document.createElement('p');
|
|
265
|
+
what.textContent = message;
|
|
266
|
+
const page = document.createElement('p');
|
|
267
|
+
page.className = 'page';
|
|
268
|
+
page.textContent = decodeURI(new URL(url).pathname);
|
|
269
|
+
const element = document.createElement('p');
|
|
270
|
+
element.className = 'element';
|
|
271
|
+
element.textContent = detail;
|
|
272
|
+
for (const part of [head, what, page, element]) link.appendChild(part);
|
|
273
|
+
item.appendChild(link);
|
|
274
|
+
return item;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/** Every page of the site at every phone width, listed as each comes in. */
|
|
278
|
+
const runSite = async () => {
|
|
279
|
+
if (site) { stopSite(); status.textContent = 'Stopped.'; return; }
|
|
280
|
+
const controller = new AbortController();
|
|
281
|
+
site = controller;
|
|
282
|
+
siteButton.textContent = 'Stop';
|
|
283
|
+
findings = [];
|
|
284
|
+
current = -1;
|
|
285
|
+
place();
|
|
286
|
+
list.replaceChildren();
|
|
287
|
+
rulesSection.hidden = true;
|
|
288
|
+
pagesSection.hidden = true;
|
|
289
|
+
title.textContent = 'Constraints';
|
|
290
|
+
status.textContent = 'Finding the pages…';
|
|
291
|
+
const pages = await findSitePages();
|
|
292
|
+
const widths = `${VIEWPORT_WIDTHS.slice(0, -1).join(', ')} and ${VIEWPORT_WIDTHS[VIEWPORT_WIDTHS.length - 1]}px`;
|
|
293
|
+
let broken = 0;
|
|
294
|
+
const results = await checkSite({
|
|
295
|
+
pages,
|
|
296
|
+
inspect: (url, widths) => inspectInFrame(frames, url, widths),
|
|
297
|
+
signal: controller.signal,
|
|
298
|
+
onResult(result, done, total) {
|
|
299
|
+
const found = result.error ? [{ code: 'page', message: `It could not be checked: ${result.error}.`, element: '' }] : result.findings;
|
|
300
|
+
for (const { code, message, element } of found) list.appendChild(siteItem(++broken, result, code, message, element));
|
|
301
|
+
title.textContent = broken ? `Constraints · ${broken} broken` : 'Constraints';
|
|
302
|
+
status.textContent = `Checking ${done} of ${total}: ${pages.length} pages at ${widths}…`;
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
if (controller.signal.aborted) return;
|
|
306
|
+
showRules(summarizeRules(results), results.length);
|
|
307
|
+
showPages(results);
|
|
308
|
+
site = null;
|
|
309
|
+
siteButton.textContent = 'Site';
|
|
310
|
+
status.textContent = broken
|
|
311
|
+
? `${pages.length} pages at ${widths}: ${broken} broken.`
|
|
312
|
+
: `Every page keeps every constraint at ${widths} (${results.length} checks).`;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const show = (mode: 'page' | 'site' = 'page') => {
|
|
316
|
+
if (!panel.isConnected) document.body.appendChild(panel);
|
|
317
|
+
panel.hidden = false;
|
|
318
|
+
setLinesOnly(window.innerWidth < 640);
|
|
319
|
+
if (mode === 'site') void runSite(); else run();
|
|
320
|
+
layoutChanges.observe(document.body, {subtree:true, childList:true, attributes:true, attributeFilter:['style','class','hidden','data-ds-fault-lines','data-ds-fault-axis']});
|
|
321
|
+
sizeChanges?.observe(document.body);
|
|
322
|
+
window.addEventListener('scroll', schedule, { passive: true, capture: true });
|
|
323
|
+
window.addEventListener('resize', schedule);
|
|
324
|
+
};
|
|
325
|
+
const hide = () => {
|
|
326
|
+
stopSite();
|
|
327
|
+
panel.hidden = true;
|
|
328
|
+
if (frame) cancelAnimationFrame(frame);
|
|
329
|
+
frame = 0;
|
|
330
|
+
faultLines.replaceChildren();
|
|
331
|
+
layoutChanges.disconnect();
|
|
332
|
+
sizeChanges?.disconnect();
|
|
333
|
+
window.removeEventListener('scroll', schedule, { capture: true });
|
|
334
|
+
window.removeEventListener('resize', schedule);
|
|
335
|
+
};
|
|
336
|
+
shadow.querySelector('[data-run]')!.addEventListener('click', run);
|
|
337
|
+
siteButton.addEventListener('click', () => void runSite());
|
|
338
|
+
shadow.querySelector('[data-close]')!.addEventListener('click', hide);
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
show,
|
|
342
|
+
hide,
|
|
343
|
+
run,
|
|
344
|
+
runSite,
|
|
345
|
+
toggle: () => (panel.hidden ? show() : hide()),
|
|
346
|
+
get findings() { return findings; },
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** The device switch a site without sign-in has instead: `?ds-owner=on` once in a browser, `?ds-owner=off` to forget it. */
|
|
351
|
+
export const OWNER_DEVICE_KEY = 'ds-owner';
|
|
352
|
+
|
|
353
|
+
/** Takes `?ds-owner=on` or `off` from the address into this browser's storage for the site. */
|
|
354
|
+
function rememberOwnerDevice(): void {
|
|
355
|
+
const asked = new URLSearchParams(window.location.search).get('ds-owner');
|
|
356
|
+
if (asked !== 'on' && asked !== 'off') return;
|
|
357
|
+
try {
|
|
358
|
+
if (asked === 'on') localStorage.setItem(OWNER_DEVICE_KEY, 'on');
|
|
359
|
+
else localStorage.removeItem(OWNER_DEVICE_KEY);
|
|
360
|
+
} catch { /* Storage blocked: the switch lasts this page alone. */ }
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** A browser switched on as the owner's with `?ds-owner=on`. */
|
|
364
|
+
const isOwnerDevice = () => {
|
|
365
|
+
try { return localStorage.getItem(OWNER_DEVICE_KEY) === 'on'; } catch { return false; }
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Whether the viewer owns the page: `<html data-ds-owner>`, which a site with
|
|
370
|
+
* sign-in sets from its own server-checked owner, or a browser switched on as
|
|
371
|
+
* the owner's (`?ds-owner=on`) on a site without sign-in.
|
|
372
|
+
*/
|
|
373
|
+
export const isPageOwner = () => document.documentElement.hasAttribute('data-ds-owner') || isOwnerDevice()
|
|
374
|
+
|| new URLSearchParams(window.location.search).get('ds-owner') === 'on';
|
|
375
|
+
|
|
376
|
+
/** What the address asks the panel to show on load: `?constraints=1` this page, `?constraints=site` every page. */
|
|
377
|
+
export function askedConstraints(search = window.location.search): 'page' | 'site' | null {
|
|
378
|
+
const asked = new URLSearchParams(search).get('constraints');
|
|
379
|
+
if (asked === 'site') return 'site';
|
|
380
|
+
return asked === '1' || asked === 'page' || asked === '' ? 'page' : null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Five presses of C toggle the constraint panel, for the page's owner only
|
|
385
|
+
* (`isPageOwner`): for anyone else the presses do nothing. `?constraints=1` in
|
|
386
|
+
* the address opens it for anyone once the page has loaded, since it only
|
|
387
|
+
* measures; `?constraints=site` opens it on the whole site's check. Escape
|
|
388
|
+
* hides it. Presses typed into a field, with a modifier or held down never
|
|
389
|
+
* count, and any other key starts the count again.
|
|
390
|
+
*/
|
|
391
|
+
export function initConstraintShortcut(): void {
|
|
392
|
+
if (typeof document === 'undefined') return;
|
|
393
|
+
const root = document.documentElement;
|
|
394
|
+
if (root.hasAttribute('data-ds-constraints-ready')) return;
|
|
395
|
+
root.setAttribute('data-ds-constraints-ready', '');
|
|
396
|
+
rememberOwnerDevice();
|
|
397
|
+
let panel: ReturnType<typeof createConstraintPanel> | null = null;
|
|
398
|
+
const open = () => (panel ??= createConstraintPanel());
|
|
399
|
+
|
|
400
|
+
const asked = askedConstraints();
|
|
401
|
+
// Not in a frame of the site's own check, and only once the page and its pictures have drawn.
|
|
402
|
+
if (asked && window.parent === window) {
|
|
403
|
+
if (document.readyState === 'complete') open().show(asked);
|
|
404
|
+
else window.addEventListener('load', () => open().show(asked), { once: true });
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
let presses = 0;
|
|
408
|
+
let lastPress = 0;
|
|
409
|
+
const reset = () => { presses = 0; };
|
|
410
|
+
window.addEventListener('blur', reset);
|
|
411
|
+
window.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
412
|
+
const editing = document.designMode === 'on' || event.composedPath().some(target =>
|
|
413
|
+
target instanceof HTMLElement && (
|
|
414
|
+
target.isContentEditable || target.matches('input, textarea, select, [role="textbox"], [role="combobox"]')
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
if (editing || event.defaultPrevented || event.isComposing || event.repeat || event.metaKey || event.ctrlKey || event.altKey) {
|
|
418
|
+
reset();
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (event.key === 'Escape') panel?.hide();
|
|
422
|
+
if (event.key.toLowerCase() !== 'c') {
|
|
423
|
+
reset();
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const now = performance.now();
|
|
427
|
+
presses = now - lastPress <= 800 ? presses + 1 : 1;
|
|
428
|
+
lastPress = now;
|
|
429
|
+
if (presses === CONSTRAINT_PRESSES) {
|
|
430
|
+
reset();
|
|
431
|
+
if (isPageOwner()) open().toggle();
|
|
432
|
+
else panel?.hide();
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (typeof document !== 'undefined') {
|
|
438
|
+
if (document.readyState === 'loading') {
|
|
439
|
+
document.addEventListener('DOMContentLoaded', initConstraintShortcut, { once: true });
|
|
440
|
+
} else {
|
|
441
|
+
initConstraintShortcut();
|
|
442
|
+
}
|
|
443
|
+
}
|