@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.
Files changed (782) hide show
  1. package/DS1/0-face/button-label.ts +28 -0
  2. package/DS1/0-face/calendar.ts +6 -4
  3. package/DS1/0-face/carousel.ts +70 -0
  4. package/DS1/0-face/constraint-panel.ts +443 -0
  5. package/DS1/0-face/constraint-site.ts +201 -0
  6. package/DS1/0-face/constraints.ts +308 -0
  7. package/DS1/0-face/copy-text.ts +1 -1
  8. package/DS1/0-face/cut-fade.ts +312 -0
  9. package/DS1/0-face/define.ts +30 -2
  10. package/DS1/0-face/face-correction.ts +96 -0
  11. package/DS1/0-face/failures.ts +32 -0
  12. package/DS1/0-face/fault-lines.ts +159 -0
  13. package/DS1/0-face/feedback-overlays.ts +5 -3
  14. package/DS1/0-face/feedback.ts +3 -0
  15. package/DS1/0-face/focus-vision.swift +31 -0
  16. package/DS1/0-face/focus.ts +181 -0
  17. package/DS1/0-face/google-face-metrics.json +102 -0
  18. package/DS1/0-face/grid.ts +61 -4
  19. package/DS1/0-face/i18n.ts +36 -18
  20. package/DS1/0-face/layout-inspector.ts +124 -98
  21. package/DS1/0-face/preference-options.ts +4 -0
  22. package/DS1/0-face/scaling.ts +21 -3
  23. package/DS1/0-face/shape.ts +43 -0
  24. package/DS1/0-face/text-contrast.ts +164 -0
  25. package/DS1/0-face/theme-bootstrap.js +43 -0
  26. package/DS1/0-face/toast-queue.ts +7 -1
  27. package/DS1/0-face/translations/da.json +10 -1
  28. package/DS1/0-face/translations/de.json +10 -1
  29. package/DS1/0-face/translations/en.json +10 -1
  30. package/DS1/0-face/translations/es.json +10 -1
  31. package/DS1/0-face/translations/fi.json +10 -1
  32. package/DS1/0-face/translations/fr.json +10 -1
  33. package/DS1/0-face/translations/is.json +10 -1
  34. package/DS1/0-face/translations/it.json +10 -1
  35. package/DS1/0-face/translations/ja.json +10 -1
  36. package/DS1/0-face/translations/ko.json +10 -1
  37. package/DS1/0-face/translations/nb.json +10 -1
  38. package/DS1/0-face/translations/pt-BR.json +10 -1
  39. package/DS1/0-face/translations/pt.json +10 -1
  40. package/DS1/0-face/translations/sv.json +10 -1
  41. package/DS1/0-face/translations/zh.json +10 -1
  42. package/DS1/0-face/word-wrap.ts +113 -0
  43. package/DS1/1-root/card.css +47 -20
  44. package/DS1/1-root/carousel.css +7 -0
  45. package/DS1/1-root/cjk.css +1 -1
  46. package/DS1/1-root/component-tokens.css +3 -2
  47. package/DS1/1-root/context.css +44 -6
  48. package/DS1/1-root/controls.css +99 -8
  49. package/DS1/1-root/document.css +9 -1
  50. package/DS1/1-root/empty.css +46 -5
  51. package/DS1/1-root/figures.css +50 -3
  52. package/DS1/1-root/fonts.css +1 -1
  53. package/DS1/1-root/footer.css +147 -16
  54. package/DS1/1-root/foundation.ts +60 -0
  55. package/DS1/1-root/guide.css +35 -0
  56. package/DS1/1-root/header.css +30 -9
  57. package/DS1/1-root/material.css +67 -0
  58. package/DS1/1-root/notice.css +10 -2
  59. package/DS1/1-root/one.css +15 -7
  60. package/DS1/1-root/progress.css +9 -1
  61. package/DS1/1-root/row.css +68 -2
  62. package/DS1/1-root/table.css +47 -4
  63. package/DS1/1-root/text.css +26 -0
  64. package/DS1/2-core/button-split.ts +10 -5
  65. package/DS1/2-core/chart/chart.css +71 -2
  66. package/DS1/2-core/chart/grid-chart.ts +2 -1
  67. package/DS1/2-core/ds-activity.ts +32 -0
  68. package/DS1/2-core/ds-app-chrome.ts +1 -0
  69. package/DS1/2-core/ds-avatar.ts +75 -7
  70. package/DS1/2-core/ds-badge.ts +8 -1
  71. package/DS1/2-core/ds-button.ts +7 -1
  72. package/DS1/2-core/ds-chart.ts +184 -49
  73. package/DS1/2-core/ds-cycle.ts +27 -186
  74. package/DS1/2-core/ds-device-bezel.ts +1 -0
  75. package/DS1/2-core/ds-empty.ts +6 -4
  76. package/DS1/2-core/ds-input.ts +23 -3
  77. package/DS1/2-core/ds-message.ts +22 -0
  78. package/DS1/2-core/ds-number.ts +349 -0
  79. package/DS1/2-core/ds-progress.ts +3 -0
  80. package/DS1/2-core/ds-radio.ts +3 -0
  81. package/DS1/2-core/ds-stat.ts +3 -0
  82. package/DS1/2-core/ds-switch.ts +5 -1
  83. package/DS1/2-core/ds-tag.ts +9 -2
  84. package/DS1/2-core/ds-text.ts +7 -0
  85. package/DS1/2-core/ds-token.ts +3 -0
  86. package/DS1/2-core/ds-tooltip.ts +17 -2
  87. package/DS1/2-core/ds-window.ts +1 -0
  88. package/DS1/2-core/generated/ds-icon-map.ts +47 -5
  89. package/DS1/2-core/generated/icons-extra.ts +24 -3
  90. package/DS1/2-core/generated/icons-immediate.ts +3 -3
  91. package/DS1/2-core/number-expression.ts +64 -0
  92. package/DS1/2-core/styles/ds-activity.css +16 -0
  93. package/DS1/2-core/styles/ds-badge.css +4 -1
  94. package/DS1/2-core/styles/ds-button-host.css +47 -13
  95. package/DS1/2-core/styles/ds-button-split.css +8 -0
  96. package/DS1/2-core/styles/ds-button.css +94 -20
  97. package/DS1/2-core/styles/ds-card.css +6 -0
  98. package/DS1/2-core/styles/ds-checkbox.css +20 -8
  99. package/DS1/2-core/styles/ds-image.css +2 -1
  100. package/DS1/2-core/styles/ds-input.css +37 -4
  101. package/DS1/2-core/styles/ds-number.css +127 -0
  102. package/DS1/2-core/styles/ds-radio.css +4 -1
  103. package/DS1/2-core/styles/ds-switch.css +34 -4
  104. package/DS1/2-core/styles/ds-tag.css +34 -6
  105. package/DS1/2-core/styles/ds-text.css +13 -4
  106. package/DS1/2-core/styles/ds-token.css +4 -1
  107. package/DS1/2-core/styles/ds-tooltip.css +13 -7
  108. package/DS1/3-unit/calendar-base.ts +5 -2
  109. package/DS1/3-unit/context-trigger.ts +29 -2
  110. package/DS1/3-unit/ds-calendar.ts +711 -37
  111. package/DS1/3-unit/ds-carousel.ts +13 -1
  112. package/DS1/3-unit/ds-context.ts +40 -2
  113. package/DS1/3-unit/ds-form.ts +47 -11
  114. package/DS1/3-unit/ds-list.ts +31 -3
  115. package/DS1/3-unit/ds-matrix.ts +3 -0
  116. package/DS1/3-unit/ds-menu.ts +9 -5
  117. package/DS1/3-unit/ds-row.ts +17 -2
  118. package/DS1/3-unit/ds-select.ts +1 -1
  119. package/DS1/3-unit/ds-sidebar.ts +18 -3
  120. package/DS1/3-unit/ds-table-of-contents.ts +166 -0
  121. package/DS1/3-unit/ds-table.ts +2 -1
  122. package/DS1/3-unit/ds-tabs.ts +40 -2
  123. package/DS1/3-unit/styles/ds-calendar.css +356 -42
  124. package/DS1/3-unit/styles/ds-context.css +38 -0
  125. package/DS1/3-unit/styles/ds-list.css +26 -1
  126. package/DS1/3-unit/styles/ds-matrix.css +4 -1
  127. package/DS1/3-unit/styles/ds-row.css +39 -0
  128. package/DS1/3-unit/styles/ds-select.css +22 -12
  129. package/DS1/3-unit/styles/ds-sidebar.css +16 -2
  130. package/DS1/3-unit/styles/ds-table-of-contents.css +40 -0
  131. package/DS1/3-unit/styles/ds-tabs.css +95 -0
  132. package/DS1/4-page/ds-container.ts +2 -1
  133. package/DS1/4-page/ds-document.ts +3 -0
  134. package/DS1/4-page/ds-footer.ts +93 -18
  135. package/DS1/4-page/ds-header.ts +5 -1
  136. package/DS1/4-page/ds-overlay.ts +8 -3
  137. package/DS1/4-page/ds-page.ts +22 -1
  138. package/DS1/4-page/email.ts +7 -4
  139. package/DS1/4-page/styles/ds-container.css +0 -1
  140. package/DS1/4-page/styles/ds-overlay.css +7 -0
  141. package/DS1/4-page/styles/ds-page.css +10 -0
  142. package/DS1/5-visual-kit/app-chrome.ts +129 -0
  143. package/DS1/5-visual-kit/bezels.ts +394 -0
  144. package/DS1/5-visual-kit/browser-icons.LICENSE +53 -0
  145. package/DS1/5-visual-kit/browser-icons.ts +47 -0
  146. package/DS1/5-visual-kit/browser-styles.ts +53 -0
  147. package/DS1/5-visual-kit/device-bezel.ts +55 -0
  148. package/DS1/5-visual-kit/instagram-frame.ts +15 -0
  149. package/DS1/5-visual-kit/instagram.ts +41 -0
  150. package/DS1/5-visual-kit/mobile-chrome.ts +25 -0
  151. package/DS1/5-visual-kit/native-icon-paths.ts +145 -0
  152. package/DS1/5-visual-kit/window.ts +22 -0
  153. package/DS1/components.ts +1 -0
  154. package/DS1/index.ts +14 -1
  155. package/DS1/react/choice.ts +4 -2
  156. package/DS1/react/context.ts +11 -6
  157. package/DS1/react/empty.ts +2 -2
  158. package/DS1/react/footer.ts +5 -5
  159. package/DS1/react/header.ts +1 -1
  160. package/DS1/react/message.ts +4 -2
  161. package/DS1/react/number.ts +53 -0
  162. package/DS1/react/sidebar.ts +4 -2
  163. package/DS1/react/table-of-contents.ts +28 -0
  164. package/DS1/x-flag/LICENSE.md +26 -0
  165. package/DS1/x-flag/ac.svg +1 -0
  166. package/DS1/x-flag/ad.svg +1 -0
  167. package/DS1/x-flag/ae.svg +1 -0
  168. package/DS1/x-flag/af.svg +1 -0
  169. package/DS1/x-flag/ag.svg +1 -0
  170. package/DS1/x-flag/ai.svg +1 -0
  171. package/DS1/x-flag/al.svg +1 -0
  172. package/DS1/x-flag/am.svg +1 -0
  173. package/DS1/x-flag/ao.svg +1 -0
  174. package/DS1/x-flag/aq.svg +1 -0
  175. package/DS1/x-flag/ar.svg +1 -0
  176. package/DS1/x-flag/as.svg +1 -0
  177. package/DS1/x-flag/at.svg +1 -0
  178. package/DS1/x-flag/au.svg +1 -0
  179. package/DS1/x-flag/aw.svg +1 -0
  180. package/DS1/x-flag/ax.svg +1 -0
  181. package/DS1/x-flag/az.svg +1 -0
  182. package/DS1/x-flag/ba.svg +1 -0
  183. package/DS1/x-flag/bb.svg +1 -0
  184. package/DS1/x-flag/bd.svg +1 -0
  185. package/DS1/x-flag/be.svg +1 -0
  186. package/DS1/x-flag/bf.svg +1 -0
  187. package/DS1/x-flag/bg.svg +1 -0
  188. package/DS1/x-flag/bh.svg +1 -0
  189. package/DS1/x-flag/bi.svg +1 -0
  190. package/DS1/x-flag/bj.svg +1 -0
  191. package/DS1/x-flag/bl.svg +1 -0
  192. package/DS1/x-flag/bm.svg +1 -0
  193. package/DS1/x-flag/bn.svg +1 -0
  194. package/DS1/x-flag/bo.svg +1 -0
  195. package/DS1/x-flag/bq-bo.svg +1 -0
  196. package/DS1/x-flag/bq-sa.svg +1 -0
  197. package/DS1/x-flag/bq-se.svg +1 -0
  198. package/DS1/x-flag/bq.svg +1 -0
  199. package/DS1/x-flag/br.svg +1 -0
  200. package/DS1/x-flag/bs.svg +1 -0
  201. package/DS1/x-flag/bt.svg +1 -0
  202. package/DS1/x-flag/bv.svg +1 -0
  203. package/DS1/x-flag/bw.svg +1 -0
  204. package/DS1/x-flag/by.svg +1 -0
  205. package/DS1/x-flag/bz.svg +1 -0
  206. package/DS1/x-flag/ca.svg +1 -0
  207. package/DS1/x-flag/cc.svg +1 -0
  208. package/DS1/x-flag/cd.svg +1 -0
  209. package/DS1/x-flag/cf.svg +1 -0
  210. package/DS1/x-flag/cg.svg +1 -0
  211. package/DS1/x-flag/ch.svg +1 -0
  212. package/DS1/x-flag/ci.svg +1 -0
  213. package/DS1/x-flag/ck.svg +1 -0
  214. package/DS1/x-flag/cl.svg +1 -0
  215. package/DS1/x-flag/cm.svg +1 -0
  216. package/DS1/x-flag/cn.svg +1 -0
  217. package/DS1/x-flag/co.svg +1 -0
  218. package/DS1/x-flag/cr.svg +1 -0
  219. package/DS1/x-flag/cu.svg +1 -0
  220. package/DS1/x-flag/cv.svg +1 -0
  221. package/DS1/x-flag/cw.svg +1 -0
  222. package/DS1/x-flag/cx.svg +1 -0
  223. package/DS1/x-flag/cy.svg +1 -0
  224. package/DS1/x-flag/cz.svg +1 -0
  225. package/DS1/x-flag/de.svg +1 -0
  226. package/DS1/x-flag/dj.svg +1 -0
  227. package/DS1/x-flag/dk.svg +1 -0
  228. package/DS1/x-flag/dm.svg +1 -0
  229. package/DS1/x-flag/do.svg +1 -0
  230. package/DS1/x-flag/dz.svg +1 -0
  231. package/DS1/x-flag/ec.svg +1 -0
  232. package/DS1/x-flag/ee.svg +1 -0
  233. package/DS1/x-flag/eg.svg +1 -0
  234. package/DS1/x-flag/eh.svg +1 -0
  235. package/DS1/x-flag/er.svg +1 -0
  236. package/DS1/x-flag/es-ct.svg +1 -0
  237. package/DS1/x-flag/es.svg +1 -0
  238. package/DS1/x-flag/et.svg +1 -0
  239. package/DS1/x-flag/eu.svg +1 -0
  240. package/DS1/x-flag/fi.svg +1 -0
  241. package/DS1/x-flag/fj.svg +1 -0
  242. package/DS1/x-flag/fk.svg +1 -0
  243. package/DS1/x-flag/fm.svg +1 -0
  244. package/DS1/x-flag/fo.svg +1 -0
  245. package/DS1/x-flag/fr.svg +1 -0
  246. package/DS1/x-flag/ga.svg +1 -0
  247. package/DS1/x-flag/gb-eng.svg +1 -0
  248. package/DS1/x-flag/gb-nir.svg +1 -0
  249. package/DS1/x-flag/gb-sct.svg +1 -0
  250. package/DS1/x-flag/gb-wls.svg +1 -0
  251. package/DS1/x-flag/gb.svg +1 -0
  252. package/DS1/x-flag/gd.svg +1 -0
  253. package/DS1/x-flag/ge.svg +1 -0
  254. package/DS1/x-flag/gf.svg +1 -0
  255. package/DS1/x-flag/gg.svg +1 -0
  256. package/DS1/x-flag/gh.svg +1 -0
  257. package/DS1/x-flag/gi.svg +1 -0
  258. package/DS1/x-flag/gl.svg +1 -0
  259. package/DS1/x-flag/gm.svg +1 -0
  260. package/DS1/x-flag/gn.svg +1 -0
  261. package/DS1/x-flag/gp.svg +1 -0
  262. package/DS1/x-flag/gq.svg +1 -0
  263. package/DS1/x-flag/gr.svg +1 -0
  264. package/DS1/x-flag/gs.svg +1 -0
  265. package/DS1/x-flag/gt.svg +1 -0
  266. package/DS1/x-flag/gu.svg +1 -0
  267. package/DS1/x-flag/gw.svg +1 -0
  268. package/DS1/x-flag/gy.svg +1 -0
  269. package/DS1/x-flag/hk.svg +1 -0
  270. package/DS1/x-flag/hm.svg +1 -0
  271. package/DS1/x-flag/hn.svg +1 -0
  272. package/DS1/x-flag/hr.svg +1 -0
  273. package/DS1/x-flag/ht.svg +1 -0
  274. package/DS1/x-flag/hu.svg +1 -0
  275. package/DS1/x-flag/ic.svg +1 -0
  276. package/DS1/x-flag/id.svg +1 -0
  277. package/DS1/x-flag/ie.svg +1 -0
  278. package/DS1/x-flag/il.svg +1 -0
  279. package/DS1/x-flag/im.svg +1 -0
  280. package/DS1/x-flag/in.svg +1 -0
  281. package/DS1/x-flag/io.svg +1 -0
  282. package/DS1/x-flag/iq.svg +1 -0
  283. package/DS1/x-flag/ir.svg +1 -0
  284. package/DS1/x-flag/is.svg +1 -0
  285. package/DS1/x-flag/it.svg +1 -0
  286. package/DS1/x-flag/je.svg +1 -0
  287. package/DS1/x-flag/jm.svg +1 -0
  288. package/DS1/x-flag/jo.svg +1 -0
  289. package/DS1/x-flag/jp.svg +1 -0
  290. package/DS1/x-flag/ke.svg +1 -0
  291. package/DS1/x-flag/kg.svg +1 -0
  292. package/DS1/x-flag/kh.svg +1 -0
  293. package/DS1/x-flag/ki.svg +1 -0
  294. package/DS1/x-flag/km.svg +1 -0
  295. package/DS1/x-flag/kn.svg +1 -0
  296. package/DS1/x-flag/kp.svg +1 -0
  297. package/DS1/x-flag/kr.svg +1 -0
  298. package/DS1/x-flag/kw.svg +1 -0
  299. package/DS1/x-flag/ky.svg +1 -0
  300. package/DS1/x-flag/kz.svg +1 -0
  301. package/DS1/x-flag/la.svg +1 -0
  302. package/DS1/x-flag/lb.svg +1 -0
  303. package/DS1/x-flag/lc.svg +1 -0
  304. package/DS1/x-flag/li.svg +1 -0
  305. package/DS1/x-flag/lk.svg +1 -0
  306. package/DS1/x-flag/lr.svg +1 -0
  307. package/DS1/x-flag/ls.svg +1 -0
  308. package/DS1/x-flag/lt.svg +1 -0
  309. package/DS1/x-flag/lu.svg +1 -0
  310. package/DS1/x-flag/lv.svg +1 -0
  311. package/DS1/x-flag/ly.svg +1 -0
  312. package/DS1/x-flag/ma.svg +1 -0
  313. package/DS1/x-flag/mc.svg +1 -0
  314. package/DS1/x-flag/md.svg +1 -0
  315. package/DS1/x-flag/me.svg +1 -0
  316. package/DS1/x-flag/mf.svg +1 -0
  317. package/DS1/x-flag/mg.svg +1 -0
  318. package/DS1/x-flag/mh.svg +1 -0
  319. package/DS1/x-flag/mk.svg +1 -0
  320. package/DS1/x-flag/ml.svg +1 -0
  321. package/DS1/x-flag/mm.svg +1 -0
  322. package/DS1/x-flag/mn.svg +1 -0
  323. package/DS1/x-flag/mo.svg +1 -0
  324. package/DS1/x-flag/mp.svg +1 -0
  325. package/DS1/x-flag/mq.svg +1 -0
  326. package/DS1/x-flag/mr.svg +1 -0
  327. package/DS1/x-flag/ms.svg +1 -0
  328. package/DS1/x-flag/mt.svg +1 -0
  329. package/DS1/x-flag/mu.svg +1 -0
  330. package/DS1/x-flag/mv.svg +1 -0
  331. package/DS1/x-flag/mw.svg +1 -0
  332. package/DS1/x-flag/mx.svg +1 -0
  333. package/DS1/x-flag/my.svg +1 -0
  334. package/DS1/x-flag/mz.svg +1 -0
  335. package/DS1/x-flag/na.svg +1 -0
  336. package/DS1/x-flag/nc.svg +1 -0
  337. package/DS1/x-flag/ne.svg +1 -0
  338. package/DS1/x-flag/nf.svg +1 -0
  339. package/DS1/x-flag/ng.svg +1 -0
  340. package/DS1/x-flag/ni.svg +1 -0
  341. package/DS1/x-flag/nl.svg +1 -0
  342. package/DS1/x-flag/no.svg +1 -0
  343. package/DS1/x-flag/np.svg +1 -0
  344. package/DS1/x-flag/nr.svg +1 -0
  345. package/DS1/x-flag/nu.svg +1 -0
  346. package/DS1/x-flag/nz.svg +1 -0
  347. package/DS1/x-flag/om.svg +1 -0
  348. package/DS1/x-flag/pa.svg +1 -0
  349. package/DS1/x-flag/pe.svg +1 -0
  350. package/DS1/x-flag/pf.svg +1 -0
  351. package/DS1/x-flag/pg.svg +1 -0
  352. package/DS1/x-flag/ph.svg +1 -0
  353. package/DS1/x-flag/pk.svg +1 -0
  354. package/DS1/x-flag/pl.svg +1 -0
  355. package/DS1/x-flag/pm.svg +1 -0
  356. package/DS1/x-flag/pn.svg +1 -0
  357. package/DS1/x-flag/pr.svg +1 -0
  358. package/DS1/x-flag/ps.svg +1 -0
  359. package/DS1/x-flag/pt.svg +1 -0
  360. package/DS1/x-flag/pw.svg +1 -0
  361. package/DS1/x-flag/py.svg +1 -0
  362. package/DS1/x-flag/qa.svg +1 -0
  363. package/DS1/x-flag/re.svg +1 -0
  364. package/DS1/x-flag/ro.svg +1 -0
  365. package/DS1/x-flag/rs.svg +1 -0
  366. package/DS1/x-flag/ru.svg +1 -0
  367. package/DS1/x-flag/rw.svg +1 -0
  368. package/DS1/x-flag/sa.svg +1 -0
  369. package/DS1/x-flag/sb.svg +1 -0
  370. package/DS1/x-flag/sc.svg +1 -0
  371. package/DS1/x-flag/sd.svg +1 -0
  372. package/DS1/x-flag/se.svg +1 -0
  373. package/DS1/x-flag/sg.svg +1 -0
  374. package/DS1/x-flag/sh.svg +1 -0
  375. package/DS1/x-flag/si.svg +1 -0
  376. package/DS1/x-flag/sj.svg +1 -0
  377. package/DS1/x-flag/sk.svg +1 -0
  378. package/DS1/x-flag/sl.svg +1 -0
  379. package/DS1/x-flag/sm.svg +1 -0
  380. package/DS1/x-flag/sn.svg +1 -0
  381. package/DS1/x-flag/so.svg +1 -0
  382. package/DS1/x-flag/sr.svg +1 -0
  383. package/DS1/x-flag/ss.svg +1 -0
  384. package/DS1/x-flag/st.svg +1 -0
  385. package/DS1/x-flag/sv.svg +1 -0
  386. package/DS1/x-flag/sx.svg +1 -0
  387. package/DS1/x-flag/sy.svg +1 -0
  388. package/DS1/x-flag/sz.svg +1 -0
  389. package/DS1/x-flag/ta.svg +1 -0
  390. package/DS1/x-flag/tc.svg +1 -0
  391. package/DS1/x-flag/td.svg +1 -0
  392. package/DS1/x-flag/tf.svg +1 -0
  393. package/DS1/x-flag/tg.svg +1 -0
  394. package/DS1/x-flag/th.svg +1 -0
  395. package/DS1/x-flag/tj.svg +1 -0
  396. package/DS1/x-flag/tk.svg +1 -0
  397. package/DS1/x-flag/tl.svg +1 -0
  398. package/DS1/x-flag/tm.svg +1 -0
  399. package/DS1/x-flag/tn.svg +1 -0
  400. package/DS1/x-flag/to.svg +1 -0
  401. package/DS1/x-flag/tr.svg +1 -0
  402. package/DS1/x-flag/tt.svg +1 -0
  403. package/DS1/x-flag/tv.svg +1 -0
  404. package/DS1/x-flag/tw.svg +1 -0
  405. package/DS1/x-flag/tz.svg +1 -0
  406. package/DS1/x-flag/ua.svg +1 -0
  407. package/DS1/x-flag/ug.svg +1 -0
  408. package/DS1/x-flag/um.svg +1 -0
  409. package/DS1/x-flag/us.svg +1 -0
  410. package/DS1/x-flag/uy.svg +1 -0
  411. package/DS1/x-flag/uz.svg +1 -0
  412. package/DS1/x-flag/va.svg +1 -0
  413. package/DS1/x-flag/vc.svg +1 -0
  414. package/DS1/x-flag/ve.svg +1 -0
  415. package/DS1/x-flag/vg.svg +1 -0
  416. package/DS1/x-flag/vi.svg +1 -0
  417. package/DS1/x-flag/vn.svg +1 -0
  418. package/DS1/x-flag/vu.svg +1 -0
  419. package/DS1/x-flag/wf.svg +1 -0
  420. package/DS1/x-flag/ws.svg +1 -0
  421. package/DS1/x-flag/xk.svg +1 -0
  422. package/DS1/x-flag/ye.svg +1 -0
  423. package/DS1/x-flag/yt.svg +1 -0
  424. package/DS1/x-flag/za.svg +1 -0
  425. package/DS1/x-flag/zm.svg +1 -0
  426. package/DS1/x-flag/zw.svg +1 -0
  427. package/DS1/x-icon/android.svg +9 -0
  428. package/DS1/x-icon/arrange-check.svg +1 -1
  429. package/DS1/x-icon/arrange-page.svg +1 -1
  430. package/DS1/x-icon/chrome.svg +7 -0
  431. package/DS1/x-icon/edge-brand.svg +6 -0
  432. package/DS1/x-icon/firefox.svg +4 -0
  433. package/DS1/x-icon/health.svg +3 -0
  434. package/DS1/x-icon/left.svg +2 -3
  435. package/DS1/x-icon/linux.svg +1 -0
  436. package/DS1/x-icon/material.svg +1 -0
  437. package/DS1/x-icon/milestone-planned.svg +3 -0
  438. package/DS1/x-icon/milestone.svg +3 -0
  439. package/DS1/x-icon/more.svg +1 -5
  440. package/DS1/x-icon/network.svg +3 -0
  441. package/DS1/x-icon/opera.svg +4 -0
  442. package/DS1/x-icon/prediction.svg +3 -0
  443. package/DS1/x-icon/priority-high.svg +3 -0
  444. package/DS1/x-icon/priority-low.svg +3 -0
  445. package/DS1/x-icon/priority-medium.svg +3 -0
  446. package/DS1/x-icon/project.svg +3 -0
  447. package/DS1/x-icon/redo.svg +2 -2
  448. package/DS1/x-icon/repeat-small.svg +3 -0
  449. package/DS1/x-icon/safari.svg +4 -0
  450. package/DS1/x-icon/scaling.svg +3 -0
  451. package/DS1/x-icon/tabs.svg +4 -0
  452. package/DS1/x-icon/windows.svg +5 -0
  453. package/README.md +3 -3
  454. package/dist/0-face/button-label.d.ts +5 -0
  455. package/dist/0-face/button-label.d.ts.map +1 -0
  456. package/dist/0-face/button-label.js +31 -0
  457. package/dist/0-face/calendar.d.ts +1 -1
  458. package/dist/0-face/calendar.d.ts.map +1 -1
  459. package/dist/0-face/calendar.js +6 -3
  460. package/dist/0-face/carousel.d.ts +9 -0
  461. package/dist/0-face/carousel.d.ts.map +1 -1
  462. package/dist/0-face/carousel.js +80 -0
  463. package/dist/0-face/constraint-panel.d.ts +43 -0
  464. package/dist/0-face/constraint-panel.d.ts.map +1 -0
  465. package/dist/0-face/constraint-panel.js +451 -0
  466. package/dist/0-face/constraint-site.d.ts +73 -0
  467. package/dist/0-face/constraint-site.d.ts.map +1 -0
  468. package/dist/0-face/constraint-site.js +186 -0
  469. package/dist/0-face/constraints.d.ts +47 -0
  470. package/dist/0-face/constraints.d.ts.map +1 -0
  471. package/dist/0-face/constraints.js +274 -0
  472. package/dist/0-face/copy-text.js +1 -1
  473. package/dist/0-face/cut-fade.d.ts +112 -0
  474. package/dist/0-face/cut-fade.d.ts.map +1 -0
  475. package/dist/0-face/cut-fade.js +274 -0
  476. package/dist/0-face/define.d.ts.map +1 -1
  477. package/dist/0-face/define.js +24 -3
  478. package/dist/0-face/face-correction.d.ts +51 -0
  479. package/dist/0-face/face-correction.d.ts.map +1 -0
  480. package/dist/0-face/face-correction.js +80 -0
  481. package/dist/0-face/failures.d.ts +16 -0
  482. package/dist/0-face/failures.d.ts.map +1 -0
  483. package/dist/0-face/failures.js +21 -0
  484. package/dist/0-face/fault-lines.d.ts +20 -0
  485. package/dist/0-face/fault-lines.d.ts.map +1 -0
  486. package/dist/0-face/fault-lines.js +172 -0
  487. package/dist/0-face/feedback-overlays.d.ts.map +1 -1
  488. package/dist/0-face/feedback-overlays.js +5 -3
  489. package/dist/0-face/feedback.d.ts +2 -0
  490. package/dist/0-face/feedback.d.ts.map +1 -1
  491. package/dist/0-face/feedback.js +1 -0
  492. package/dist/0-face/focus.d.ts +71 -0
  493. package/dist/0-face/focus.d.ts.map +1 -0
  494. package/dist/0-face/focus.js +196 -0
  495. package/dist/0-face/grid.d.ts +11 -1
  496. package/dist/0-face/grid.d.ts.map +1 -1
  497. package/dist/0-face/grid.js +90 -4
  498. package/dist/0-face/i18n.d.ts.map +1 -1
  499. package/dist/0-face/i18n.js +38 -16
  500. package/dist/0-face/layout-inspector.d.ts +5 -1
  501. package/dist/0-face/layout-inspector.d.ts.map +1 -1
  502. package/dist/0-face/layout-inspector.js +130 -104
  503. package/dist/0-face/preference-options.d.ts +4 -0
  504. package/dist/0-face/preference-options.d.ts.map +1 -1
  505. package/dist/0-face/scaling.d.ts +8 -1
  506. package/dist/0-face/scaling.d.ts.map +1 -1
  507. package/dist/0-face/scaling.js +19 -2
  508. package/dist/0-face/shape.d.ts +35 -0
  509. package/dist/0-face/shape.d.ts.map +1 -0
  510. package/dist/0-face/shape.js +23 -0
  511. package/dist/0-face/text-contrast.d.ts +22 -0
  512. package/dist/0-face/text-contrast.d.ts.map +1 -0
  513. package/dist/0-face/text-contrast.js +178 -0
  514. package/dist/0-face/theme-bootstrap.js +56 -0
  515. package/dist/0-face/toast-queue.d.ts +4 -0
  516. package/dist/0-face/toast-queue.d.ts.map +1 -1
  517. package/dist/0-face/toast-queue.js +4 -1
  518. package/dist/0-face/translations/da.json +10 -1
  519. package/dist/0-face/translations/de.json +10 -1
  520. package/dist/0-face/translations/en.json +10 -1
  521. package/dist/0-face/translations/es.json +10 -1
  522. package/dist/0-face/translations/fi.json +10 -1
  523. package/dist/0-face/translations/fr.json +10 -1
  524. package/dist/0-face/translations/is.json +10 -1
  525. package/dist/0-face/translations/it.json +10 -1
  526. package/dist/0-face/translations/ja.json +10 -1
  527. package/dist/0-face/translations/ko.json +10 -1
  528. package/dist/0-face/translations/nb.json +10 -1
  529. package/dist/0-face/translations/pt-BR.json +10 -1
  530. package/dist/0-face/translations/pt.json +10 -1
  531. package/dist/0-face/translations/sv.json +10 -1
  532. package/dist/0-face/translations/zh.json +10 -1
  533. package/dist/0-face/word-wrap.d.ts +6 -0
  534. package/dist/0-face/word-wrap.d.ts.map +1 -0
  535. package/dist/0-face/word-wrap.js +119 -0
  536. package/dist/1-root/foundation.d.ts +12 -0
  537. package/dist/1-root/foundation.d.ts.map +1 -0
  538. package/dist/1-root/foundation.js +59 -0
  539. package/dist/2-core/button-split.d.ts +1 -0
  540. package/dist/2-core/button-split.d.ts.map +1 -1
  541. package/dist/2-core/button-split.js +9 -4
  542. package/dist/2-core/chart/grid-chart.d.ts +2 -0
  543. package/dist/2-core/chart/grid-chart.d.ts.map +1 -1
  544. package/dist/2-core/chart/grid-chart.js +2 -1
  545. package/dist/2-core/ds-activity.d.ts +25 -0
  546. package/dist/2-core/ds-activity.d.ts.map +1 -0
  547. package/dist/2-core/ds-activity.js +28 -0
  548. package/dist/2-core/ds-app-chrome.d.ts +2 -0
  549. package/dist/2-core/ds-app-chrome.d.ts.map +1 -0
  550. package/dist/2-core/ds-app-chrome.js +1 -0
  551. package/dist/2-core/ds-avatar.d.ts +12 -0
  552. package/dist/2-core/ds-avatar.d.ts.map +1 -1
  553. package/dist/2-core/ds-avatar.js +86 -7
  554. package/dist/2-core/ds-badge.d.ts +7 -1
  555. package/dist/2-core/ds-badge.d.ts.map +1 -1
  556. package/dist/2-core/ds-badge.js +8 -1
  557. package/dist/2-core/ds-button.d.ts +12 -0
  558. package/dist/2-core/ds-button.d.ts.map +1 -1
  559. package/dist/2-core/ds-button.js +4 -0
  560. package/dist/2-core/ds-chart.d.ts +28 -3
  561. package/dist/2-core/ds-chart.d.ts.map +1 -1
  562. package/dist/2-core/ds-chart.js +110 -130
  563. package/dist/2-core/ds-cycle.d.ts +2 -2
  564. package/dist/2-core/ds-cycle.d.ts.map +1 -1
  565. package/dist/2-core/ds-cycle.js +36 -171
  566. package/dist/2-core/ds-device-bezel.d.ts +2 -0
  567. package/dist/2-core/ds-device-bezel.d.ts.map +1 -0
  568. package/dist/2-core/ds-device-bezel.js +1 -0
  569. package/dist/2-core/ds-empty.d.ts +2 -2
  570. package/dist/2-core/ds-empty.d.ts.map +1 -1
  571. package/dist/2-core/ds-empty.js +6 -4
  572. package/dist/2-core/ds-input.d.ts +7 -0
  573. package/dist/2-core/ds-input.d.ts.map +1 -1
  574. package/dist/2-core/ds-input.js +23 -3
  575. package/dist/2-core/ds-message.d.ts +11 -0
  576. package/dist/2-core/ds-message.d.ts.map +1 -1
  577. package/dist/2-core/ds-message.js +18 -0
  578. package/dist/2-core/ds-number.d.ts +86 -0
  579. package/dist/2-core/ds-number.d.ts.map +1 -0
  580. package/dist/2-core/ds-number.js +326 -0
  581. package/dist/2-core/ds-progress.d.ts +3 -0
  582. package/dist/2-core/ds-progress.d.ts.map +1 -1
  583. package/dist/2-core/ds-progress.js +3 -0
  584. package/dist/2-core/ds-radio.d.ts +3 -0
  585. package/dist/2-core/ds-radio.d.ts.map +1 -1
  586. package/dist/2-core/ds-radio.js +10 -1
  587. package/dist/2-core/ds-stat.d.ts +3 -0
  588. package/dist/2-core/ds-stat.d.ts.map +1 -1
  589. package/dist/2-core/ds-stat.js +3 -0
  590. package/dist/2-core/ds-switch.d.ts +14 -1
  591. package/dist/2-core/ds-switch.d.ts.map +1 -1
  592. package/dist/2-core/ds-switch.js +3 -1
  593. package/dist/2-core/ds-tag.d.ts +8 -1
  594. package/dist/2-core/ds-tag.d.ts.map +1 -1
  595. package/dist/2-core/ds-tag.js +12 -2
  596. package/dist/2-core/ds-text.d.ts +7 -0
  597. package/dist/2-core/ds-text.d.ts.map +1 -1
  598. package/dist/2-core/ds-text.js +7 -0
  599. package/dist/2-core/ds-token.d.ts +3 -0
  600. package/dist/2-core/ds-token.d.ts.map +1 -1
  601. package/dist/2-core/ds-token.js +3 -0
  602. package/dist/2-core/ds-tooltip.d.ts.map +1 -1
  603. package/dist/2-core/ds-tooltip.js +23 -2
  604. package/dist/2-core/ds-window.d.ts +2 -0
  605. package/dist/2-core/ds-window.d.ts.map +1 -0
  606. package/dist/2-core/ds-window.js +1 -0
  607. package/dist/2-core/generated/ds-icon-map.d.ts +27 -6
  608. package/dist/2-core/generated/ds-icon-map.d.ts.map +1 -1
  609. package/dist/2-core/generated/ds-icon-map.js +47 -5
  610. package/dist/2-core/generated/icons-extra.d.ts.map +1 -1
  611. package/dist/2-core/generated/icons-extra.js +24 -3
  612. package/dist/2-core/generated/icons-immediate.d.ts +1 -1
  613. package/dist/2-core/generated/icons-immediate.d.ts.map +1 -1
  614. package/dist/2-core/generated/icons-immediate.js +3 -3
  615. package/dist/2-core/number-expression.d.ts +12 -0
  616. package/dist/2-core/number-expression.d.ts.map +1 -0
  617. package/dist/2-core/number-expression.js +82 -0
  618. package/dist/3-unit/calendar-base.d.ts +5 -0
  619. package/dist/3-unit/calendar-base.d.ts.map +1 -1
  620. package/dist/3-unit/calendar-base.js +3 -2
  621. package/dist/3-unit/context-trigger.d.ts.map +1 -1
  622. package/dist/3-unit/context-trigger.js +32 -2
  623. package/dist/3-unit/ds-calendar.d.ts +197 -4
  624. package/dist/3-unit/ds-calendar.d.ts.map +1 -1
  625. package/dist/3-unit/ds-calendar.js +687 -45
  626. package/dist/3-unit/ds-carousel.d.ts +3 -0
  627. package/dist/3-unit/ds-carousel.d.ts.map +1 -1
  628. package/dist/3-unit/ds-carousel.js +13 -1
  629. package/dist/3-unit/ds-context.d.ts +18 -1
  630. package/dist/3-unit/ds-context.d.ts.map +1 -1
  631. package/dist/3-unit/ds-context.js +37 -1
  632. package/dist/3-unit/ds-form.d.ts +9 -0
  633. package/dist/3-unit/ds-form.d.ts.map +1 -1
  634. package/dist/3-unit/ds-form.js +52 -11
  635. package/dist/3-unit/ds-list.d.ts +20 -1
  636. package/dist/3-unit/ds-list.d.ts.map +1 -1
  637. package/dist/3-unit/ds-list.js +31 -3
  638. package/dist/3-unit/ds-matrix.d.ts +3 -0
  639. package/dist/3-unit/ds-matrix.d.ts.map +1 -1
  640. package/dist/3-unit/ds-matrix.js +3 -0
  641. package/dist/3-unit/ds-menu.d.ts.map +1 -1
  642. package/dist/3-unit/ds-menu.js +17 -1
  643. package/dist/3-unit/ds-row.d.ts +13 -0
  644. package/dist/3-unit/ds-row.d.ts.map +1 -1
  645. package/dist/3-unit/ds-row.js +15 -2
  646. package/dist/3-unit/ds-select.js +1 -1
  647. package/dist/3-unit/ds-sidebar.d.ts +17 -0
  648. package/dist/3-unit/ds-sidebar.d.ts.map +1 -1
  649. package/dist/3-unit/ds-sidebar.js +14 -3
  650. package/dist/3-unit/ds-table-of-contents.d.ts +68 -0
  651. package/dist/3-unit/ds-table-of-contents.d.ts.map +1 -0
  652. package/dist/3-unit/ds-table-of-contents.js +190 -0
  653. package/dist/3-unit/ds-table.d.ts.map +1 -1
  654. package/dist/3-unit/ds-table.js +2 -1
  655. package/dist/3-unit/ds-tabs.d.ts +32 -1
  656. package/dist/3-unit/ds-tabs.d.ts.map +1 -1
  657. package/dist/3-unit/ds-tabs.js +39 -1
  658. package/dist/4-page/ds-container.d.ts.map +1 -1
  659. package/dist/4-page/ds-container.js +2 -1
  660. package/dist/4-page/ds-document.d.ts +3 -0
  661. package/dist/4-page/ds-document.d.ts.map +1 -1
  662. package/dist/4-page/ds-document.js +3 -0
  663. package/dist/4-page/ds-footer.d.ts +47 -7
  664. package/dist/4-page/ds-footer.d.ts.map +1 -1
  665. package/dist/4-page/ds-footer.js +58 -14
  666. package/dist/4-page/ds-header.d.ts +6 -0
  667. package/dist/4-page/ds-header.d.ts.map +1 -1
  668. package/dist/4-page/ds-header.js +4 -1
  669. package/dist/4-page/ds-overlay.d.ts +2 -2
  670. package/dist/4-page/ds-overlay.d.ts.map +1 -1
  671. package/dist/4-page/ds-overlay.js +8 -3
  672. package/dist/4-page/ds-page.d.ts +12 -0
  673. package/dist/4-page/ds-page.d.ts.map +1 -1
  674. package/dist/4-page/ds-page.js +19 -1
  675. package/dist/4-page/email.d.ts +2 -0
  676. package/dist/4-page/email.d.ts.map +1 -1
  677. package/dist/4-page/email.js +5 -4
  678. package/dist/5-visual-kit/app-chrome.d.ts +98 -0
  679. package/dist/5-visual-kit/app-chrome.d.ts.map +1 -0
  680. package/dist/5-visual-kit/app-chrome.js +119 -0
  681. package/dist/5-visual-kit/bezels.d.ts +30 -0
  682. package/dist/5-visual-kit/bezels.d.ts.map +1 -0
  683. package/dist/5-visual-kit/bezels.js +388 -0
  684. package/dist/5-visual-kit/browser-icons.d.ts +5 -0
  685. package/dist/5-visual-kit/browser-icons.d.ts.map +1 -0
  686. package/dist/5-visual-kit/browser-icons.js +51 -0
  687. package/dist/5-visual-kit/browser-styles.d.ts +3 -0
  688. package/dist/5-visual-kit/browser-styles.d.ts.map +1 -0
  689. package/dist/5-visual-kit/browser-styles.js +52 -0
  690. package/dist/5-visual-kit/device-bezel.d.ts +84 -0
  691. package/dist/5-visual-kit/device-bezel.d.ts.map +1 -0
  692. package/dist/5-visual-kit/device-bezel.js +56 -0
  693. package/dist/5-visual-kit/instagram-frame.d.ts +8 -0
  694. package/dist/5-visual-kit/instagram-frame.d.ts.map +1 -0
  695. package/dist/5-visual-kit/instagram-frame.js +13 -0
  696. package/dist/5-visual-kit/instagram.d.ts +18 -0
  697. package/dist/5-visual-kit/instagram.d.ts.map +1 -0
  698. package/dist/5-visual-kit/instagram.js +39 -0
  699. package/dist/5-visual-kit/mobile-chrome.d.ts +4 -0
  700. package/dist/5-visual-kit/mobile-chrome.d.ts.map +1 -0
  701. package/dist/5-visual-kit/mobile-chrome.js +24 -0
  702. package/dist/5-visual-kit/native-icon-paths.d.ts +146 -0
  703. package/dist/5-visual-kit/native-icon-paths.d.ts.map +1 -0
  704. package/dist/5-visual-kit/native-icon-paths.js +145 -0
  705. package/dist/5-visual-kit/window.d.ts +51 -0
  706. package/dist/5-visual-kit/window.d.ts.map +1 -0
  707. package/dist/5-visual-kit/window.js +20 -0
  708. package/dist/browser-icons-BFbS1tIx.js +56 -0
  709. package/dist/browser-icons-BFbS1tIx.js.map +1 -0
  710. package/dist/browser-icons-CT8qU77Z.js +48 -0
  711. package/dist/browser-icons-CT8qU77Z.js.map +1 -0
  712. package/dist/components.d.ts +1 -0
  713. package/dist/components.d.ts.map +1 -1
  714. package/dist/components.js +1 -0
  715. package/dist/design-system-1.bundle.js +5874 -2097
  716. package/dist/design-system-1.bundle.js.map +1 -1
  717. package/dist/design-system-1.bundle.min.js +7332 -4682
  718. package/dist/design-system-1.bundle.min.js.map +1 -1
  719. package/dist/design-system-1.css +1 -1
  720. package/dist/feedback.js +197 -167
  721. package/dist/feedback.js.map +1 -1
  722. package/dist/{icons-extra-CRxxWFjX.js → icons-extra-BMPvmQPI.js} +25 -4
  723. package/dist/icons-extra-BMPvmQPI.js.map +1 -0
  724. package/dist/{icons-extra-H5pqCM_R.js → icons-extra-BfYOw-cR.js} +83 -5
  725. package/dist/icons-extra-BfYOw-cR.js.map +1 -0
  726. package/dist/index.d.ts +12 -1
  727. package/dist/index.d.ts.map +1 -1
  728. package/dist/index.js +11 -1
  729. package/dist/instagram-CKofs55A.js +50 -0
  730. package/dist/instagram-CKofs55A.js.map +1 -0
  731. package/dist/instagram-CcYf5oiM.js +48 -0
  732. package/dist/instagram-CcYf5oiM.js.map +1 -0
  733. package/dist/lit-Ce_uWYM4.js +612 -0
  734. package/dist/lit-Ce_uWYM4.js.map +1 -0
  735. package/dist/lit-DGUVm1Ce.js +557 -0
  736. package/dist/lit-DGUVm1Ce.js.map +1 -0
  737. package/dist/native-icon-paths-CB9evXBM.js +93 -0
  738. package/dist/native-icon-paths-CB9evXBM.js.map +1 -0
  739. package/dist/native-icon-paths-zay-3g_n.js +150 -0
  740. package/dist/native-icon-paths-zay-3g_n.js.map +1 -0
  741. package/dist/react/avatar.d.ts +1 -1
  742. package/dist/react/choice.d.ts +4 -0
  743. package/dist/react/choice.d.ts.map +1 -1
  744. package/dist/react/choice.js +2 -2
  745. package/dist/react/context.d.ts +19 -4
  746. package/dist/react/context.d.ts.map +1 -1
  747. package/dist/react/context.js +4 -4
  748. package/dist/react/empty.d.ts +2 -2
  749. package/dist/react/empty.d.ts.map +1 -1
  750. package/dist/react/empty.js +1 -1
  751. package/dist/react/footer.d.ts +5 -5
  752. package/dist/react/footer.d.ts.map +1 -1
  753. package/dist/react/footer.js +2 -2
  754. package/dist/react/header.d.ts +2 -2
  755. package/dist/react/header.d.ts.map +1 -1
  756. package/dist/react/message.d.ts +4 -0
  757. package/dist/react/message.d.ts.map +1 -1
  758. package/dist/react/message.js +2 -2
  759. package/dist/react/number.d.ts +53 -0
  760. package/dist/react/number.d.ts.map +1 -0
  761. package/dist/react/number.js +25 -0
  762. package/dist/react/page.d.ts +1 -1
  763. package/dist/react/sidebar.d.ts +4 -0
  764. package/dist/react/sidebar.d.ts.map +1 -1
  765. package/dist/react/sidebar.js +2 -2
  766. package/dist/react/table-of-contents.d.ts +19 -0
  767. package/dist/react/table-of-contents.d.ts.map +1 -0
  768. package/dist/react/table-of-contents.js +28 -0
  769. package/dist/{shared-words-CdMDVtXx.js → shared-words-C5cjxMjZ.js} +151 -16
  770. package/dist/shared-words-C5cjxMjZ.js.map +1 -0
  771. package/dist/{shared-words-BtRee8xR.js → shared-words-Cdm7xd-_.js} +163 -28
  772. package/dist/shared-words-Cdm7xd-_.js.map +1 -0
  773. package/package.json +25 -12
  774. package/DS1/3-unit/ds-calendar-large.ts +0 -353
  775. package/DS1/3-unit/styles/ds-calendar-large.css +0 -178
  776. package/dist/3-unit/ds-calendar-large.d.ts +0 -142
  777. package/dist/3-unit/ds-calendar-large.d.ts.map +0 -1
  778. package/dist/3-unit/ds-calendar-large.js +0 -308
  779. package/dist/icons-extra-CRxxWFjX.js.map +0 -1
  780. package/dist/icons-extra-H5pqCM_R.js.map +0 -1
  781. package/dist/shared-words-BtRee8xR.js.map +0 -1
  782. package/dist/shared-words-CdMDVtXx.js.map +0 -1
