@0001-labs/design-system-1 0.3.0-alpha.28 → 0.3.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/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 +422 -0
- package/DS1/0-face/constraint-site.ts +200 -0
- package/DS1/0-face/constraints.ts +281 -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/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 +14 -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 +35 -6
- 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 +45 -12
- package/DS1/2-core/styles/ds-button-split.css +8 -0
- package/DS1/2-core/styles/ds-button.css +92 -19
- 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 +32 -5
- 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/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 +45 -10
- 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-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-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 +429 -0
- package/dist/0-face/constraint-site.d.ts +72 -0
- package/dist/0-face/constraint-site.d.ts.map +1 -0
- package/dist/0-face/constraint-site.js +185 -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 +247 -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/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 +7 -0
- package/dist/2-core/ds-avatar.d.ts.map +1 -1
- package/dist/2-core/ds-avatar.js +41 -6
- 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/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 +50 -10
- 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-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-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 +5514 -2077
- package/dist/design-system-1.bundle.js.map +1 -1
- package/dist/design-system-1.bundle.min.js +7026 -4628
- 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 +23 -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,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cut words fade, never an ellipsis. Wherever Design system 1 cuts words that do
|
|
3
|
+
* not fit (a row's name, a tag, a menu entry, a calendar's title), they fade out
|
|
4
|
+
* over their last square (`var(--ds-unit)`), a mask on the words, so they fade
|
|
5
|
+
* into whatever is behind them. Words that fit stay crisp: the fade is drawn
|
|
6
|
+
* only while an element is marked `data-cut="end"`, and this module is what
|
|
7
|
+
* measures and marks it.
|
|
8
|
+
*
|
|
9
|
+
* Every stylesheet writes the fade the same way: the element clips
|
|
10
|
+
* (`text-overflow: clip`), and only under `[data-cut="end"]` takes
|
|
11
|
+
* `mask-image: linear-gradient(to right, #000 calc(100% - var(--ds-unit)), transparent)`,
|
|
12
|
+
* the gradient running to the left in a right-to-left page.
|
|
13
|
+
*
|
|
14
|
+
* - `watchCuts()` is the watcher a component owns: it marks the elements it
|
|
15
|
+
* watches while `scrollWidth > clientWidth + 1`, measures again when they
|
|
16
|
+
* resize, when `measure()` is called (after a render, since words can change
|
|
17
|
+
* without the box resizing), once the page's fonts have loaded and, with
|
|
18
|
+
* `text: true`, when the words inside them change. `disconnect()` lets go.
|
|
19
|
+
* - Every watcher measures in the next frame, together with every other one:
|
|
20
|
+
* all widths are read, then all marks written, so a page building a few
|
|
21
|
+
* hundred words lays itself out once for them rather than once each. Read
|
|
22
|
+
* one by one, after each element connected or updated, the words of Ezo's
|
|
23
|
+
* landing page laid it out again two hundred times, over half a second.
|
|
24
|
+
* Elements that resize are measured the same way, in one pass for all.
|
|
25
|
+
* - `CutFades` is the same watcher as a Lit reactive controller: it starts when
|
|
26
|
+
* its element connects, measures after every update and stops when it
|
|
27
|
+
* disconnects.
|
|
28
|
+
* - `startCutFades()` is for a page without Lit: it marks DS1's native classes
|
|
29
|
+
* (`.ds-row__name`, `.ds-sidebar__label`, `.ds-menu__item`, …) in the page,
|
|
30
|
+
* and keeps marking them as the page changes. It returns a function that
|
|
31
|
+
* stops it.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** The attribute a cut element carries: `data-cut="end"`. */
|
|
35
|
+
export const CUT_ATTRIBUTE = "data-cut";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The native classes DS1's stylesheets fade when they are marked cut, for
|
|
39
|
+
* `startCutFades()` on a page without Lit.
|
|
40
|
+
*/
|
|
41
|
+
export const CUT_FADE_SELECTOR = [
|
|
42
|
+
".ds-row__name",
|
|
43
|
+
".ds-sidebar__label",
|
|
44
|
+
".ds-menu__item",
|
|
45
|
+
".ds-badge__label",
|
|
46
|
+
".ds-notice__title",
|
|
47
|
+
".ds-notice__text",
|
|
48
|
+
".ds-progress__label",
|
|
49
|
+
".ds-stat__figure",
|
|
50
|
+
".ds-document__toc-list a",
|
|
51
|
+
".ds-footer__links a",
|
|
52
|
+
".item-text",
|
|
53
|
+
].join(", ");
|
|
54
|
+
|
|
55
|
+
/** Whether an element's words are wider than its box. */
|
|
56
|
+
export function isCut(element: Element): boolean {
|
|
57
|
+
return element.scrollWidth > element.clientWidth + 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Marks an element `data-cut="end"` while its words do not fit, and takes the mark off when they do. Returns whether it is cut. */
|
|
61
|
+
export function markCut(element: Element): boolean {
|
|
62
|
+
const cut = isCut(element);
|
|
63
|
+
const mark = element.getAttribute(CUT_ATTRIBUTE);
|
|
64
|
+
if (cut) {
|
|
65
|
+
if (mark !== "end") element.setAttribute(CUT_ATTRIBUTE, "end");
|
|
66
|
+
} else if (mark === "end") element.removeAttribute(CUT_ATTRIBUTE);
|
|
67
|
+
return cut;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Elements to watch: one, several, or a function that finds them again at each measure. */
|
|
71
|
+
export type CutSource = Element | Iterable<Element> | (() => Iterable<Element>);
|
|
72
|
+
|
|
73
|
+
export type CutWatchOptions = {
|
|
74
|
+
/** Also measure again when the words inside a watched element change (a MutationObserver). */
|
|
75
|
+
text?: boolean;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type CutWatcher = {
|
|
79
|
+
/** Watches these elements and measures them. A function is asked again at each measure, so elements a render adds are taken in. */
|
|
80
|
+
watch(source: CutSource): void;
|
|
81
|
+
/** Watches what matches `selector` inside `root`, found again at each measure. */
|
|
82
|
+
select(root: ParentNode, selector: string): void;
|
|
83
|
+
/** Measures every watched element again: after a render, or when words change. */
|
|
84
|
+
measure(): void;
|
|
85
|
+
/** Stops watching and lets every element go. Marks stay as they are. */
|
|
86
|
+
disconnect(): void;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type Watched = {
|
|
90
|
+
/** Finds the elements again and observes the new ones; returns them. */
|
|
91
|
+
refresh(): Set<Element>;
|
|
92
|
+
stopped: boolean;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/** Reads every element's widths first, then writes every mark, so the page is laid out once for all of them. */
|
|
96
|
+
function markAll(elements: Iterable<Element>) {
|
|
97
|
+
const cuts: [Element, boolean][] = [];
|
|
98
|
+
for (const element of elements) if (element.isConnected) cuts.push([element, isCut(element)]);
|
|
99
|
+
hookFonts();
|
|
100
|
+
for (const [element, cut] of cuts) {
|
|
101
|
+
const mark = element.getAttribute(CUT_ATTRIBUTE);
|
|
102
|
+
if (cut) {
|
|
103
|
+
if (mark !== "end") element.setAttribute(CUT_ATTRIBUTE, "end");
|
|
104
|
+
} else if (mark === "end") element.removeAttribute(CUT_ATTRIBUTE);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const live = new Set<Watched>();
|
|
109
|
+
const queued = new Set<Watched>();
|
|
110
|
+
let frame = false;
|
|
111
|
+
|
|
112
|
+
const nextFrame = (run: () => void) => {
|
|
113
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
114
|
+
else setTimeout(run, 0);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
function flush() {
|
|
118
|
+
frame = false;
|
|
119
|
+
const watchers = [...queued];
|
|
120
|
+
queued.clear();
|
|
121
|
+
const elements = new Set<Element>();
|
|
122
|
+
for (const watcher of watchers) {
|
|
123
|
+
if (watcher.stopped) continue;
|
|
124
|
+
for (const element of watcher.refresh()) elements.add(element);
|
|
125
|
+
}
|
|
126
|
+
markAll(elements);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Measures this watcher in the next frame, with every other watcher waiting for it. */
|
|
130
|
+
function schedule(watcher: Watched) {
|
|
131
|
+
if (watcher.stopped) return;
|
|
132
|
+
queued.add(watcher);
|
|
133
|
+
if (frame) return;
|
|
134
|
+
frame = true;
|
|
135
|
+
nextFrame(flush);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// One observer for every watched element: the sizes of a frame arrive in one
|
|
139
|
+
// call, read in one pass. An element two watchers hold (a row's name, which the
|
|
140
|
+
// row and its ds-text both watch) is let go when the last one does.
|
|
141
|
+
let sizes: ResizeObserver | undefined;
|
|
142
|
+
const holders = new Map<Element, number>();
|
|
143
|
+
function observe(element: Element) {
|
|
144
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
145
|
+
sizes ??= new ResizeObserver(entries => markAll(entries.map(entry => entry.target)));
|
|
146
|
+
const held = holders.get(element) ?? 0;
|
|
147
|
+
if (!held) sizes.observe(element);
|
|
148
|
+
holders.set(element, held + 1);
|
|
149
|
+
}
|
|
150
|
+
function unobserve(element: Element) {
|
|
151
|
+
const held = holders.get(element);
|
|
152
|
+
if (!held) return;
|
|
153
|
+
if (held > 1) { holders.set(element, held - 1); return; }
|
|
154
|
+
holders.delete(element);
|
|
155
|
+
sizes?.unobserve(element);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Words drawn in a fallback face are narrower or wider once the page's fonts
|
|
159
|
+
// arrive. Asking for `document.fonts.ready` lays out a page that has changed,
|
|
160
|
+
// so it is asked once, while a measure has just laid the page out anyway.
|
|
161
|
+
let fontsHooked = false;
|
|
162
|
+
function hookFonts() {
|
|
163
|
+
if (fontsHooked || typeof document === "undefined") return;
|
|
164
|
+
fontsHooked = true;
|
|
165
|
+
const again = () => { for (const watcher of live) schedule(watcher); };
|
|
166
|
+
const fonts = document.fonts;
|
|
167
|
+
fonts?.ready?.then(again, () => {});
|
|
168
|
+
fonts?.addEventListener?.("loadingdone", again);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** A watcher that marks the elements it watches `data-cut="end"` while their words do not fit. */
|
|
172
|
+
export function watchCuts(options: CutWatchOptions = {}): CutWatcher {
|
|
173
|
+
const sources: CutSource[] = [];
|
|
174
|
+
let watched = new Set<Element>();
|
|
175
|
+
const words = options.text && typeof MutationObserver !== "undefined"
|
|
176
|
+
? new MutationObserver(() => schedule(self))
|
|
177
|
+
: undefined;
|
|
178
|
+
|
|
179
|
+
const collect = () => {
|
|
180
|
+
const found = new Set<Element>();
|
|
181
|
+
for (const source of sources) {
|
|
182
|
+
const elements = typeof source === "function" ? source() : source instanceof Element ? [source] : source;
|
|
183
|
+
for (const element of elements) found.add(element);
|
|
184
|
+
}
|
|
185
|
+
return found;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const self: Watched = {
|
|
189
|
+
stopped: false,
|
|
190
|
+
refresh() {
|
|
191
|
+
const next = collect();
|
|
192
|
+
let changed = next.size !== watched.size;
|
|
193
|
+
for (const element of watched) {
|
|
194
|
+
if (!next.has(element)) { unobserve(element); changed = true; }
|
|
195
|
+
}
|
|
196
|
+
for (const element of next) {
|
|
197
|
+
if (!watched.has(element)) { observe(element); changed = true; }
|
|
198
|
+
}
|
|
199
|
+
// A MutationObserver cannot let one element go, so it starts again when the set changes.
|
|
200
|
+
if (words && changed) {
|
|
201
|
+
words.disconnect();
|
|
202
|
+
for (const element of next) words.observe(element, { childList: true, characterData: true, subtree: true });
|
|
203
|
+
}
|
|
204
|
+
watched = next;
|
|
205
|
+
return watched;
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
live.add(self);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
watch(source) { sources.push(source); schedule(self); },
|
|
212
|
+
select(root, selector) { sources.push(() => root.querySelectorAll(selector)); schedule(self); },
|
|
213
|
+
measure() { schedule(self); },
|
|
214
|
+
disconnect() {
|
|
215
|
+
self.stopped = true;
|
|
216
|
+
live.delete(self);
|
|
217
|
+
queued.delete(self);
|
|
218
|
+
for (const element of watched) unobserve(element);
|
|
219
|
+
words?.disconnect();
|
|
220
|
+
watched = new Set();
|
|
221
|
+
sources.length = 0;
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The part of a Lit element `CutFades` uses, so this module needs nothing from
|
|
229
|
+
* Lit. The render root is read as a node to search; it is typed loosely so an
|
|
230
|
+
* element type-checks in every product, whichever DOM library it compiles with.
|
|
231
|
+
*/
|
|
232
|
+
type ControllerHost = Element & {
|
|
233
|
+
addController(controller: { hostConnected?(): void; hostUpdated?(): void; hostDisconnected?(): void }): void;
|
|
234
|
+
readonly renderRoot?: unknown;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export type CutFadeOptions = {
|
|
238
|
+
/** What to measure in the element's render root (its shadow root), found again after every update. */
|
|
239
|
+
selector?: string;
|
|
240
|
+
/** Other elements to measure, asked again after every update: the host itself, its slotted children. */
|
|
241
|
+
targets?: () => Iterable<Element>;
|
|
242
|
+
/** Also measure again when the element's own children or words change (the words slotted into it). */
|
|
243
|
+
text?: boolean;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The cut-words watcher as a Lit reactive controller:
|
|
248
|
+
* `protected readonly cuts = new CutFades(this, { selector: ".label" })`. It watches from
|
|
249
|
+
* when the element connects to when it disconnects, and measures after every
|
|
250
|
+
* update; call `measure()` when words change outside an update.
|
|
251
|
+
*/
|
|
252
|
+
export class CutFades {
|
|
253
|
+
private watcher: CutWatcher | undefined;
|
|
254
|
+
private words: MutationObserver | undefined;
|
|
255
|
+
private readonly host: ControllerHost;
|
|
256
|
+
private readonly options: CutFadeOptions;
|
|
257
|
+
|
|
258
|
+
constructor(host: ControllerHost, options: CutFadeOptions) {
|
|
259
|
+
this.host = host;
|
|
260
|
+
this.options = options;
|
|
261
|
+
host.addController(this);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
hostConnected() {
|
|
265
|
+
this.hostDisconnected();
|
|
266
|
+
const watcher = watchCuts();
|
|
267
|
+
const { selector, targets, text } = this.options;
|
|
268
|
+
if (selector) watcher.watch(() => ((this.host.renderRoot as ParentNode | undefined) ?? this.host).querySelectorAll(selector));
|
|
269
|
+
if (targets) watcher.watch(targets);
|
|
270
|
+
this.watcher = watcher;
|
|
271
|
+
// Words slotted into the element can change without an update or a resize.
|
|
272
|
+
if (text && typeof MutationObserver !== "undefined") {
|
|
273
|
+
this.words = new MutationObserver(() => this.measure());
|
|
274
|
+
this.words.observe(this.host, { childList: true, characterData: true, subtree: true });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
hostUpdated() { this.measure(); }
|
|
279
|
+
|
|
280
|
+
hostDisconnected() {
|
|
281
|
+
this.words?.disconnect();
|
|
282
|
+
this.words = undefined;
|
|
283
|
+
this.watcher?.disconnect();
|
|
284
|
+
this.watcher = undefined;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** Measures again, as after an update. */
|
|
288
|
+
measure() { this.watcher?.measure(); }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Marks DS1's native classes cut on a page without Lit, so their words fade
|
|
293
|
+
* where they are cut, and keeps marking them as the page changes. Returns a
|
|
294
|
+
* function that stops it.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* // A module script on the page, beside one.css and controls.css (Sync 1 `root` `"modules": ["cut-fade"]`):
|
|
298
|
+
* startCutFades();
|
|
299
|
+
*/
|
|
300
|
+
export function startCutFades(root: ParentNode = document, selector: string = CUT_FADE_SELECTOR): () => void {
|
|
301
|
+
const watcher = watchCuts();
|
|
302
|
+
watcher.select(root, selector);
|
|
303
|
+
// The page is marked as it starts, in one pass; its changes are measured in the frame after them.
|
|
304
|
+
markAll(root.querySelectorAll(selector));
|
|
305
|
+
const changes = typeof MutationObserver === "undefined" ? undefined : new MutationObserver(() => watcher.measure());
|
|
306
|
+
const node = root instanceof Document ? root.documentElement : (root as Node);
|
|
307
|
+
changes?.observe(node, { childList: true, characterData: true, subtree: true });
|
|
308
|
+
return () => {
|
|
309
|
+
changes?.disconnect();
|
|
310
|
+
watcher.disconnect();
|
|
311
|
+
};
|
|
312
|
+
}
|
package/DS1/0-face/define.ts
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
|
+
type StyledElement = HTMLElement & {
|
|
2
|
+
createRenderRoot?: () => HTMLElement | ShadowRoot;
|
|
3
|
+
renderOptions?: { renderBefore?: ChildNode | null };
|
|
4
|
+
};
|
|
5
|
+
type StyledConstructor = CustomElementConstructor & {
|
|
6
|
+
elementStyles?: Array<{ cssText?: string; cssRules?: CSSRuleList }>;
|
|
7
|
+
shadowRootOptions?: ShadowRootInit;
|
|
8
|
+
};
|
|
9
|
+
|
|
1
10
|
/** Register a shared element once; a fresh page picks up changes during HMR. */
|
|
2
11
|
export function define(name: string, element: CustomElementConstructor): void {
|
|
3
|
-
if (typeof customElements ===
|
|
4
|
-
|
|
12
|
+
if (typeof customElements === 'undefined' || customElements.get(name)) return;
|
|
13
|
+
const type = element as StyledConstructor;
|
|
14
|
+
const prototype = element.prototype as StyledElement;
|
|
15
|
+
const original = prototype.createRenderRoot;
|
|
16
|
+
if (original) {
|
|
17
|
+
const definingDocument = document;
|
|
18
|
+
prototype.createRenderRoot = function (this: StyledElement) {
|
|
19
|
+
if (this.ownerDocument === definingDocument || !type.elementStyles?.length) return original.call(this);
|
|
20
|
+
// Constructed sheets cannot cross documents. The exact finalized component
|
|
21
|
+
// styles can, as ordinary style nodes in the owning document's shadow root.
|
|
22
|
+
const root = this.shadowRoot ?? this.attachShadow(type.shadowRootOptions ?? { mode: 'open' });
|
|
23
|
+
for (const sheet of type.elementStyles) {
|
|
24
|
+
const style = this.ownerDocument.createElement('style');
|
|
25
|
+
style.textContent = sheet.cssText ?? Array.from(sheet.cssRules ?? [], rule => rule.cssText).join('\n');
|
|
26
|
+
root.append(style);
|
|
27
|
+
}
|
|
28
|
+
if (this.renderOptions) this.renderOptions.renderBefore ??= root.firstChild;
|
|
29
|
+
return root;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
customElements.define(name, element);
|
|
5
33
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A face Design system 1 did not draw, set on the sixteen: its `@font-face` corrected once so that at 14px on a
|
|
3
|
+
* 16px line its capitals are 10px tall and its baseline stands 3px above the square's foot, as GT America's do
|
|
4
|
+
* (https://designsystem1.com/1-root/constraints/#a-face-you-add). Plain TypeScript with no imports, for the
|
|
5
|
+
* browser and for a build script alike.
|
|
6
|
+
*
|
|
7
|
+
* A face's metrics are fractions of its em: the ascent and descent the browser sets a line with and the height
|
|
8
|
+
* of its capitals (`readFaceMetrics` takes them from a TrueType or OpenType file). `google-face-metrics.json`
|
|
9
|
+
* beside this module holds them for the Google faces 0001's products offer; `scripts/face-metrics.mjs` measures
|
|
10
|
+
* more. Correct the face, never its words: no padding, `top` or transform in a component.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** A face's vertical metrics, each over its em. */
|
|
14
|
+
export interface FaceMetrics {
|
|
15
|
+
ascent: number;
|
|
16
|
+
descent: number;
|
|
17
|
+
capHeight: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** GT America's: capitals 0.71 of the em, and its ascent less its descent, which places the baseline in a line. */
|
|
21
|
+
export const SIXTEEN_FACE = { capHeight: 0.71, baseline: 0.742 } as const;
|
|
22
|
+
|
|
23
|
+
/** The four `@font-face` descriptors that put a face on the sixteen, as CSS values. */
|
|
24
|
+
export interface FaceDescriptors {
|
|
25
|
+
sizeAdjust: string;
|
|
26
|
+
ascentOverride: string;
|
|
27
|
+
descentOverride: string;
|
|
28
|
+
lineGapOverride: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The descriptors for a face: `size-adjust` makes its capitals 0.71 of the em, and the overrides make its ascent
|
|
33
|
+
* less its descent 0.742 while it keeps its own height of ascent and descent. `size-adjust` scales the overrides
|
|
34
|
+
* too, so they are given before it.
|
|
35
|
+
*/
|
|
36
|
+
export function faceDescriptors({ ascent, descent, capHeight }: FaceMetrics): FaceDescriptors {
|
|
37
|
+
if (!(capHeight > 0) || !(ascent + descent > 0)) throw new Error('A face needs a cap height and a line height');
|
|
38
|
+
const size = SIXTEEN_FACE.capHeight / capHeight;
|
|
39
|
+
const height = Math.max((ascent + descent) * size, SIXTEEN_FACE.baseline);
|
|
40
|
+
const percent = (value: number) => `${+(value * 100).toFixed(2)}%`;
|
|
41
|
+
return {
|
|
42
|
+
sizeAdjust: percent(size),
|
|
43
|
+
ascentOverride: percent((height + SIXTEEN_FACE.baseline) / 2 / size),
|
|
44
|
+
descentOverride: percent((height - SIXTEEN_FACE.baseline) / 2 / size),
|
|
45
|
+
lineGapOverride: '0%',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The descriptors as declarations for an `@font-face` rule. */
|
|
50
|
+
export function faceCorrection(metrics: FaceMetrics): string {
|
|
51
|
+
const { sizeAdjust, ascentOverride, descentOverride, lineGapOverride } = faceDescriptors(metrics);
|
|
52
|
+
return `size-adjust:${sizeAdjust};ascent-override:${ascentOverride};descent-override:${descentOverride};line-gap-override:${lineGapOverride}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A stylesheet of `@font-face` rules (Google's css2 answer, say) with every face corrected in its own rule,
|
|
57
|
+
* without comments or spaces. A face with no metrics stops it: an uncorrected face would stand off the sixteen.
|
|
58
|
+
*/
|
|
59
|
+
export function correctFaces(css: string, metrics: Readonly<Record<string, FaceMetrics>>): string {
|
|
60
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\s*([{};:,])\s*/g, '$1').trim().replace(/@font-face{([^}]*)}/g, (_, body: string) => {
|
|
61
|
+
const family = body.match(/font-family:(['"]?)([^;'"]+)\1(?:;|$)/)?.[2];
|
|
62
|
+
if (!family || !Object.hasOwn(metrics, family)) throw new Error(`No metrics for the face ${family ?? '(unnamed)'}`);
|
|
63
|
+
return `@font-face{${body}${body.endsWith(';') ? '' : ';'}${faceCorrection(metrics[family]!)}}`;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Google's css2 stylesheet at `href`, read and corrected. css2 answers with woff2 to the browser asking. */
|
|
68
|
+
export async function correctedGoogleFonts(href: string, metrics: Readonly<Record<string, FaceMetrics>>, init?: RequestInit): Promise<string> {
|
|
69
|
+
const response = await fetch(href, init);
|
|
70
|
+
if (!response.ok) throw new Error(`Google Fonts answered ${response.status} for ${href}`);
|
|
71
|
+
return correctFaces(await response.text(), metrics);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The metrics a browser sets a line of the face with, from its TrueType or OpenType file (not woff2): `hhea`'s
|
|
76
|
+
* ascent and descent, or `OS/2`'s typographic ones when the face asks for them (USE_TYPO_METRICS), and `OS/2`'s
|
|
77
|
+
* cap height, each over `head`'s units per em, to four places.
|
|
78
|
+
*/
|
|
79
|
+
export function readFaceMetrics(file: Uint8Array): FaceMetrics {
|
|
80
|
+
const view = new DataView(file.buffer, file.byteOffset, file.byteLength);
|
|
81
|
+
const tables = new Map<string, number>();
|
|
82
|
+
for (let i = 0, count = view.getUint16(4); i < count; i++) {
|
|
83
|
+
const at = 12 + i * 16;
|
|
84
|
+
tables.set(String.fromCharCode(...file.subarray(at, at + 4)), view.getUint32(at + 8));
|
|
85
|
+
}
|
|
86
|
+
const head = tables.get('head'), hhea = tables.get('hhea'), os2 = tables.get('OS/2');
|
|
87
|
+
if (head === undefined || hhea === undefined || os2 === undefined) throw new Error('Not a TrueType or OpenType face');
|
|
88
|
+
const em = view.getUint16(head + 18);
|
|
89
|
+
const typo = (view.getUint16(os2 + 62) & 0x80) !== 0;
|
|
90
|
+
const ascent = typo ? view.getInt16(os2 + 68) : view.getInt16(hhea + 4);
|
|
91
|
+
const descent = -(typo ? view.getInt16(os2 + 70) : view.getInt16(hhea + 6));
|
|
92
|
+
const capHeight = view.getUint16(os2) >= 2 ? view.getInt16(os2 + 88) : 0;
|
|
93
|
+
if (!capHeight) throw new Error('The face has no cap height in OS/2');
|
|
94
|
+
const fraction = (value: number) => Math.round((value / em) * 10000) / 10000;
|
|
95
|
+
return { ascent: fraction(ascent), descent: fraction(descent), capHeight: fraction(capHeight) };
|
|
96
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** A real operation failure, separate from validation, warnings and message colour.
|
|
2
|
+
* Applications subscribe to `ds-failure`; this module never sends network requests.
|
|
3
|
+
* Use an authored, stable code and summary, never user content or a server response.
|
|
4
|
+
*/
|
|
5
|
+
export interface Failure {
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
/** Original caught error; only its stack frames enter the diagnostic. */
|
|
9
|
+
error?: unknown;
|
|
10
|
+
/** Captured at reporting time so startup handoff keeps the original call site. */
|
|
11
|
+
stack?: string;
|
|
12
|
+
}
|
|
13
|
+
export const FAILURE_EVENT = "ds-failure";
|
|
14
|
+
/** A bounded handoff for failures shown before the application reporter starts. */
|
|
15
|
+
const PENDING = Symbol.for("design-system-1.pending-failures");
|
|
16
|
+
|
|
17
|
+
/** Report a failed operation. Safe during server rendering; no DOM text is read. */
|
|
18
|
+
export function reportFailure(failure: Failure): void {
|
|
19
|
+
if (typeof window === "undefined" || typeof failure?.code !== "string" || typeof failure.message !== "string" || !/^[a-z][a-z0-9_.-]{0,79}$/.test(failure.code) || !failure.message.trim()) return;
|
|
20
|
+
const source = failure.error instanceof Error ? failure.error : new Error();
|
|
21
|
+
const stack = (failure.stack ?? source.stack ?? "").split("\n")
|
|
22
|
+
.filter(line => /^\s*at\s/.test(line) || /@.*:\d+/.test(line))
|
|
23
|
+
.slice(0, 8).join("\n").trim().slice(0, 500);
|
|
24
|
+
const detail = { code: failure.code, message: failure.message.trim().slice(0, 200), ...(stack ? { stack } : {}) };
|
|
25
|
+
// A reporter acknowledges by preventing the default: queueing for later.
|
|
26
|
+
if (window.dispatchEvent(new CustomEvent<Failure>(FAILURE_EVENT, { detail, cancelable: true }))) {
|
|
27
|
+
const scope = globalThis as unknown as Record<symbol, Failure[] | undefined>;
|
|
28
|
+
const pending = scope[PENDING] ??= [];
|
|
29
|
+
pending.push(detail);
|
|
30
|
+
if (pending.length > 20) pending.shift();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `confirm()` and `prompt()`, for pages without Lit or any other framework.
|
|
4
4
|
*
|
|
5
5
|
* Each is drawn on the native `dialog.ds-overlay` frame from `1-root/controls.css`
|
|
6
|
-
* (which the page loads) with its native buttons, `.ds-button--primary`,
|
|
6
|
+
* (which the page loads), as a sheet from the screen's foot on a phone, with its native buttons, `.ds-button--primary`,
|
|
7
7
|
* `--secondary` and `--danger`, and opened with `showModal()`, so the browser
|
|
8
8
|
* keeps the rest of the page inert behind it. Their words default to the
|
|
9
9
|
* shared words (OK, Cancel) in the page's language where the page loads the
|
|
@@ -99,8 +99,10 @@ function show(spec: Spec): Promise<boolean | string | null> {
|
|
|
99
99
|
return new Promise(resolve => {
|
|
100
100
|
const id = `ds-feedback-${++count}`;
|
|
101
101
|
const opener = focused();
|
|
102
|
+
// A sheet from the foot of a phone's screen, never a modal there (Joachim, 20 October 2026).
|
|
103
|
+
const phone = typeof matchMedia === "function" && matchMedia("(max-width: 768px)").matches;
|
|
102
104
|
const dialog = element("dialog", {
|
|
103
|
-
class: "ds-overlay",
|
|
105
|
+
class: phone ? "ds-overlay ds-overlay--sheet" : "ds-overlay",
|
|
104
106
|
role: spec.kind === "prompt" ? "dialog" : "alertdialog",
|
|
105
107
|
"aria-labelledby": `${id}-title`,
|
|
106
108
|
"data-ds-feedback": spec.kind,
|
|
@@ -127,7 +129,7 @@ function show(spec: Spec): Promise<boolean | string | null> {
|
|
|
127
129
|
|
|
128
130
|
const footer = element("div", { "data-ds-overlay": "footer" });
|
|
129
131
|
const cancel = spec.cancel === undefined ? undefined : element("button", { type: "button", class: "ds-button ds-button--secondary", value: "cancel" }, spec.cancel);
|
|
130
|
-
const confirm = element("button", { type: "button", class: spec.danger ? "ds-button ds-button--
|
|
132
|
+
const confirm = element("button", { type: "button", class: spec.danger ? "ds-button ds-button--danger" : "ds-button ds-button--primary", value: "confirm" }, spec.confirm);
|
|
131
133
|
if (cancel) footer.appendChild(cancel);
|
|
132
134
|
footer.appendChild(confirm);
|
|
133
135
|
dialog.appendChild(footer);
|
package/DS1/0-face/feedback.ts
CHANGED
|
@@ -38,3 +38,6 @@ export { copyText } from "./copy-text";
|
|
|
38
38
|
export type { CopyTextOptions } from "./copy-text";
|
|
39
39
|
export { setFeedbackWords } from "./feedback-words";
|
|
40
40
|
export type { FeedbackWord, FeedbackWords } from "./feedback-words";
|
|
41
|
+
|
|
42
|
+
export { reportFailure, FAILURE_EVENT } from "./failures";
|
|
43
|
+
export type { Failure } from "./failures";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Image focus with Apple's Vision framework: the faces in each picture and the part a person looks at
|
|
2
|
+
// first (attention-based saliency), as JSON for `focusFromRegions()` in focus.ts. macOS only; a build
|
|
3
|
+
// script runs it where it can and falls back to `focusOf()` elsewhere.
|
|
4
|
+
//
|
|
5
|
+
// swift focus-vision.swift photo.jpg other.jpg …
|
|
6
|
+
// {"photo.jpg":{"faces":[{"x":0.41,"y":0.12,"w":0.18,"h":0.14}],"salient":[…]}, …}
|
|
7
|
+
//
|
|
8
|
+
// Boxes are fractions of the picture, from its top left corner, as the web measures them.
|
|
9
|
+
import Foundation
|
|
10
|
+
import Vision
|
|
11
|
+
|
|
12
|
+
func box(_ rect: CGRect) -> [String: Double] {
|
|
13
|
+
["x": rect.minX, "y": 1 - rect.maxY, "w": rect.width, "h": rect.height]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
var result: [String: [String: [[String: Double]]]] = [:]
|
|
17
|
+
for path in CommandLine.arguments.dropFirst() {
|
|
18
|
+
let url = URL(fileURLWithPath: path)
|
|
19
|
+
let faces = VNDetectFaceRectanglesRequest()
|
|
20
|
+
let salient = VNGenerateAttentionBasedSaliencyImageRequest()
|
|
21
|
+
let handler = VNImageRequestHandler(url: url, options: [:])
|
|
22
|
+
do { try handler.perform([faces, salient]) } catch {
|
|
23
|
+
FileHandle.standardError.write("\(path): \(error.localizedDescription)\n".data(using: .utf8)!)
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
let found = (faces.results ?? []).filter { $0.confidence > 0.6 }.map { box($0.boundingBox) }
|
|
27
|
+
let objects = (salient.results?.first?.salientObjects ?? []).map { box($0.boundingBox) }
|
|
28
|
+
result[url.lastPathComponent] = ["faces": found, "salient": objects]
|
|
29
|
+
}
|
|
30
|
+
let data = try JSONSerialization.data(withJSONObject: result, options: [.sortedKeys])
|
|
31
|
+
FileHandle.standardOutput.write(data)
|