@@ -1,7 +1,17 @@
1
1
  // ds-calendar.ts
2
- // A month on whole squares: seven days across, a week to a row. By default a
2
+ // A month on whole squares: seven days across, a week to a row. `view` shows
3
+ // one week instead (every event of each day, nothing folded behind "+N") or one
4
+ // day (its events without a time across the top, then its hours, one square
5
+ // each, with the timed events at their hour) or a swimlane (weeks across, a
6
+ // row to an event, each event one bar from its first week to its last);
7
+ // `views` puts Day, Week, Month and Swimlane in the header to change between
8
+ // them. An event over several days is one bar
9
+ // with its name written once, and words that do not fit fade out at the end.
10
+ // By default a
3
11
  // day is four squares wide and four high (its date on the first square, two
4
- // lines of events, one square to spare), drawn in hairline boxes. `compact`
12
+ // lines of events, one square to spare), drawn in hairline boxes with a frame
13
+ // rounded more than a card's; the first week names its days inside its boxes,
14
+ // and a step back, Today and a step on are one plain split. `compact`
5
15
  // makes a day one square: the small month a year is drawn from. `picker`
6
16
  // makes the calendar a field that opens that small month below it, with the
7
17
  // first and last day written out where they can be typed, a switch for a
@@ -14,11 +24,15 @@
14
24
 
15
25
  import { html, nothing, unsafeCSS, type PropertyValues } from "lit";
16
26
  import { define } from "../0-face/define";
27
+ import { CutFades } from "../0-face/cut-fade";
17
28
  import { getText } from "../0-face/i18n";
18
29
  import { dateFormatter, type DateLength } from "../0-face/format";
19
30
  import {
31
+ addDays,
20
32
  addMonths,
33
+ compareDays,
21
34
  dateNumber,
35
+ dayLabel,
22
36
  dayOf,
23
37
  eventsByDay,
24
38
  heatLevels,
@@ -30,21 +44,148 @@ import {
30
44
  sameMonth,
31
45
  startOfMonth,
32
46
  weekdayNames,
47
+ weekdayOf,
33
48
  type CalendarEvent,
34
49
  type Day,
35
50
  type HeatLevel,
36
51
  } from "../0-face/calendar";
37
52
  import { CalendarBase, readMonth, readRange, type CalendarChangeDetail } from "./calendar-base";
38
53
  import "../2-core/ds-icon";
54
+ import "../2-core/ds-button";
39
55
  import metrics from "../1-root/component-metrics.css?inline";
40
56
  import controls from "../1-root/controls.css?inline";
41
57
  import styles from "./styles/ds-calendar.css?inline";
42
58
 
43
59
  export * from "./calendar-base";
44
60
 
61
+ /** An activity day's fill: one colour, or bands side by side when several share it. */
62
+ function activityFill(events: readonly CalendarEvent[]): string | undefined {
63
+ if (!events.length) return undefined;
64
+ const colours = [...new Set(events.map(event => event.color || "var(--ds-calendar-event-fill, var(--ds-apple-green))"))];
65
+ if (colours.length === 1) return colours[0];
66
+ const share = 100 / colours.length;
67
+ return `linear-gradient(90deg, ${colours.map((colour, index) => `${colour} ${index * share}% ${(index + 1) * share}%`).join(", ")})`;
68
+ }
69
+
45
70
  const whole = (value: number | undefined, least: number, most: number, fallback: number) =>
46
71
  typeof value === "number" && Number.isFinite(value) ? Math.max(least, Math.min(most, Math.floor(value))) : fallback;
47
72
 
73
+ /**
74
+ * A day's lines of events in a full month: the event that starts a bar on a
75
+ * line (and how many days the bar runs), `"on"` where a bar from an earlier
76
+ * day passes over the line, or null where the line is empty.
77
+ */
78
+ /** What a full calendar shows: a month, a week, a day, or the events as a swimlane over weeks. */
79
+ export type CalendarView = "month" | "week" | "day" | "swimlane";
80
+
81
+ /** The views in the header, the shortest first, with their shared words. */
82
+ const VIEWS: readonly (readonly [CalendarView, string])[] = [["day", "Day"], ["week", "Week"], ["month", "Month"], ["swimlane", "Swimlane"]];
83
+
84
+ const isView = (value: unknown): value is CalendarView => VIEWS.some(([view]) => view === value);
85
+
86
+ /** `views` as an attribute: present and empty for every view the calendar draws, or the views to offer, in order. */
87
+ const viewsConverter = {
88
+ fromAttribute: (value: string | null): boolean | string[] => {
89
+ if (value === null || value === "false") return false;
90
+ const list = value.split(/[\s,]+/).filter(Boolean);
91
+ return list.length === 0 || value === "true" ? true : list;
92
+ },
93
+ toAttribute: (value: boolean | string[]) => (Array.isArray(value) ? value.join(" ") : value ? "" : null),
94
+ };
95
+
96
+ /** One event's bar in a swimlane: its row, and the first and last week (counted from 0) it covers in view. */
97
+ export interface SwimlaneBar {
98
+ event: CalendarEvent;
99
+ row: number;
100
+ from: number;
101
+ to: number;
102
+ }
103
+
104
+ /**
105
+ * Lays events out as a swimlane over `weeks` (each the first day of a week
106
+ * of seven): one row each, in the order `eventsByDay` lists them (by first
107
+ * day, the longer first), each a bar from the week holding its first day to
108
+ * the week holding its last, held inside the weeks drawn. Events wholly
109
+ * outside them are left out.
110
+ */
111
+ export function swimlaneBars(events: readonly CalendarEvent[], weeks: readonly Day[]): SwimlaneBar[] {
112
+ if (!weeks.length) return [];
113
+ const first = weeks[0], last = addDays(weeks.at(-1)!, 6);
114
+ const seen = new Set<CalendarEvent>();
115
+ const ordered: CalendarEvent[] = [];
116
+ for (const list of eventsByDay(events, first, last).values()) for (const event of list) if (!seen.has(event)) { seen.add(event); ordered.push(event); }
117
+ ordered.sort((a, b) => compareDays(a.start, b.start) || compareDays(endOf(b), endOf(a)));
118
+ const weekOf = (day: Day) => Math.max(0, Math.min(weeks.length - 1, Math.floor(daysBetween(first, day) / 7)));
119
+ return ordered.map((event, row) => ({ event, row, from: weekOf(event.start < first ? first : event.start), to: weekOf(endOf(event) > last ? last : endOf(event)) }));
120
+ }
121
+
122
+ /** An event's last day: its end, or its start for one day. */
123
+ const endOf = (event: CalendarEvent): Day => (event.end && isDay(event.end) && event.end > event.start ? event.end : event.start);
124
+
125
+ /** Whole days from `from` to `to`. */
126
+ const daysBetween = (from: Day, to: Day) => Math.round((Date.UTC(+to.slice(0, 4), +to.slice(5, 7) - 1, +to.slice(8, 10)) - Date.UTC(+from.slice(0, 4), +from.slice(5, 7) - 1, +from.slice(8, 10))) / 864e5);
127
+
128
+ /** Detail of `view-change`. */
129
+ export interface CalendarViewDetail { view: CalendarView }
130
+
131
+ /** What a full month's day writes before its date: its weekday's name (the first week), and its week's number. */
132
+ type DayLabel = { weekday?: string; today?: boolean; week?: number };
133
+
134
+ export type CalendarLine = { event: CalendarEvent; span: number } | "on" | null;
135
+
136
+ /**
137
+ * Lays one week's events on lines, so an event over several days keeps its
138
+ * line and is one bar with its name written once: each event takes the
139
+ * lowest line free on all its days in the week, longest first as `byDay`
140
+ * lists them. A day whose events need more lines than `lines` keeps the last
141
+ * one for "+N", and a bar breaks there and goes on after it; `shown` says
142
+ * which days are drawn at all (a bar stops at a day that is not).
143
+ */
144
+ export function weekLines(
145
+ week: readonly Day[],
146
+ byDay: ReadonlyMap<Day, readonly CalendarEvent[]>,
147
+ lines: number,
148
+ shown: (day: Day) => boolean = () => true,
149
+ ): { lines: CalendarLine[]; hidden: number }[] {
150
+ const lineOf = new Map<CalendarEvent, number>();
151
+ const taken = week.map(() => new Set<number>());
152
+ week.forEach((day, column) => {
153
+ for (const event of byDay.get(day) ?? []) {
154
+ if (lineOf.has(event)) continue;
155
+ const columns: number[] = [];
156
+ for (let next = column; next < week.length && (byDay.get(week[next]) ?? []).includes(event); next++) columns.push(next);
157
+ let line = 0;
158
+ while (columns.some(next => taken[next].has(line))) line++;
159
+ lineOf.set(event, line);
160
+ for (const next of columns) taken[next].add(line);
161
+ }
162
+ });
163
+ // How many lines each day draws: all of them, or one fewer for "+N".
164
+ const room = week.map(day => {
165
+ if (!shown(day)) return 0;
166
+ const events = byDay.get(day) ?? [];
167
+ const deepest = Math.max(-1, ...events.map(event => lineOf.get(event)!));
168
+ return deepest < lines ? lines : Math.max(0, lines - 1);
169
+ });
170
+ return week.map((day, column) => {
171
+ const events = byDay.get(day) ?? [];
172
+ const drawn: CalendarLine[] = [];
173
+ for (let line = 0; line < room[column]; line++) {
174
+ const event = events.find(candidate => lineOf.get(candidate) === line);
175
+ if (!event) { drawn.push(null); continue; }
176
+ const before = column > 0 && line < room[column - 1] && (byDay.get(week[column - 1]) ?? []).includes(event);
177
+ if (before) { drawn.push("on"); continue; }
178
+ let span = 1;
179
+ while (column + span < week.length && line < room[column + span] && (byDay.get(week[column + span]) ?? []).includes(event)) span++;
180
+ drawn.push({ event, span });
181
+ }
182
+ // Drop the empty lines at the foot, so a quiet day draws nothing under its date.
183
+ while (drawn.length && drawn.at(-1) === null) drawn.pop();
184
+ const hidden = room[column] < lines ? events.filter(event => lineOf.get(event)! >= room[column]).length : 0;
185
+ return { lines: drawn, hidden };
186
+ });
187
+ }
188
+
48
189
  /** One end of a picker's value: its day and, when it has one, its time (`14:30`). */
49
190
  export interface CalendarEnd {
50
191
  day: Day;
@@ -102,12 +243,38 @@ const openPickers = new Set<Calendar>();
102
243
  * small month.
103
244
  * @prop {number} dayWidth - Squares per day (`day-width`): 4 by default, 1
104
245
  * when compact.
246
+ * @prop {string} view - `month` (the default), `week`, `day` or `swimlane`:
247
+ * the weeks from the month shown across (a week half a day wide, so it is
248
+ * as wide as the month), each event one row with one bar from its first
249
+ * week to its last. A compact calendar and a picker are always a month.
250
+ * @prop {boolean | string[]} views - Day, Week, Month and Swimlane in the
251
+ * header, to change `view`; or the views to offer, in order
252
+ * (`views="month swimlane"`). A name the calendar does not draw is the
253
+ * page's own view: chosen, the calendar keeps its header (the month's title,
254
+ * the arrows moving a month) and shows what the page puts in its slot of
255
+ * that name (`<div slot="earnings">`) in place of the days.
256
+ * @prop {Record<string, string>} viewNames - The words for each view in the
257
+ * switch (property only), over the shared Day, Week, Month and Swimlane;
258
+ * a page's own view is named by its name when left out.
259
+ * @prop {string} date - The day the week or day view shows, `YYYY-MM-DD`;
260
+ * today, or the first of the month shown, by default.
105
261
  * @prop {number} lines - Lines of events under a day's date: 2 by default.
106
262
  * @prop {boolean} weekNumbers - Write the week's number (`week-numbers`) on
107
263
  * its first day.
108
- * @prop {boolean} fixed - Always draw six weeks, so the month keeps its height.
264
+ * @prop {boolean} fixed - Always draw six weeks, so the month keeps its height,
265
+ * and every other view stands in that same height (the weekdays and six
266
+ * weeks): the week's days grow to it, the day's hours fill it, the
267
+ * swimlane's rows fill it and scroll beyond it, and a page's own view gets
268
+ * it, so nothing under the calendar moves when the view changes.
109
269
  * @prop {boolean} outsideDays - Draw the days of the months before and after
110
270
  * in the title grey (`outside-days`); pressing one moves there.
271
+ * @prop {boolean} activity - The days as quiet squares, a contribution grid:
272
+ * weeks across a square each, as the swimlane runs, and the days down them,
273
+ * every other weekday named before them and the month over its weeks; a
274
+ * day on which something happens is filled with its events' colours, split
275
+ * into bands when several share it. Dates stay in each day's name and
276
+ * tooltip. Takes the place of the large calendar's months in squares.
277
+ * @prop {number} months - How many months activity draws from `month`: 1 by default.
111
278
  * @prop {boolean} heat - Light each day by how much happens on it, as a
112
279
  * contribution graph does: the events' `count`s added up (one each by
113
280
  * default), in four steps of the busiest day shown.
@@ -116,7 +283,12 @@ const openPickers = new Set<Calendar>();
116
283
  * by default.
117
284
  * @prop {boolean} noHeader - Leave out the title and arrows (`no-header`).
118
285
  * With a header, pressing the title travels by months and years: the
119
- * twelve months of the year, then twelve years, and back down.
286
+ * twelve months of the year, then twelve years, and back down. With a
287
+ * header, a swipe sideways across the days (a finger or a pen), or a
288
+ * trackpad's sideways scroll, does what the arrows do, the next month
289
+ * towards the start and the one before towards the end, and stops where
290
+ * they stop; the days take sideways touches for it, so a carousel or a
291
+ * page around the calendar does not move with them.
120
292
  * @prop {boolean} noToday - Leave out the Today button (`no-today`).
121
293
  * @prop {string} min - The first day a person may choose.
122
294
  * @prop {string} max - The last day a person may choose.
@@ -135,6 +307,11 @@ const openPickers = new Set<Calendar>();
135
307
  * @prop {boolean} disabled - A picker cannot be opened.
136
308
  * @prop {boolean} open - A picker's month is open.
137
309
  * @prop {CalendarEvent[]} events - What happens on the days (property only).
310
+ * @prop {(month: Date, view: string) => string} monthHeading - Names the month view's title, and a page's own view's,
311
+ * (property only): given the first of the month shown, it returns the words,
312
+ * so a product can write "Events in October" instead of "October 2026". The
313
+ * week and day views, the twelve months and the twelve years keep their own
314
+ * titles, and the title button's label still says what it opens.
138
315
  *
139
316
  * @fires day-press - A day was pressed or chosen with Enter or Space;
140
317
  * `{ day, events }`. Cancelable: cancelled, a selectable calendar keeps its value.
@@ -142,7 +319,8 @@ const openPickers = new Set<Calendar>();
142
319
  * `{ value, previous, start, end }`, `end` empty while it is still to come.
143
320
  * @fires input - A picker's value changed, the same moment as `change`.
144
321
  * @fires event-press - An event was pressed; `{ event, day }`.
145
- * @fires navigate - A person moved to another month; `{ month }`.
322
+ * @fires navigate - A person moved to another month, week or day; `{ month }`.
323
+ * @fires view-change - A person chose another view; `{ view }`.
146
324
  * @fires ds-calendar-toggle - A picker's month opened or closed; `{ open }`.
147
325
  *
148
326
  * A selectable calendar shows Clear right under its dates while something is chosen, and `clear()`
@@ -163,11 +341,17 @@ export class Calendar extends CalendarBase {
163
341
  dayWidth: { type: Number, attribute: "day-width" },
164
342
  lines: { type: Number },
165
343
  weekNumbers: { type: Boolean, attribute: "week-numbers", reflect: true },
344
+ view: { type: String, reflect: true },
345
+ views: { reflect: true, converter: viewsConverter },
346
+ viewNames: { attribute: false },
347
+ date: { type: String, reflect: true },
166
348
  fixed: { type: Boolean, reflect: true },
167
349
  outsideDays: { type: Boolean, attribute: "outside-days", reflect: true },
168
350
  noHeader: { type: Boolean, attribute: "no-header", reflect: true },
169
351
  noToday: { type: Boolean, attribute: "no-today", reflect: true },
170
352
  heat: { type: Boolean, reflect: true },
353
+ activity: { type: Boolean, reflect: true },
354
+ months: { type: Number },
171
355
  heatMax: { type: Number, attribute: "heat-max" },
172
356
  picker: { type: Boolean, reflect: true },
173
357
  name: { type: String, reflect: true },
@@ -179,23 +363,34 @@ export class Calendar extends CalendarBase {
179
363
  open: { type: Boolean, reflect: true },
180
364
  unfolded: { state: true },
181
365
  embedded: { attribute: false },
366
+ monthHeading: { attribute: false },
182
367
  level: { state: true },
183
368
  browseYear: { state: true },
184
369
  pickFocus: { state: true },
185
370
  };
186
371
 
187
372
  static styles = [unsafeCSS(metrics), unsafeCSS(controls), unsafeCSS(styles)];
373
+ /** Words cut short (the title, a weekday, the picker's value, an event's name on its bar) fade over their last square, never "…": marks them `data-cut="end"` while they do not fit. */
374
+ protected readonly cuts = new CutFades(this, { selector: ".title:not(.title-button), .title-text, .weekday, .trigger .text, .event .name, .swimlane-month" });
188
375
 
189
376
  declare month: string | undefined;
377
+ /** Names the month view's title from the first of the month shown; the month and year when unset. */
378
+ declare monthHeading: ((month: Date, view: string) => string) | undefined;
190
379
  declare compact: boolean;
191
380
  declare dayWidth: number | undefined;
192
381
  declare lines: number | undefined;
193
382
  declare weekNumbers: boolean;
383
+ declare view: CalendarView | (string & {});
384
+ declare views: boolean | string[];
385
+ declare viewNames: Record<string, string> | undefined;
386
+ declare date: string | undefined;
194
387
  declare fixed: boolean;
195
388
  declare outsideDays: boolean;
196
389
  declare noHeader: boolean;
197
390
  declare noToday: boolean;
198
391
  declare heat: boolean;
392
+ declare activity: boolean;
393
+ declare months: number | undefined;
199
394
  declare heatMax: number | undefined;
200
395
  declare picker: boolean;
201
396
  declare name: string | undefined;
@@ -231,11 +426,14 @@ export class Calendar extends CalendarBase {
231
426
  super();
232
427
  this.compact = false;
233
428
  this.weekNumbers = false;
429
+ this.view = "month";
430
+ this.views = false;
234
431
  this.fixed = false;
235
432
  this.outsideDays = false;
236
433
  this.noHeader = false;
237
434
  this.noToday = false;
238
435
  this.heat = false;
436
+ this.activity = false;
239
437
  this.picker = false;
240
438
  this.time = false;
241
439
  this.required = false;
@@ -281,6 +479,88 @@ export class Calendar extends CalendarBase {
281
479
  return this.byDay.get(day) ?? [];
282
480
  }
283
481
 
482
+ /** The view drawn: a compact calendar and a picker are always a month. */
483
+ get shownView(): CalendarView {
484
+ if (this.picker || this.compact) return "month";
485
+ if (isView(this.view)) return this.view;
486
+ return this.viewChoices.includes(this.view) ? (this.view as CalendarView) : "month";
487
+ }
488
+
489
+ /** The views offered in the header, in order: every one the calendar draws, or the page's list. */
490
+ get viewChoices(): string[] {
491
+ const views = this.views;
492
+ if (Array.isArray(views)) return [...new Set(views.map(view => String(view).trim()).filter(Boolean))];
493
+ return views ? VIEWS.map(([view]) => view) : [];
494
+ }
495
+
496
+ /** Whether the view shown is the page's own, drawn in its slot. */
497
+ private get ownView() {
498
+ return !isView(this.shownView);
499
+ }
500
+
501
+ /** A view's words in the switch: the page's, else the shared ones, else its name. */
502
+ private viewName(view: string): string {
503
+ const shared = VIEWS.find(([choice]) => choice === view)?.[1];
504
+ const word = this.viewNames?.[view] ?? (shared ? this.words(shared) : view);
505
+ // The switch's options are written `value:words,value:words`.
506
+ return word.replace(/,/g, " ");
507
+ }
508
+
509
+ /** Whether the view moves by days (a week or a day) rather than by months (a month or a swimlane). */
510
+ private get byDays() {
511
+ const view = this.shownView;
512
+ return view === "week" || view === "day";
513
+ }
514
+
515
+ /** The day the week or day view shows: `date`, else today in the month shown, else its first. */
516
+ get shownDay(): Day {
517
+ if (isDay(this.date)) return this.date;
518
+ const month = this.shownMonth;
519
+ return sameMonth(this.todayDay, month) ? this.todayDay : month;
520
+ }
521
+
522
+ /** The seven days of the week `day` falls in. */
523
+ private weekOf(day: Day): Day[] {
524
+ const start = addDays(day, -((weekdayOf(day) - this.firstDay + 7) % 7));
525
+ return Array.from({ length: 7 }, (_, index) => addDays(start, index));
526
+ }
527
+
528
+ /** Shows another week or day around `day`, and says so with `navigate`. */
529
+ showDay(day: Day, announce = false) {
530
+ if (!isDay(day) || day === this.date) return;
531
+ this.date = day;
532
+ this.month = day.slice(0, 7);
533
+ this.unfolded = undefined;
534
+ if (announce) this.announceMonth(day);
535
+ }
536
+
537
+ /** Changes the view, as Day, Week and Month do, and says so with `view-change`. */
538
+ showView(view: CalendarView) {
539
+ if (view === this.shownView) return;
540
+ if (!isDay(this.date)) this.date = this.shownDay;
541
+ this.view = view;
542
+ this.unfolded = undefined;
543
+ this.dispatchEvent(new CustomEvent<CalendarViewDetail>("view-change", { bubbles: true, composed: true, detail: { view } }));
544
+ }
545
+
546
+ /** The split button's choice; its own change event stays inside, since a calendar's change is a chosen day. */
547
+ private onViewChange = (event: Event) => {
548
+ event.stopPropagation();
549
+ const view = (event as CustomEvent<{ value: string }>).detail?.value;
550
+ if (view && (isView(view) || this.viewChoices.includes(view))) this.showView(view as CalendarView);
551
+ };
552
+
553
+ /** Brings a day into view: its month, its week or the day itself. */
554
+ private bringIntoView(day: Day) {
555
+ const view = this.shownView;
556
+ if (!this.byDays) {
557
+ if (!sameMonth(day, this.shownMonth)) this.showMonth(day, true);
558
+ } else if (view === "day" || !this.weekOf(this.shownDay).includes(day)) this.showDay(day, true);
559
+ }
560
+
561
+ /** Each shown day's lines of events, laid out a week at a time in render(). */
562
+ private laidOut = new Map<Day, { lines: CalendarLine[]; hidden: number }>();
563
+
284
564
  protected willUpdate(changed: PropertyValues<this>) {
285
565
  super.willUpdate(changed);
286
566
  this.style.setProperty("--ds-calendar-day-squares", String(this.squaresPerDay));
@@ -299,6 +579,13 @@ export class Calendar extends CalendarBase {
299
579
 
300
580
  protected updated(changed: PropertyValues<this>) {
301
581
  super.updated(changed);
582
+ // A day opens its hours an hour before its first timed event, or at seven.
583
+ if (this.shownView === "day" && (changed.has("view") || changed.has("date") || changed.has("events"))) {
584
+ const hours = this.renderRoot.querySelector<HTMLElement>(".hours");
585
+ const first = hours?.querySelector<HTMLElement>(".hour[data-busy]")?.dataset.hour;
586
+ const open = hours?.querySelector<HTMLElement>(`.hour[data-hour="${Math.max(0, (first ? Number(first) : 8) - 1)}"]`);
587
+ if (hours && open) hours.scrollTop = open.offsetTop;
588
+ }
302
589
  if (changed.has("value") || changed.has("required")) {
303
590
  this.internals?.setFormValue(this.value || null);
304
591
  if (this.required && !this.value) this.internals?.setValidity({ valueMissing: true }, this.pickerWords(undefined, "Choose a date"), this.trigger ?? undefined);
@@ -333,6 +620,7 @@ export class Calendar extends CalendarBase {
333
620
  showToday() {
334
621
  this.level = "days";
335
622
  this.showMonth(this.todayDay, true);
623
+ if (this.shownView !== "month") this.showDay(this.todayDay, true);
336
624
  this.focusDay = this.todayDay;
337
625
  }
338
626
 
@@ -394,7 +682,11 @@ export class Calendar extends CalendarBase {
394
682
 
395
683
  /** The arrows: a month among the days, a year among the months, twelve years among the years. */
396
684
  private step(direction: -1 | 1) {
397
- if (this.level === "days") return direction < 0 ? this.previousMonth() : this.nextMonth();
685
+ if (this.level === "days") {
686
+ const view = this.shownView;
687
+ if (this.byDays) return this.showDay(addDays(this.shownDay, direction * (view === "week" ? 7 : 1)), true);
688
+ return direction < 0 ? this.previousMonth() : this.nextMonth();
689
+ }
398
690
  this.browseYear += direction * (this.level === "months" ? 1 : 12);
399
691
  if (this.level === "years") this.pickFocus = (this.pickFocus ?? this.browseYear) + direction * 12;
400
692
  }
@@ -412,6 +704,7 @@ export class Calendar extends CalendarBase {
412
704
  const month = `${String(this.browseYear).padStart(4, "0")}-${String(value + 1).padStart(2, "0")}-01`;
413
705
  this.level = "days";
414
706
  this.showMonth(month, true);
707
+ if (this.shownView !== "month") this.showDay(month as Day, false);
415
708
  const day = [this.focusDay, this.chosen.start, this.todayDay].find(day => day && sameMonth(day, month)) ?? month;
416
709
  void this.focusCell(day);
417
710
  }
@@ -533,10 +826,62 @@ export class Calendar extends CalendarBase {
533
826
  const target = this.keyTarget(event, day);
534
827
  if (!target) return;
535
828
  event.preventDefault();
536
- if (!sameMonth(target, this.shownMonth)) this.showMonth(target, true);
829
+ this.bringIntoView(target);
537
830
  void this.focusCell(target);
538
831
  };
539
832
 
833
+ // A swipe sideways across the days or the months, as the arrows: by finger or pen, or a trackpad's
834
+ // sideways scroll. Read from the arrows themselves, so a swipe goes nowhere an arrow cannot.
835
+ private swipe?: { id: number; x: number; y: number; at: number };
836
+ private swipedAt = 0;
837
+ private wheel = { dx: 0, at: 0, locked: 0 };
838
+
839
+ private swipeTo(direction: -1 | 1) {
840
+ const arrow = this.renderRoot.querySelector<HTMLButtonElement>(`.header [part~="${direction < 0 ? "previous" : "next"}"]`);
841
+ if (!arrow || arrow.disabled) return false;
842
+ this.step(direction);
843
+ return true;
844
+ }
845
+
846
+ private get rtl() {
847
+ return getComputedStyle(this).direction === "rtl";
848
+ }
849
+
850
+ private onSwipeStart = (event: PointerEvent) => {
851
+ this.swipe = event.pointerType === "mouse" || !event.isPrimary ? undefined : { id: event.pointerId, x: event.clientX, y: event.clientY, at: event.timeStamp };
852
+ };
853
+
854
+ private onSwipeEnd = (event: PointerEvent) => {
855
+ const swipe = this.swipe;
856
+ this.swipe = undefined;
857
+ if (!swipe || event.pointerId !== swipe.id) return;
858
+ const dx = (event.clientX - swipe.x) * (this.rtl ? -1 : 1);
859
+ const dy = event.clientY - swipe.y;
860
+ if (Math.abs(dx) < 40 || Math.abs(dx) < Math.abs(dy) * 2 || event.timeStamp - swipe.at > 800) return;
861
+ // A day the swipe started on is not pressed by it.
862
+ if (this.swipeTo(dx < 0 ? 1 : -1)) this.swipedAt = Date.now();
863
+ };
864
+
865
+ private onSwipeWheel = (event: WheelEvent) => {
866
+ if (Math.abs(event.deltaX) <= Math.abs(event.deltaY)) return;
867
+ event.preventDefault();
868
+ const now = Date.now();
869
+ if (now < this.wheel.locked) return;
870
+ if (now - this.wheel.at > 200) this.wheel.dx = 0;
871
+ this.wheel.at = now;
872
+ this.wheel.dx += event.deltaX * (this.rtl ? -1 : 1);
873
+ if (Math.abs(this.wheel.dx) < 60) return;
874
+ const direction = this.wheel.dx > 0 ? 1 : -1;
875
+ this.wheel = { dx: 0, at: 0, locked: now + 500 };
876
+ this.swipeTo(direction);
877
+ };
878
+
879
+ private onSwipeClick = (event: MouseEvent) => {
880
+ if (Date.now() - this.swipedAt > 400) return;
881
+ event.preventDefault();
882
+ event.stopImmediatePropagation();
883
+ };
884
+
540
885
  private onClick = (event: MouseEvent) => {
541
886
  const path = event.composedPath() as HTMLElement[];
542
887
  const find = (selector: string) => path.find(node => node instanceof HTMLElement && node.matches(selector));
@@ -557,7 +902,7 @@ export class Calendar extends CalendarBase {
557
902
  this.focusDay = day;
558
903
  this.press(day);
559
904
  // A day of the month before or after takes the calendar there.
560
- if (!sameMonth(day, this.shownMonth)) this.showMonth(day, true);
905
+ this.bringIntoView(day);
561
906
  };
562
907
 
563
908
  /** While a range waits for its end, the day under the pointer previews it. */
@@ -581,26 +926,41 @@ export class Calendar extends CalendarBase {
581
926
  const level = this.level;
582
927
  const year = this.browseYear;
583
928
  const span = this.yearSpan;
584
- const labels = { days: ["Previous month", "Next month"], months: ["Previous year", "Next year"], years: ["Earlier years", "Later years"] }[level];
585
- const blocked = level === "days"
929
+ const view = this.shownView;
930
+ const labels = level === "days" && this.byDays
931
+ ? view === "week" ? ["Previous week", "Next week"] : ["Previous day", "Next day"]
932
+ : { days: ["Previous month", "Next month"], months: ["Previous year", "Next year"], years: ["Earlier years", "Later years"] }[level];
933
+ const shownDays = view === "week" ? this.weekOf(this.shownDay) : [this.shownDay];
934
+ const blocked = level === "days" && this.byDays
935
+ ? [Boolean(min && addDays(shownDays[0], -1) < min), Boolean(max && addDays(shownDays.at(-1)!, 1) > max)]
936
+ : level === "days"
586
937
  ? [before, after]
587
938
  : level === "months"
588
939
  ? [Boolean(min && year - 1 < Number(min.slice(0, 4))), Boolean(max && year + 1 > Number(max.slice(0, 4)))]
589
940
  : [Boolean(min && span[0] - 1 < Number(min.slice(0, 4))), Boolean(max && span[0] + 12 > Number(max.slice(0, 4)))];
590
941
  const arrow = (which: "previous" | "next") => html`<button
591
- class="ds-button ds-button--icon nav"
942
+ class="nav"
592
943
  part=${which}
593
944
  type="button"
594
945
  aria-label=${this.words(labels[which === "previous" ? 0 : 1])}
595
946
  ?disabled=${blocked[which === "previous" ? 0 : 1]}
596
947
  @click=${() => this.step(which === "previous" ? -1 : 1)}
597
- ><ds-icon type=${which === "previous" ? "chevron-left" : "chevron-right"} size="large" aria-hidden="true"></ds-icon></button>`;
948
+ ><ds-icon type=${(this.compact ? "chevron-" : "") + (which === "previous" ? "left" : "right")} size=${this.compact ? "large" : nothing} aria-hidden="true"></ds-icon></button>`;
598
949
  const title = level === "days"
599
- ? monthTitle(month, this.compact ? "short" : "long")
950
+ ? view === "week"
951
+ ? this.rangeTitle(shownDays[0], shownDays[6])
952
+ : view === "day"
953
+ ? dayLabel(this.shownDay)
954
+ : view === "swimlane"
955
+ ? this.monthRangeTitle(this.swimlaneWeeks)
956
+ : this.monthHeading
957
+ ? this.monthHeading(new Date(Number(month.slice(0, 4)), Number(month.slice(5, 7)) - 1, 1), view)
958
+ : monthTitle(month, this.compact ? "short" : "long")
600
959
  : level === "months"
601
960
  ? this.yearName(year)
602
961
  : `${this.yearName(span[0])} – ${this.yearName(span[0] + 11)}`;
603
- return html`<div class="header" part="header">
962
+ const switchable = this.viewChoices.length > 1 && !this.compact && !this.picker;
963
+ return html`<div class="header" part="header" ?data-views=${switchable}>
604
964
  ${level === "years"
605
965
  ? html`<span class="title" id="title" aria-live="polite">${title}</span>`
606
966
  : html`<button
@@ -610,26 +970,38 @@ export class Calendar extends CalendarBase {
610
970
  aria-label=${`${title}, ${this.words("Choose a month and year")}`}
611
971
  @click=${this.levelUp}
612
972
  ><span class="title-text" id="title" aria-live="polite">${title}</span></button>`}
613
- <span class="controls">
614
- ${this.noToday || this.squaresPerDay < 2 ? nothing : html`<button class="ds-button today-button" part="today" type="button" @click=${() => this.showToday()}>${this.words("Today")}</button>`}
973
+ ${switchable ? html`<ds-button
974
+ class="views"
975
+ part="views"
976
+ split
977
+ literal
978
+ aria-label=${this.words("View")}
979
+ .options=${this.viewChoices.map(choice => `${choice}:${this.viewName(choice)}`).join(",")}
980
+ .value=${view}
981
+ @change=${this.onViewChange}
982
+ ></ds-button>` : nothing}
983
+ <span class="controls" role="group" aria-label=${this.words("Date")}>
615
984
  ${arrow("previous")}
985
+ ${this.noToday || this.squaresPerDay < 2 ? nothing : html`<button class="today-button" part="today" type="button" @click=${() => this.showToday()}>${this.words("Today")}</button>`}
616
986
  ${arrow("next")}
617
987
  </span>
618
988
  </div>`;
619
989
  }
620
990
 
621
- private renderDay(day: Day, column: number) {
622
- const month = this.shownMonth;
623
- const outside = !sameMonth(day, month);
624
- if (outside && !this.outsideDays) return html`<div role="gridcell" class="day outside" part="day outside"></div>`;
991
+ private renderDay(day: Day, inView = sameMonth(day, this.shownMonth), tabDay = this.tabDay, label?: DayLabel) {
992
+ const outside = !inView;
993
+ if (outside && !this.outsideDays) {
994
+ return html`<div role="gridcell" class="day outside" part="day outside">${label?.weekday || label?.week
995
+ ? html`<span class="date-line" aria-hidden="true">${this.renderLabel(label)}</span>`
996
+ : nothing}</div>`;
997
+ }
625
998
  const events = this.eventsOn(day);
626
999
  const lines = this.eventLines;
627
1000
  const isToday = day === this.todayDay;
628
1001
  const { selected, inside, first, last } = this.selection(day);
629
1002
  const allowed = this.allowed(day);
630
1003
  const unfolded = this.unfolded === day;
631
- const shown = unfolded || events.length <= lines ? events : events.slice(0, Math.max(0, lines - 1));
632
- const hidden = events.length - shown.length;
1004
+ const laid = this.laidOut.get(day) ?? { lines: [], hidden: 0 };
633
1005
  const heat = this.heatByDay.get(day);
634
1006
  const parts = ["day", isToday ? "today" : "", selected ? "selected" : "", heat ? "heat" : ""].filter(Boolean).join(" ");
635
1007
  return html`<div
@@ -637,7 +1009,7 @@ export class Calendar extends CalendarBase {
637
1009
  class="day"
638
1010
  part=${parts}
639
1011
  data-day=${day}
640
- tabindex=${!outside && day === this.tabDay ? 0 : -1}
1012
+ tabindex=${!outside && day === tabDay ? 0 : -1}
641
1013
  aria-label=${this.cellLabel(day, events)}
642
1014
  aria-selected=${this.selectable ? String(selected || inside) : nothing}
643
1015
  aria-current=${isToday ? "date" : nothing}
@@ -653,29 +1025,306 @@ export class Calendar extends CalendarBase {
653
1025
  ?data-open=${unfolded}
654
1026
  >
655
1027
  <span class="date-line" aria-hidden="true">
656
- ${this.weekNumbers && column === 0 && !this.compact ? html`<span class="week-number">${this.words("W{week}", { week: isoWeek(day) })}</span>` : nothing}
1028
+ ${label ? this.renderLabel(label) : nothing}
657
1029
  <span class="date">${dateNumber(day)}</span>
658
1030
  </span>
659
1031
  ${lines > 0 && events.length
660
1032
  ? html`<span class="events" aria-hidden="true">
661
- ${shown.map(event => html`<span
662
- class="event"
663
- part="event"
664
- data-event=${events.indexOf(event)}
665
- style=${event.color ? `--ds-calendar-event-fill: ${event.color}; --ds-calendar-event-ink: var(--ds-slate)` : nothing}
666
- >${event.time ? html`<span class="time">${event.time}</span>` : nothing}<span class="name">${event.title}</span></span>`)}
667
- ${hidden > 0 && !unfolded ? html`<span class="more" part="more" data-more>+${hidden}</span>` : nothing}
1033
+ ${unfolded
1034
+ ? events.map(event => this.renderEvent(event, events, 1))
1035
+ : laid.lines.map(line => line === null || line === "on"
1036
+ ? html`<span class="line" data-line=${line ?? "empty"}></span>`
1037
+ : this.renderEvent(line.event, events, line.span))}
1038
+ ${laid.hidden > 0 && !unfolded ? html`<span class="more" part="more" data-more>+${laid.hidden}</span>` : nothing}
668
1039
  </span>`
669
1040
  : nothing}
670
1041
  </div>`;
671
1042
  }
672
1043
 
1044
+ /** What a day writes before its date: its weekday's name in the first week, and the week's number on its first day. */
1045
+ private renderLabel(label: DayLabel) {
1046
+ return html`${label.weekday ? html`<span class="weekday-name" ?data-today=${label.today}>${label.weekday}</span>` : nothing}${label.week
1047
+ ? html`<span class="week-number">${this.words("W{week}", { week: label.week })}</span>`
1048
+ : nothing}`;
1049
+ }
1050
+
1051
+ /** A week's days as one title: "Oct 18 – 24, 2026", in the language's own way. */
1052
+ private rangeTitle(from: Day, to: Day): string {
1053
+ const format = dateFormatter({ month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
1054
+ const at = (day: Day) => Date.UTC(Number(day.slice(0, 4)), Number(day.slice(5, 7)) - 1, Number(day.slice(8, 10)), 12);
1055
+ return typeof format.formatRange === "function" ? format.formatRange(at(from), at(to)) : `${format.format(at(from))} – ${format.format(at(to))}`;
1056
+ }
1057
+
1058
+ /** The first day of each week a swimlane draws: from the week holding the month's first, a week to each square the month has across. */
1059
+ private get swimlaneWeeks(): Day[] {
1060
+ const first = this.shownMonth;
1061
+ const start = addDays(first, -((weekdayOf(first) - this.firstDay + 7) % 7));
1062
+ const count = Math.max(4, 7 * this.squaresPerDay);
1063
+ return Array.from({ length: count }, (_, index) => addDays(start, index * 7));
1064
+ }
1065
+
1066
+ /** The month owning most of a week: its Thursday's, counted from the week's first day. */
1067
+ private ownerOf(weekStart: Day): Day {
1068
+ return startOfMonth(addDays(weekStart, 3));
1069
+ }
1070
+
1071
+ /** The months a swimlane covers as one title: "Oct 2026 – Jan 2027". */
1072
+ private monthRangeTitle(weeks: readonly Day[]): string {
1073
+ const from = this.ownerOf(weeks[0]), to = this.ownerOf(weeks.at(-1)!);
1074
+ const format = dateFormatter({ month: "short", year: "numeric", timeZone: "UTC" });
1075
+ const at = (day: Day) => Date.UTC(Number(day.slice(0, 4)), Number(day.slice(5, 7)) - 1, 15);
1076
+ if (from === to) return monthTitle(from);
1077
+ return typeof format.formatRange === "function" ? format.formatRange(at(from), at(to)) : `${format.format(at(from))} – ${format.format(at(to))}`;
1078
+ }
1079
+
1080
+ /**
1081
+ * The events as a swimlane: weeks across, a square each; over them the
1082
+ * months, named where the month owning the week changes, and each week's
1083
+ * first date (today's date in its disc on today's week); then a row to an
1084
+ * event, a square high, each one bar from its first week to its last.
1085
+ */
1086
+ private renderSwimlane() {
1087
+ const weeks = this.swimlaneWeeks;
1088
+ const bars = swimlaneBars(this.events ?? [], weeks);
1089
+ // Fixed, the rows (a square each) fill the month's height under the months and dates, and scroll past it.
1090
+ const fit = this.fixed ? Math.max(1, 6 * (this.eventLines + 2) - 1) : 6;
1091
+ const rows = Math.max(fit, bars.length + 1);
1092
+ const today = this.todayDay;
1093
+ const todayWeek = weeks.findIndex(start => today >= start && today <= addDays(start, 6));
1094
+ const months: { column: number; span: number; month: Day }[] = [];
1095
+ weeks.forEach((start, column) => {
1096
+ const month = this.ownerOf(start);
1097
+ const last = months.at(-1);
1098
+ if (last && last.month === month) last.span++;
1099
+ else months.push({ column, span: 1, month });
1100
+ });
1101
+ const range = (event: CalendarEvent) => {
1102
+ const end = event.end && isDay(event.end) && event.end > event.start ? event.end : event.start;
1103
+ return end === event.start ? dayLabel(event.start) : this.rangeTitle(event.start, end);
1104
+ };
1105
+ return this.swipeFrame(html`<div
1106
+ class="swimlane"
1107
+ part="swimlane"
1108
+ role="group"
1109
+ ?data-travel=${this.travelled}
1110
+ aria-label=${this.nameOr(this.monthRangeTitle(weeks))}
1111
+ style=${`--ds-calendar-weeks: ${weeks.length}; --ds-calendar-rows: ${rows}; --ds-calendar-fit: ${fit}`}
1112
+ >
1113
+ <div class="swimlane-months" part="months" aria-hidden="true">
1114
+ ${months.map(({ column, span, month }, index) => html`<span class="swimlane-month" style=${`grid-column: ${column + 1} / span ${span}`}>${
1115
+ index === 0 || month.slice(5, 7) === "01" ? monthTitle(month, "short") : monthName(month, "short")
1116
+ }</span>`)}
1117
+ </div>
1118
+ <div class="swimlane-dates" part="dates" aria-hidden="true">
1119
+ ${weeks.map((start, column) => column === todayWeek
1120
+ ? html`<span class="swimlane-date" data-today><span class="date">${dateNumber(today)}</span></span>`
1121
+ : html`<span class="swimlane-date"><span class="date">${dateNumber(start)}</span></span>`)}
1122
+ </div>
1123
+ <div class="swimlane-scroll" part="scroll"><div class="swimlane-grid" part="grid">
1124
+ ${Array.from({ length: rows }, (_, row) => weeks.map((_, column) => html`<span
1125
+ class="cell"
1126
+ aria-hidden="true"
1127
+ style=${`grid-row: ${row + 1}; grid-column: ${column + 1}`}
1128
+ ?data-first-row=${row === 0}
1129
+ ?data-last-row=${row === rows - 1}
1130
+ ?data-first-column=${column === 0}
1131
+ ?data-last-column=${column === weeks.length - 1}
1132
+ ></span>`))}
1133
+ ${bars.map(({ event, row, from, to }, index) => {
1134
+ const fill = event.color ? `--ds-calendar-event-fill: ${event.color}; --ds-calendar-event-ink: var(--ds-slate); ` : "";
1135
+ return html`<button
1136
+ type="button"
1137
+ class="event"
1138
+ part="event"
1139
+ data-event=${index}
1140
+ aria-label=${`${event.title}, ${range(event)}`}
1141
+ style=${`${fill}grid-row: ${row + 1}; grid-column: ${from + 1} / ${to + 2}`}
1142
+ @click=${() => this.pressEvent(event, event.start)}
1143
+ ><span class="name">${event.title}</span></button>`;
1144
+ })}
1145
+ </div></div>
1146
+ </div>`);
1147
+ }
1148
+
1149
+ /** The first day of each week activity draws: from the week holding the month's first to the one holding its last month's last day. */
1150
+ private get activityWeeks(): Day[] {
1151
+ const first = this.shownMonth;
1152
+ const end = addDays(addMonths(first, whole(this.months, 1, 36, 1)), -1);
1153
+ const weeks: Day[] = [];
1154
+ for (let day = addDays(first, -((weekdayOf(first) - this.firstDay + 7) % 7)); day <= end; day = addDays(day, 7)) weeks.push(day);
1155
+ return weeks;
1156
+ }
1157
+
1158
+ /**
1159
+ * The days as quiet squares: every other weekday named down the start, the
1160
+ * months over their weeks, and a week to a column a square wide, its days
1161
+ * down it, each a square drawn two pixels in with a picture's corners,
1162
+ * filled with its events' colours. Days outside the months stay empty.
1163
+ */
1164
+ private renderActivity() {
1165
+ const weeks = this.activityWeeks;
1166
+ const first = this.shownMonth;
1167
+ const end = addMonths(first, whole(this.months, 1, 36, 1));
1168
+ this.byDay = eventsByDay(this.events ?? [], weeks[0], addDays(weeks.at(-1)!, 6));
1169
+ const short = weekdayNames(this.firstDay, "short");
1170
+ const narrow = weekdayNames(this.firstDay, "narrow");
1171
+ const long = weekdayNames(this.firstDay, "long");
1172
+ const today = this.todayDay;
1173
+ const months: { column: number; span: number; month: Day }[] = [];
1174
+ // A week is named by the month owning most of it, held to the months drawn.
1175
+ const lastMonth = addMonths(end, -1);
1176
+ weeks.forEach((start, column) => {
1177
+ const owner = this.ownerOf(start);
1178
+ const month = owner < first ? first : owner > lastMonth ? lastMonth : owner;
1179
+ const last = months.at(-1);
1180
+ if (last && last.month === month) last.span++;
1181
+ else months.push({ column, span: 1, month });
1182
+ });
1183
+ return html`<div class="calendar" part="calendar">
1184
+ ${this.renderHeader()}
1185
+ <div class="activity" part="activity" style=${`--ds-calendar-weeks: ${weeks.length}`}>
1186
+ <div class="activity-rail" part="weekdays" aria-hidden="true">
1187
+ ${short.map((name, row) => html`<span class="activity-weekday" data-narrow=${narrow[row]}>${row % 2 === 1 ? name : ""}</span>`)}
1188
+ </div>
1189
+ <div class="activity-weeks">
1190
+ <div class="activity-months" part="months" aria-hidden="true">
1191
+ ${months.map(({ column, span, month }, index) => html`<span class="activity-month" style=${`grid-column: ${column + 1} / span ${span}`}>${
1192
+ index === 0 || month.slice(5, 7) === "01" ? monthTitle(month, "short") : monthName(month, "short")
1193
+ }</span>`)}
1194
+ </div>
1195
+ <div
1196
+ class="activity-grid"
1197
+ part="grid"
1198
+ role="grid"
1199
+ aria-label=${this.nameOr(months.length > 1 ? this.monthRangeTitle(weeks) : monthTitle(first))}
1200
+ @click=${this.onClick}
1201
+ >
1202
+ ${short.map((_, row) => html`<div role="row" class="activity-row">
1203
+ <span role="rowheader" class="activity-hidden">${long[row]}</span>
1204
+ ${weeks.map((start, column) => {
1205
+ const day = addDays(start, row);
1206
+ const style = `grid-row: ${row + 1}; grid-column: ${column + 1}`;
1207
+ if (day < first || day >= end) return html`<span role="gridcell" class="activity-day" aria-hidden="true" style=${style}></span>`;
1208
+ const events = this.eventsOn(day);
1209
+ const fill = activityFill(events);
1210
+ const label = this.cellLabel(day, events);
1211
+ const { selected } = this.selection(day);
1212
+ return html`<span
1213
+ role="gridcell"
1214
+ class="activity-day"
1215
+ part=${["day", day === today ? "today" : "", events.length ? "filled" : ""].filter(Boolean).join(" ")}
1216
+ data-day=${day}
1217
+ aria-label=${label}
1218
+ title=${label}
1219
+ aria-current=${day === today ? "date" : nothing}
1220
+ aria-selected=${this.selectable ? String(selected) : nothing}
1221
+ ?data-filled=${events.length > 0}
1222
+ ?data-selected=${selected}
1223
+ style=${`${style};${fill ? ` --ds-calendar-cell-fill: ${fill};` : ""}`}
1224
+ ></span>`;
1225
+ })}
1226
+ </div>`)}
1227
+ </div>
1228
+ </div>
1229
+ </div>
1230
+ </div>`;
1231
+ }
1232
+
1233
+ /** A view drawn under the header that swipes as the arrows move: the swimlane and a page's own view. */
1234
+ private swipeFrame(content: unknown) {
1235
+ const swipes = !this.noHeader;
1236
+ return html`<div
1237
+ class="calendar"
1238
+ part="calendar"
1239
+ ?data-swipe=${swipes}
1240
+ @pointerdown=${swipes ? this.onSwipeStart : nothing}
1241
+ @pointerup=${swipes ? this.onSwipeEnd : nothing}
1242
+ @pointercancel=${() => (this.swipe = undefined)}
1243
+ @wheel=${swipes ? this.onSwipeWheel : nothing}
1244
+ @click=${{ handleEvent: this.onSwipeClick, capture: true }}
1245
+ >
1246
+ ${this.renderHeader()}
1247
+ ${content}
1248
+ </div>`;
1249
+ }
1250
+
1251
+ /** A page's own view: what it puts in the slot named after the view, as wide as the month. */
1252
+ private renderOwnView() {
1253
+ const view = this.shownView;
1254
+ return this.swipeFrame(html`<div class="own-view" part="own-view" data-view=${view} ?data-travel=${this.travelled}><slot name=${view}></slot></div>`);
1255
+ }
1256
+
1257
+ /**
1258
+ * One day: its events without a time across the top, a day's width each,
1259
+ * then its hours, a square each, in an area that scrolls, with each timed
1260
+ * event at its hour beside the others of that hour.
1261
+ */
1262
+ private renderDayView() {
1263
+ const day = this.shownDay;
1264
+ this.byDay = eventsByDay(this.events ?? [], day, day);
1265
+ const events = this.eventsOn(day);
1266
+ const allDay = events.filter(event => !event.time);
1267
+ const hourName = dateFormatter({ hour: "numeric", timeZone: "UTC" });
1268
+ const hours = Array.from({ length: 24 }, (_, hour) => ({
1269
+ hour,
1270
+ name: hourName.format(Date.UTC(2000, 0, 1, hour)),
1271
+ events: events.filter(event => event.time && Number(event.time.slice(0, 2)) === hour),
1272
+ }));
1273
+ return html`<div class="calendar" part="calendar">
1274
+ ${this.renderHeader()}
1275
+ ${this.level !== "days" ? this.renderPicks(6) : html`<div
1276
+ class="day-view"
1277
+ part="day-view"
1278
+ data-day=${day}
1279
+ aria-label=${this.cellLabel(day, events)}
1280
+ @click=${this.onClick}
1281
+ >
1282
+ ${allDay.length ? html`<div class="all-day" part="all-day">${allDay.map(event => this.renderEvent(event, events, 1))}</div>` : nothing}
1283
+ <div class="hours" part="hours">
1284
+ ${hours.map(({ hour, name, events: atHour }) => html`<div class="hour" part="hour" data-hour=${hour} ?data-busy=${atHour.length > 0}>
1285
+ <span class="hour-name">${name}</span>
1286
+ <span class="hour-events">${atHour.map(event => this.renderEvent(event, events, 1))}</span>
1287
+ </div>`)}
1288
+ </div>
1289
+ </div>`}
1290
+ </div>`;
1291
+ }
1292
+
1293
+ /** An event on its line: one bar over `span` days, its name written once. */
1294
+ private renderEvent(event: CalendarEvent, events: readonly CalendarEvent[], span: number) {
1295
+ const fill = event.color ? `--ds-calendar-event-fill: ${event.color}; --ds-calendar-event-ink: var(--ds-slate);` : "";
1296
+ return html`<span
1297
+ class="event"
1298
+ part="event"
1299
+ data-event=${events.indexOf(event)}
1300
+ data-span=${span > 1 ? span : nothing}
1301
+ style=${fill || span > 1 ? `${fill}${span > 1 ? ` --ds-calendar-event-span: ${span}` : ""}` : nothing}
1302
+ >${event.time ? html`<span class="time">${event.time}</span>` : nothing}<span class="name">${event.title}</span></span>`;
1303
+ }
1304
+
673
1305
  render() {
674
1306
  if (this.picker) return this.renderPicker();
1307
+ if (this.activity && this.level === "days") return this.renderActivity();
675
1308
  const month = this.shownMonth;
676
1309
  const first = this.firstDay;
677
- const weeks = monthWeeks(month, first, this.fixed);
1310
+ const view = this.shownView;
1311
+ if (view === "day" && this.level === "days") return this.renderDayView();
1312
+ if (view === "swimlane" && this.level === "days") return this.renderSwimlane();
1313
+ if (this.ownView && this.level === "days") return this.renderOwnView();
1314
+ const weeks = view === "week" ? [this.weekOf(this.shownDay)] : monthWeeks(month, first, this.fixed);
678
1315
  this.byDay = eventsByDay(this.events ?? [], weeks[0][0], weeks.at(-1)![6]);
1316
+ this.laidOut = new Map();
1317
+ // In view: the week's days, or the month's (the days around it are drawn only with outside-days).
1318
+ const inView = (day: Day) => view === "week" || sameMonth(day, month);
1319
+ const drawn = (day: Day) => inView(day) || this.outsideDays;
1320
+ // A week shows every event of each day: as many lines as its fullest day needs.
1321
+ const depth = view === "week"
1322
+ ? Math.max(this.eventLines, ...weekLines(weeks[0], this.byDay, 99).map(day => day.lines.length))
1323
+ : this.eventLines;
1324
+ for (const week of weeks) weekLines(week, this.byDay, depth, drawn).forEach((laid, column) => this.laidOut.set(week[column], laid));
1325
+ const tabDay = view === "week"
1326
+ ? [this.focusDay, this.chosen.start, this.todayDay].find(day => day && weeks[0].includes(day)) ?? weeks[0][0]
1327
+ : this.tabDay;
679
1328
  // Heat is measured over the days of the month shown, so the neighbours' days never set its scale.
680
1329
  this.heatByDay = this.heat ? heatLevels(new Map([...this.byDay].filter(([day]) => sameMonth(day, month))), this.heatMax) : new Map();
681
1330
  // A compact month names its days in a letter (one square) or two (wider); a full month in short.
@@ -685,14 +1334,33 @@ export class Calendar extends CalendarBase {
685
1334
  : weekdayNames(first, "short").map(name => (/^\p{Script=Latin}/u.test(name) ? name.replace(/\.$/, "").slice(0, 2) : name))
686
1335
  : weekdayNames(first, "short");
687
1336
  const long = weekdayNames(first, "long");
688
- return html`<div class="calendar" part="calendar" @focusout=${this.onFocusOut} @pointerover=${this.onPointerOver} @pointerleave=${() => (this.hoverDay = undefined)}>
1337
+ // Inside a day's box the name is short where the day is three squares or more, and a letter where it is narrower.
1338
+ const inside = this.squaresPerDay >= 3 ? short : weekdayNames(first, "narrow");
1339
+ const today = this.todayDay;
1340
+ const todayColumn = drawn(today) && weeks.some(week => week.includes(today)) ? (weekdayOf(today) - first + 7) % 7 : -1;
1341
+ const swipes = !this.noHeader;
1342
+ return html`<div
1343
+ class="calendar"
1344
+ part="calendar"
1345
+ ?data-swipe=${swipes}
1346
+ @focusout=${this.onFocusOut}
1347
+ @pointerover=${this.onPointerOver}
1348
+ @pointerleave=${() => (this.hoverDay = undefined)}
1349
+ @pointerdown=${swipes ? this.onSwipeStart : nothing}
1350
+ @pointerup=${swipes ? this.onSwipeEnd : nothing}
1351
+ @pointercancel=${() => (this.swipe = undefined)}
1352
+ @wheel=${swipes ? this.onSwipeWheel : nothing}
1353
+ @click=${{ handleEvent: this.onSwipeClick, capture: true }}
1354
+ >
689
1355
  ${this.renderHeader()}
690
1356
  ${this.level !== "days" && !this.noHeader ? this.renderPicks(weeks.length) : html`<div
691
1357
  class="grid"
692
1358
  part="grid"
693
1359
  role="grid"
1360
+ data-view=${view}
694
1361
  ?data-travel=${this.travelled}
695
- aria-label=${this.nameOr(monthTitle(month))}
1362
+ aria-label=${this.nameOr(view === "week" ? this.rangeTitle(weeks[0][0], weeks[0][6]) : monthTitle(month))}
1363
+ style=${view === "week" ? `--ds-calendar-lines: ${depth}` : nothing}
696
1364
  aria-multiselectable=${this.selectable ? "true" : nothing}
697
1365
  @keydown=${this.onKeyDown}
698
1366
  @click=${this.onClick}
@@ -700,7 +1368,13 @@ export class Calendar extends CalendarBase {
700
1368
  <div role="row" class="weekdays" part="weekdays">
701
1369
  ${short.map((name, index) => html`<span role="columnheader" class="weekday" aria-label=${long[index]}>${name}</span>`)}
702
1370
  </div>
703
- ${weeks.map(week => html`<div role="row" class="week" part="week">${week.map((day, column) => this.renderDay(day, column))}</div>`)}
1371
+ ${weeks.map((week, row) => html`<div role="row" class="week" part="week">${week.map((day, column) => this.renderDay(day, inView(day), tabDay, this.compact ? undefined : {
1372
+ // A full month names its days inside the first week's boxes, at their start, today's weekday in today's red.
1373
+ weekday: row === 0 ? inside[column] : undefined,
1374
+ today: row === 0 && todayColumn === column,
1375
+ // The week's number on its first day, counted from the week's middle so a week from Sunday takes its Monday's.
1376
+ week: this.weekNumbers && column === 0 && this.squaresPerDay >= 3 && week.some(drawn) ? isoWeek(addDays(day, 3)) : undefined,
1377
+ }))}</div>`)}
704
1378
  </div>`}
705
1379
  ${this.renderClear()}
706
1380
  </div>`;
@@ -779,7 +1453,7 @@ export class Calendar extends CalendarBase {
779
1453
  month.renderRoot.querySelector<HTMLElement>('[data-day][tabindex="0"]')?.focus({ preventScroll: true });
780
1454
  }
781
1455
 
782
- /** Below the field, half a square from it, or above when there is more room there; held inside the screen. */
1456
+ /** Directly against the field, or above when there is more room there; held inside the screen. */
783
1457
  private place = () => {
784
1458
  const panel = this.panel, trigger = this.trigger;
785
1459
  if (!this.shown || !panel || !trigger) return;
@@ -789,7 +1463,7 @@ export class Calendar extends CalendarBase {
789
1463
  const left = viewport?.offsetLeft ?? 0, top = viewport?.offsetTop ?? 0;
790
1464
  const width = viewport?.width ?? view.innerWidth, height = viewport?.height ?? view.innerHeight;
791
1465
  const box = panel.getBoundingClientRect();
792
- const gap = (parseFloat(getComputedStyle(panel).paddingTop) || 9) + 1;
1466
+ const gap = 0;
793
1467
  // The face is one control high at the foot of its square: measure from that square.
794
1468
  const square = Math.max(rect.height, gap * 2);
795
1469
  const foot = rect.bottom, head = rect.bottom - square;