@editora/ui-core 0.1.24 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/README.md +339 -5
  2. package/dist/accordion.cjs.js +13 -12
  3. package/dist/accordion.esm.js +13 -12
  4. package/dist/alert-dialog.cjs.js +76 -45
  5. package/dist/alert-dialog.esm.js +179 -135
  6. package/dist/alert.cjs.js +41 -32
  7. package/dist/alert.esm.js +79 -70
  8. package/dist/animated-beam.cjs.js +42 -50
  9. package/dist/animated-beam.esm.js +47 -55
  10. package/dist/animated-list.cjs.js +11 -27
  11. package/dist/animated-list.esm.js +12 -28
  12. package/dist/animated-text.cjs.js +4 -4
  13. package/dist/animated-text.esm.js +4 -4
  14. package/dist/app-header.cjs.js +5 -5
  15. package/dist/app-header.esm.js +6 -6
  16. package/dist/aspect-ratio.cjs.js +10 -12
  17. package/dist/aspect-ratio.esm.js +11 -13
  18. package/dist/avatar.cjs.js +13 -17
  19. package/dist/avatar.esm.js +13 -17
  20. package/dist/badge.cjs.js +27 -22
  21. package/dist/badge.esm.js +32 -27
  22. package/dist/block-controls.cjs.js +11 -12
  23. package/dist/block-controls.esm.js +8 -9
  24. package/dist/box.cjs.js +2 -3
  25. package/dist/box.esm.js +2 -3
  26. package/dist/breadcrumb.cjs.js +12 -18
  27. package/dist/breadcrumb.esm.js +11 -17
  28. package/dist/button.cjs.js +1 -1
  29. package/dist/button.esm.js +1 -1
  30. package/dist/{calendar-B3PUKHQm.mjs → calendar-DmxiZrR7.mjs} +126 -117
  31. package/dist/{calendar-D-mXMgqc.js → calendar-o273O28D.js} +53 -44
  32. package/dist/calendar.cjs.js +1 -1
  33. package/dist/calendar.esm.js +1 -1
  34. package/dist/card.cjs.js +6 -7
  35. package/dist/card.esm.js +5 -6
  36. package/dist/chart.cjs.js +52 -52
  37. package/dist/chart.esm.js +95 -95
  38. package/dist/checkbox.cjs.js +19 -15
  39. package/dist/checkbox.esm.js +19 -15
  40. package/dist/collapsible.cjs.js +7 -11
  41. package/dist/collapsible.esm.js +7 -11
  42. package/dist/color-picker.cjs.js +36 -17
  43. package/dist/color-picker.esm.js +132 -113
  44. package/dist/combobox.cjs.js +57 -54
  45. package/dist/combobox.esm.js +62 -58
  46. package/dist/command-palette.cjs.js +1 -0
  47. package/dist/command-palette.esm.js +1 -0
  48. package/dist/command.cjs.js +32 -14
  49. package/dist/command.esm.js +46 -28
  50. package/dist/components/date-time-utils.d.ts.map +1 -1
  51. package/dist/components/gantt-schedule.d.ts +79 -0
  52. package/dist/components/gantt-schedule.d.ts.map +1 -0
  53. package/dist/components/ui-accordion.d.ts.map +1 -1
  54. package/dist/components/ui-alert-dialog.d.ts +2 -0
  55. package/dist/components/ui-alert-dialog.d.ts.map +1 -1
  56. package/dist/components/ui-alert.d.ts.map +1 -1
  57. package/dist/components/ui-animated-beam.d.ts.map +1 -1
  58. package/dist/components/ui-animated-list.d.ts.map +1 -1
  59. package/dist/components/ui-aspect-ratio.d.ts.map +1 -1
  60. package/dist/components/ui-avatar.d.ts.map +1 -1
  61. package/dist/components/ui-badge.d.ts.map +1 -1
  62. package/dist/components/ui-block-controls.d.ts.map +1 -1
  63. package/dist/components/ui-box.d.ts.map +1 -1
  64. package/dist/components/ui-breadcrumb.d.ts.map +1 -1
  65. package/dist/components/ui-button.d.ts.map +1 -1
  66. package/dist/components/ui-calendar.d.ts.map +1 -1
  67. package/dist/components/ui-card.d.ts.map +1 -1
  68. package/dist/components/ui-checkbox.d.ts.map +1 -1
  69. package/dist/components/ui-collapsible.d.ts.map +1 -1
  70. package/dist/components/ui-color-picker.d.ts.map +1 -1
  71. package/dist/components/ui-combobox.d.ts.map +1 -1
  72. package/dist/components/ui-command-palette.d.ts.map +1 -1
  73. package/dist/components/ui-command.d.ts.map +1 -1
  74. package/dist/components/ui-container.d.ts.map +1 -1
  75. package/dist/components/ui-context-menu.d.ts.map +1 -1
  76. package/dist/components/ui-data-table.d.ts +7 -0
  77. package/dist/components/ui-data-table.d.ts.map +1 -1
  78. package/dist/components/ui-date-picker.d.ts.map +1 -1
  79. package/dist/components/ui-date-range-picker.d.ts.map +1 -1
  80. package/dist/components/ui-date-range-time-picker.d.ts.map +1 -1
  81. package/dist/components/ui-date-time-picker.d.ts.map +1 -1
  82. package/dist/components/ui-dialog.d.ts +2 -0
  83. package/dist/components/ui-dialog.d.ts.map +1 -1
  84. package/dist/components/ui-dock.d.ts.map +1 -1
  85. package/dist/components/ui-drawer.d.ts.map +1 -1
  86. package/dist/components/ui-dropdown.d.ts.map +1 -1
  87. package/dist/components/ui-empty-state.d.ts.map +1 -1
  88. package/dist/components/ui-field.d.ts.map +1 -1
  89. package/dist/components/ui-fieldset.d.ts.map +1 -1
  90. package/dist/components/ui-file-upload.d.ts.map +1 -1
  91. package/dist/components/ui-floating-toolbar.d.ts.map +1 -1
  92. package/dist/components/ui-form.d.ts.map +1 -1
  93. package/dist/components/ui-gantt.d.ts +186 -2
  94. package/dist/components/ui-gantt.d.ts.map +1 -1
  95. package/dist/components/ui-icon-cloud.d.ts.map +1 -1
  96. package/dist/components/ui-inline-edit.d.ts.map +1 -1
  97. package/dist/components/ui-input.d.ts.map +1 -1
  98. package/dist/components/ui-marquee.d.ts.map +1 -1
  99. package/dist/components/ui-menu.d.ts.map +1 -1
  100. package/dist/components/ui-menubar.d.ts.map +1 -1
  101. package/dist/components/ui-meter.d.ts.map +1 -1
  102. package/dist/components/ui-multi-select.d.ts.map +1 -1
  103. package/dist/components/ui-number-field.d.ts.map +1 -1
  104. package/dist/components/ui-orbiter.d.ts.map +1 -1
  105. package/dist/components/ui-pagination.d.ts.map +1 -1
  106. package/dist/components/ui-password-field.d.ts.map +1 -1
  107. package/dist/components/ui-pin-input.d.ts.map +1 -1
  108. package/dist/components/ui-popover.d.ts.map +1 -1
  109. package/dist/components/ui-progress.d.ts.map +1 -1
  110. package/dist/components/ui-radio-group.d.ts.map +1 -1
  111. package/dist/components/ui-radio.d.ts.map +1 -1
  112. package/dist/components/ui-rating.d.ts +1 -0
  113. package/dist/components/ui-rating.d.ts.map +1 -1
  114. package/dist/components/ui-scroll-area.d.ts.map +1 -1
  115. package/dist/components/ui-section.d.ts.map +1 -1
  116. package/dist/components/ui-select.d.ts.map +1 -1
  117. package/dist/components/ui-selection-popup.d.ts.map +1 -1
  118. package/dist/components/ui-slider.d.ts.map +1 -1
  119. package/dist/components/ui-sortable.d.ts.map +1 -1
  120. package/dist/components/ui-spinning-text.d.ts.map +1 -1
  121. package/dist/components/ui-split-button.d.ts.map +1 -1
  122. package/dist/components/ui-splitter.d.ts.map +1 -1
  123. package/dist/components/ui-stepper.d.ts.map +1 -1
  124. package/dist/components/ui-switch.d.ts.map +1 -1
  125. package/dist/components/ui-tabs.d.ts.map +1 -1
  126. package/dist/components/ui-tags-input.d.ts.map +1 -1
  127. package/dist/components/ui-textarea.d.ts.map +1 -1
  128. package/dist/components/ui-time-picker.d.ts.map +1 -1
  129. package/dist/components/ui-toggle-group.d.ts +2 -0
  130. package/dist/components/ui-toggle-group.d.ts.map +1 -1
  131. package/dist/components/ui-toggle.d.ts.map +1 -1
  132. package/dist/components/ui-toolbar.d.ts +2 -0
  133. package/dist/components/ui-toolbar.d.ts.map +1 -1
  134. package/dist/components/ui-tooltip.d.ts.map +1 -1
  135. package/dist/components/ui-transfer-list.d.ts.map +1 -1
  136. package/dist/components/ui-tree-item.d.ts.map +1 -1
  137. package/dist/components/ui-tree.d.ts.map +1 -1
  138. package/dist/components/ui-wizard.d.ts.map +1 -1
  139. package/dist/container.cjs.js +6 -12
  140. package/dist/container.esm.js +8 -14
  141. package/dist/context-menu.cjs.js +8 -8
  142. package/dist/context-menu.esm.js +42 -41
  143. package/dist/data-table.cjs.js +18 -15
  144. package/dist/data-table.esm.js +207 -187
  145. package/dist/date-field.cjs.js +8 -8
  146. package/dist/date-field.esm.js +7 -7
  147. package/dist/date-picker.cjs.js +27 -18
  148. package/dist/date-picker.esm.js +57 -48
  149. package/dist/date-range-picker.cjs.js +22 -17
  150. package/dist/date-range-picker.esm.js +31 -26
  151. package/dist/date-range-time-picker.cjs.js +26 -19
  152. package/dist/date-range-time-picker.esm.js +23 -16
  153. package/dist/date-time-picker.cjs.js +23 -16
  154. package/dist/date-time-picker.esm.js +88 -81
  155. package/dist/{date-time-utils-BTlxnz5j.mjs → date-time-utils-B4hAkt36.mjs} +75 -68
  156. package/dist/date-time-utils-DdigV4hs.js +1 -0
  157. package/dist/dialog.cjs.js +57 -41
  158. package/dist/dialog.esm.js +84 -51
  159. package/dist/dock.cjs.js +16 -30
  160. package/dist/dock.esm.js +26 -40
  161. package/dist/drawer.cjs.js +8 -12
  162. package/dist/drawer.esm.js +6 -10
  163. package/dist/dropdown.cjs.js +8 -6
  164. package/dist/dropdown.esm.js +33 -30
  165. package/dist/empty-state.cjs.js +17 -15
  166. package/dist/empty-state.esm.js +13 -11
  167. package/dist/field.cjs.js +22 -13
  168. package/dist/field.esm.js +54 -45
  169. package/dist/fieldset.cjs.js +18 -11
  170. package/dist/fieldset.esm.js +20 -13
  171. package/dist/file-upload.cjs.js +77 -35
  172. package/dist/file-upload.esm.js +152 -110
  173. package/dist/floating-toolbar.cjs.js +6 -7
  174. package/dist/floating-toolbar.esm.js +8 -9
  175. package/dist/form.cjs.js +20 -23
  176. package/dist/form.esm.js +20 -23
  177. package/dist/gantt.cjs.js +525 -110
  178. package/dist/gantt.esm.js +1882 -377
  179. package/dist/hover-card.cjs.js +7 -7
  180. package/dist/hover-card.esm.js +7 -7
  181. package/dist/icon-cloud.cjs.js +19 -36
  182. package/dist/icon-cloud.esm.js +41 -58
  183. package/dist/index.cjs.js +1 -1
  184. package/dist/index.d.ts +2 -0
  185. package/dist/index.d.ts.map +1 -1
  186. package/dist/index.esm.js +108 -104
  187. package/dist/inline-edit.cjs.js +47 -19
  188. package/dist/inline-edit.esm.js +66 -38
  189. package/dist/input.cjs.js +44 -37
  190. package/dist/input.esm.js +59 -52
  191. package/dist/layout.cjs.js +3 -3
  192. package/dist/layout.esm.js +3 -3
  193. package/dist/marquee.cjs.js +7 -10
  194. package/dist/marquee.esm.js +7 -10
  195. package/dist/menu.cjs.js +8 -24
  196. package/dist/menu.esm.js +52 -72
  197. package/dist/menubar.cjs.js +9 -31
  198. package/dist/menubar.esm.js +127 -153
  199. package/dist/meter.cjs.js +4 -9
  200. package/dist/meter.esm.js +6 -11
  201. package/dist/multi-select.cjs.js +48 -35
  202. package/dist/multi-select.esm.js +67 -53
  203. package/dist/navigation-menu.cjs.js +10 -10
  204. package/dist/navigation-menu.esm.js +33 -33
  205. package/dist/number-field.cjs.js +27 -16
  206. package/dist/number-field.esm.js +36 -25
  207. package/dist/odometer.cjs.js +5 -5
  208. package/dist/odometer.esm.js +3 -3
  209. package/dist/orbiter.cjs.js +11 -28
  210. package/dist/orbiter.esm.js +28 -45
  211. package/dist/overlay-motion-B56x1GoY.js +49 -0
  212. package/dist/overlay-motion-BX3dPLay.mjs +120 -0
  213. package/dist/pagination.cjs.js +28 -25
  214. package/dist/pagination.esm.js +54 -51
  215. package/dist/password-field.cjs.js +38 -33
  216. package/dist/password-field.esm.js +62 -57
  217. package/dist/pin-input.cjs.js +17 -13
  218. package/dist/pin-input.esm.js +23 -19
  219. package/dist/plugin-panel.cjs.js +1 -1
  220. package/dist/plugin-panel.esm.js +1 -1
  221. package/dist/popover.cjs.js +16 -28
  222. package/dist/popover.esm.js +29 -45
  223. package/dist/portal-DeaM1tYY.mjs +121 -0
  224. package/dist/portal-XbYR3m_q.js +1 -0
  225. package/dist/portal.d.ts +3 -1
  226. package/dist/portal.d.ts.map +1 -1
  227. package/dist/{positioner-D0VGxtYU.mjs → positioner-BE8Nbho2.mjs} +5 -3
  228. package/dist/{positioner-D_fqyx_j.js → positioner-DZ1FW6A9.js} +1 -1
  229. package/dist/positioner.cjs.js +1 -1
  230. package/dist/positioner.esm.js +1 -1
  231. package/dist/primitives/overlay-motion.d.ts +47 -0
  232. package/dist/primitives/overlay-motion.d.ts.map +1 -0
  233. package/dist/primitives/positioner.d.ts.map +1 -1
  234. package/dist/progress.cjs.js +11 -16
  235. package/dist/progress.esm.js +37 -42
  236. package/dist/quick-actions.cjs.js +13 -13
  237. package/dist/quick-actions.esm.js +11 -11
  238. package/dist/radio-group.cjs.js +50 -26
  239. package/dist/radio-group.esm.js +53 -29
  240. package/dist/radio.cjs.js +15 -12
  241. package/dist/radio.esm.js +15 -12
  242. package/dist/rating.cjs.js +11 -15
  243. package/dist/rating.esm.js +48 -50
  244. package/dist/{runtime-CFnK53iC.mjs → runtime-CQM6wZOc.mjs} +498 -514
  245. package/dist/runtime-DxCl0A5q.js +5 -0
  246. package/dist/runtime.cjs.js +1 -1
  247. package/dist/runtime.d.ts +3 -2
  248. package/dist/runtime.d.ts.map +1 -1
  249. package/dist/runtime.esm.js +36 -32
  250. package/dist/scroll-area.cjs.js +3 -4
  251. package/dist/scroll-area.esm.js +3 -4
  252. package/dist/section.cjs.js +2 -4
  253. package/dist/section.esm.js +2 -4
  254. package/dist/select.cjs.js +40 -73
  255. package/dist/select.esm.js +55 -87
  256. package/dist/selection-popup.cjs.js +3 -4
  257. package/dist/selection-popup.esm.js +3 -4
  258. package/dist/semantic-tokens.d.ts +17 -0
  259. package/dist/semantic-tokens.d.ts.map +1 -0
  260. package/dist/sidebar.cjs.js +22 -22
  261. package/dist/sidebar.esm.js +25 -25
  262. package/dist/skeleton.cjs.js +2 -2
  263. package/dist/skeleton.esm.js +2 -2
  264. package/dist/slider.cjs.js +22 -26
  265. package/dist/slider.esm.js +25 -29
  266. package/dist/sortable.cjs.js +4 -5
  267. package/dist/sortable.esm.js +4 -5
  268. package/dist/spinning-text.cjs.js +4 -13
  269. package/dist/spinning-text.esm.js +4 -13
  270. package/dist/split-button.cjs.js +5 -5
  271. package/dist/split-button.esm.js +15 -14
  272. package/dist/splitter.cjs.js +52 -10
  273. package/dist/splitter.esm.js +55 -13
  274. package/dist/stepper.cjs.js +31 -65
  275. package/dist/stepper.esm.js +32 -66
  276. package/dist/switch.cjs.js +20 -22
  277. package/dist/switch.esm.js +20 -22
  278. package/dist/table.cjs.js +5 -5
  279. package/dist/table.esm.js +20 -20
  280. package/dist/tabs.cjs.js +91 -21
  281. package/dist/tabs.esm.js +182 -112
  282. package/dist/tags-input.cjs.js +41 -15
  283. package/dist/tags-input.esm.js +73 -47
  284. package/dist/textarea.cjs.js +32 -33
  285. package/dist/textarea.esm.js +38 -39
  286. package/dist/theme.d.ts +25 -1
  287. package/dist/theme.d.ts.map +1 -1
  288. package/dist/time-field.cjs.js +7 -7
  289. package/dist/time-field.esm.js +6 -6
  290. package/dist/time-picker.cjs.js +16 -13
  291. package/dist/time-picker.esm.js +27 -24
  292. package/dist/timeline.cjs.js +10 -10
  293. package/dist/timeline.esm.js +7 -7
  294. package/dist/toggle-group.cjs.js +13 -13
  295. package/dist/toggle-group.esm.js +66 -61
  296. package/dist/toggle.cjs.js +52 -34
  297. package/dist/toggle.esm.js +80 -62
  298. package/dist/toolbar.cjs.js +14 -14
  299. package/dist/toolbar.esm.js +41 -33
  300. package/dist/tooltip.cjs.js +3 -3
  301. package/dist/tooltip.esm.js +39 -33
  302. package/dist/transfer-list.cjs.js +28 -29
  303. package/dist/transfer-list.esm.js +28 -29
  304. package/dist/{tree-B_oQput6.mjs → tree-33fVNnaf.mjs} +6 -5
  305. package/dist/{tree-SivHxcAy.js → tree-Dc02MChE.js} +6 -5
  306. package/dist/tree-item.cjs.js +9 -8
  307. package/dist/tree-item.esm.js +13 -12
  308. package/dist/tree.cjs.js +1 -1
  309. package/dist/tree.esm.js +1 -1
  310. package/dist/{ui-button-Co8Sid6t.mjs → ui-button-C3OmI7Sn.mjs} +152 -154
  311. package/dist/{ui-button-BPrzJScZ.js → ui-button-CnLwXBnx.js} +107 -109
  312. package/dist/wizard.cjs.js +39 -36
  313. package/dist/wizard.esm.js +39 -36
  314. package/package.json +1 -1
  315. package/dist/date-time-utils-y3AvNvGe.js +0 -1
  316. package/dist/portal-DgpQ3Jo1.js +0 -1
  317. package/dist/portal-bR42gHvG.mjs +0 -118
  318. package/dist/runtime-DwE-tizc.js +0 -1
package/dist/gantt.cjs.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const At=require("./ElementBase-DxbvhLJs.js"),I=1440*60*1e3,y=42,V=62,J=376,N=28,Lt=15,vt=Lt*Math.SQRT2/2,gt={day:36,week:13,month:4.4,quarter:2.2,year:1.15},ht=`
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const Ee=require("./ElementBase-DxbvhLJs.js");function H(n,t){const e=new Date(n);return e.setDate(e.getDate()+t),e.setHours(0,0,0,0),e.getTime()}function wt(n,t){return Math.round((t-n)/864e5)}function le(n){const t=new Set(n.map(r=>r.id)),e=new Map;for(const r of n){if(!r.parent||!t.has(r.parent)||r.parent===r.id)continue;const i=e.get(r.parent)||[];i.push(r),e.set(r.parent,i)}return e}function de(n,t){const e=le(n),r=[],i=new Set([t]),a=[t];for(;a.length;)for(const s of e.get(a.shift())||[])i.has(s.id)||(i.add(s.id),r.push(s),a.push(s.id));return r}function Te(n){const t=le(n),e=new Map,r=new Set,i=a=>{const s=e.get(a.id);if(s)return s;const o={start:a.start,end:a.end,progress:a.progress},c=t.get(a.id);if(!c?.length||r.has(a.id))return o;r.add(a.id);let h=1/0,d=-1/0,g=0,u=0;for(const m of c){const p=i(m);if(h=Math.min(h,p.start),d=Math.max(d,p.end),p.progress!=null){const k=Math.max(1,wt(p.start,p.end));g+=k,u+=p.progress*k}}r.delete(a.id);const b={start:h,end:d,progress:g?u/g:void 0};return e.set(a.id,b),b};for(const a of n)i(a);return e}function Bt(n,t){const e=n.type==="e2s"||n.type==="e2e"?t.end:t.start;return{side:n.type==="e2s"||n.type==="s2s"?"start":"end",min:H(e,n.lag)}}function Ae(n,t,e){const r=Bt(n,t);return(r.side==="start"?e.start:e.end)>=r.min}function Le(n,t){const e=new Map(n.map(i=>[i.id,i])),r=new Set;for(const i of t){const a=e.get(i.source),s=e.get(i.target);a&&s&&!Ae(i,a,s)&&r.add(i.id)}return r}function Ie(n,t,e,r=!1){const i=new Map(n.map(u=>[u.id,{start:u.start,end:u.end}]));for(const[u,b]of e)i.has(u)&&i.set(u,{...b});const a=new Map(n.map(u=>[u.id,u])),s=new Map;for(const u of t){const b=s.get(u.source)||[];b.push(u),s.set(u.source,b)}const o=new Set,c=new Map,h=[...e.keys()],d=(u,b)=>{const m=i.get(u);m&&(i.set(u,{start:H(m.start,b),end:H(m.end,b)}),o.add(u))};for(;h.length;){const u=h.shift(),b=i.get(u);if(b)for(const m of s.get(u)||[]){const p=a.get(m.target),k=i.get(m.target);if(!p||!k||p.readonly)continue;const y=Bt(m,b),w=y.side==="start"?k.start:k.end;if(w>=y.min)continue;const x=(c.get(m.target)||0)+1;if(x>n.length)continue;c.set(m.target,x);const M=wt(w,y.min);if(d(m.target,M),h.push(m.target),r)for(const T of de(n,m.target))T.readonly||(d(T.id,M),h.push(T.id))}}const g=[];for(const u of o){const b=i.get(u),m=e.get(u);(!m||m.start!==b.start||m.end!==b.end)&&g.push({id:u,...b})}return g}function ze(n,t){const e=new Set(n.map(p=>p.parent).filter(p=>!!p)),r=new Map(n.filter(p=>!e.has(p.id)).map(p=>[p.id,p])),i=t.filter(p=>r.has(p.source)&&r.has(p.target)&&p.source!==p.target);if(!i.length)return new Set;const a=p=>wt(p.start,p.end),s=Math.max(...[...r.values()].map(p=>p.end)),o=new Map,c=new Map;for(const p of i)o.set(p.source,[...o.get(p.source)||[],p]),c.set(p.target,[...c.get(p.target)||[],p]);const h=new Map([...r.keys()].map(p=>[p,s])),d=new Map([...r.keys()].map(p=>[p,(o.get(p)||[]).length])),g=[...r.keys()].filter(p=>d.get(p)===0),u=new Set;for(;g.length;){const p=g.shift();u.add(p);const k=r.get(p),y=h.get(p),w=H(y,-a(k));for(const x of c.get(p)||[]){const M=r.get(x.source),T=-x.lag,z=x.type==="e2s"?H(w,T):x.type==="s2s"?H(H(w,T),a(M)):x.type==="e2e"?H(y,T):H(H(y,T),a(M));h.set(x.source,Math.min(h.get(x.source),z));const U=d.get(x.source)-1;d.set(x.source,U),U===0&&g.push(x.source)}}const b=new Set;for(const p of i){const k=r.get(p.source),y=r.get(p.target),w=Bt(p,k);(w.side==="start"?y.start:y.end)===w.min&&b.add(p.target)}const m=new Set;for(const p of u){const k=r.get(p),y=(o.get(p)||[]).length+(c.get(p)||[]).length>0,w=wt(k.end,h.get(p));y&&w<=0&&(!(c.get(p)||[]).length||b.has(p))&&m.add(p)}return m}const D=1440*60*1e3,S=42,N=62,Tt=376,ce="minmax(170px, 1fr) 82px 80px 44px",Ce=640,De=148,Fe=2,vt=28,Re=15,he=Re*Math.SQRT2/2,Jt={day:36,week:13,month:4.4,quarter:2.2,year:1.15},Gt=`
2
2
  :host {
3
3
  --ui-gantt-bg: color-mix(in srgb, var(--ui-color-surface, #ffffff) 96%, transparent);
4
4
  --ui-gantt-panel: var(--ui-color-surface, #ffffff);
@@ -21,10 +21,11 @@
21
21
  }
22
22
 
23
23
  .frame {
24
+ container: ui-gantt / inline-size;
24
25
  border: 1px solid var(--ui-gantt-border);
25
- border-radius: 12px;
26
+ border-radius: calc(var(--ui-radius, 6px) + 2px);
26
27
  background: var(--ui-gantt-bg);
27
- box-shadow: 0 14px 34px rgba(15, 23, 42, 0.08);
28
+ box-shadow: none;
28
29
  overflow: hidden;
29
30
  }
30
31
 
@@ -60,11 +61,13 @@
60
61
 
61
62
  .control,
62
63
  .select,
63
- .zoom-button {
64
+ .zoom-button,
65
+ .today-button,
66
+ .add-button {
64
67
  border: 1px solid var(--ui-gantt-border);
65
68
  background: var(--ui-gantt-panel);
66
69
  color: var(--ui-gantt-text);
67
- border-radius: 7px;
70
+ border-radius: var(--ui-control-radius-2, var(--ui-radius, 6px));
68
71
  min-block-size: 30px;
69
72
  font: inherit;
70
73
  font-size: 12px;
@@ -80,15 +83,22 @@
80
83
  min-inline-size: 118px;
81
84
  }
82
85
 
83
- .zoom-button {
86
+ .zoom-button,
87
+ .today-button,
88
+ .add-button {
84
89
  padding: 0 9px;
85
90
  cursor: pointer;
86
91
  }
87
92
 
93
+ .today-button:disabled {
94
+ opacity: 0.45;
95
+ cursor: default;
96
+ }
97
+
88
98
  .zoom-button[aria-pressed="true"] {
89
- border-color: color-mix(in srgb, var(--ui-gantt-accent) 46%, var(--ui-gantt-border));
90
- background: color-mix(in srgb, var(--ui-gantt-accent) 10%, var(--ui-gantt-panel));
91
- color: color-mix(in srgb, var(--ui-gantt-accent) 82%, var(--ui-gantt-text));
99
+ border-color: transparent;
100
+ background: var(--ui-color-accent-fill, color-mix(in srgb, var(--ui-gantt-accent) 10%, var(--ui-gantt-panel)));
101
+ color: var(--ui-color-text-strong, var(--ui-gantt-text));
92
102
  }
93
103
 
94
104
  .viewport {
@@ -96,19 +106,67 @@
96
106
  max-block-size: var(--ui-gantt-max-height, 620px);
97
107
  }
98
108
 
109
+ /* fill: the chart takes the height of its container (which needs one): the toolbar keeps its height and the
110
+ scroll area takes the rest, however tall. */
111
+ :host([fill]) {
112
+ block-size: 100%;
113
+ }
114
+
115
+ :host([fill]) .frame {
116
+ display: flex;
117
+ flex-direction: column;
118
+ block-size: 100%;
119
+ }
120
+
121
+ :host([fill]) .toolbar {
122
+ flex: none;
123
+ }
124
+
125
+ :host([fill]) .viewport {
126
+ flex: 1 1 0;
127
+ min-block-size: 0;
128
+ max-block-size: none;
129
+ }
130
+
99
131
  .surface {
132
+ --gantt-grid-w: ${Tt}px;
133
+ --gantt-cols: ${ce};
100
134
  display: grid;
101
- grid-template-columns: ${J}px minmax(640px, 1fr);
135
+ grid-template-columns: var(--gantt-grid-w) minmax(640px, 1fr);
102
136
  min-inline-size: 100%;
103
137
  }
104
138
 
139
+ /* The task grid is sticky, so at 376px it covers a phone-sized chart completely and no bar can be
140
+ reached. In a narrow host keep only the task name column and give the timeline the room. */
141
+ @container ui-gantt (max-width: 640px) {
142
+ .surface {
143
+ --gantt-grid-w: 148px;
144
+ --gantt-cols: minmax(0, 1fr);
145
+ }
146
+
147
+ .splitter-rail {
148
+ display: none;
149
+ }
150
+
151
+ /* !important: the sortable header wrappers carry an inline display: contents. */
152
+ .grid-head > :nth-child(n + 2),
153
+ .grid-cell:nth-child(n + 2) {
154
+ display: none !important;
155
+ }
156
+
157
+ .grid-cell.task-name {
158
+ padding-inline-end: 6px;
159
+ }
160
+ }
161
+
105
162
  .grid-head,
106
163
  .timeline-head {
107
164
  position: sticky;
108
165
  top: 0;
109
166
  z-index: 4;
110
167
  min-block-size: 62px;
111
- background: color-mix(in srgb, var(--ui-gantt-panel) 96%, transparent);
168
+ /* Opaque: the rows scroll underneath, and at 96% they showed through as a ghost of the text. */
169
+ background: var(--ui-gantt-panel);
112
170
  border-bottom: 1px solid var(--ui-gantt-border);
113
171
  }
114
172
 
@@ -127,7 +185,7 @@
127
185
  left: 0;
128
186
  z-index: 5;
129
187
  display: grid;
130
- grid-template-columns: minmax(170px, 1fr) 82px 80px 44px;
188
+ grid-template-columns: var(--gantt-cols);
131
189
  border-right: 1px solid var(--ui-gantt-border);
132
190
  }
133
191
 
@@ -183,15 +241,79 @@
183
241
  min-block-size: 62px;
184
242
  }
185
243
 
244
+ .band {
245
+ position: absolute;
246
+ inset-inline: 0;
247
+ }
248
+
249
+ .band.top {
250
+ inset-block-start: 0;
251
+ block-size: 26px;
252
+ border-bottom: 1px solid var(--ui-gantt-grid);
253
+ }
254
+
255
+ .band.bottom {
256
+ inset-block-start: 26px;
257
+ block-size: 36px;
258
+ }
259
+
260
+ .scale[data-zoom="year"] .band.bottom {
261
+ inset-block-start: 0;
262
+ block-size: 62px;
263
+ }
264
+
265
+ .band-cell,
186
266
  .tick {
187
267
  position: absolute;
188
268
  inset-block: 0;
269
+ display: flex;
270
+ align-items: center;
271
+ overflow: hidden;
189
272
  border-left: 1px solid var(--ui-gantt-grid);
190
- padding: 9px 8px;
273
+ padding: 0 8px;
191
274
  color: var(--ui-gantt-muted);
192
275
  font-size: 11px;
193
276
  font-weight: 650;
194
277
  white-space: nowrap;
278
+ text-overflow: ellipsis;
279
+ }
280
+
281
+ .band-cell {
282
+ color: var(--ui-gantt-text);
283
+ font-weight: 700;
284
+ }
285
+
286
+ /* Labels sit at the top of their row so the today pill has the bottom of it to itself. */
287
+ .band.bottom .tick {
288
+ align-items: flex-start;
289
+ padding-block-start: 6px;
290
+ }
291
+
292
+ .scale[data-zoom="year"] .tick {
293
+ padding-block-start: 9px;
294
+ }
295
+
296
+ .tick.day {
297
+ flex-direction: column;
298
+ justify-content: flex-start;
299
+ gap: 1px;
300
+ padding: 3px 0 0;
301
+ line-height: 1.15;
302
+ }
303
+
304
+ .tick .dow {
305
+ font-size: 9px;
306
+ font-weight: 600;
307
+ opacity: 0.8;
308
+ }
309
+
310
+ .tick .num {
311
+ font-variant-numeric: tabular-nums;
312
+ }
313
+
314
+ .tick.today-cell {
315
+ color: var(--ui-gantt-accent);
316
+ background: color-mix(in srgb, var(--ui-gantt-accent) 9%, transparent);
195
317
  }
196
318
 
197
319
  .grid-body {
@@ -204,24 +326,165 @@
204
326
 
205
327
  .timeline-body {
206
328
  position: relative;
329
+ /* grid lines can run a scrollbar's width past the track; clip them, and keep y visible for drag tips */
330
+ overflow-x: clip;
207
331
  background:
208
332
  linear-gradient(to right, var(--ui-gantt-grid) 1px, transparent 1px) 0 0 / var(--day-width) 100%,
209
333
  color-mix(in srgb, var(--ui-gantt-panel) 98%, transparent);
210
334
  }
211
335
 
336
+ /* The task list can be resized: a handle on its right edge, in the header and down the body. They are grid items
337
+ of their own, in the cells of the header and the body, so the sticky grid underneath stays a plain treegrid. */
338
+ .splitter-rail {
339
+ position: sticky;
340
+ left: 0;
341
+ grid-column: 1;
342
+ z-index: 4;
343
+ pointer-events: none;
344
+ }
345
+
346
+ .splitter-rail.head {
347
+ grid-row: 1;
348
+ top: 0;
349
+ z-index: 6;
350
+ }
351
+
352
+ .splitter-rail.body {
353
+ grid-row: 2;
354
+ }
355
+
356
+ .splitter {
357
+ position: absolute;
358
+ inset-block: 0;
359
+ inset-inline-end: -4px;
360
+ inline-size: 8px;
361
+ cursor: col-resize;
362
+ pointer-events: auto;
363
+ touch-action: none;
364
+ outline: 0;
365
+ }
366
+
367
+ .splitter::after {
368
+ content: "";
369
+ position: absolute;
370
+ inset-block: 0;
371
+ inset-inline-start: 3px;
372
+ inline-size: 2px;
373
+ background: transparent;
374
+ transition: background 120ms ease;
375
+ }
376
+
377
+ .splitter:hover::after,
378
+ .splitter.dragging::after,
379
+ .splitter:focus-visible::after {
380
+ background: var(--ui-gantt-accent);
381
+ }
382
+
383
+ .timeline-body[data-zoom="month"],
384
+ .timeline-body[data-zoom="quarter"],
385
+ .timeline-body[data-zoom="year"] {
386
+ background: color-mix(in srgb, var(--ui-gantt-panel) 98%, transparent);
387
+ }
388
+
389
+ /* Non-working days: a tint behind the rows, a warmer one for a holiday. */
390
+ .off-day {
391
+ position: absolute;
392
+ inset-block: 0;
393
+ background: color-mix(in srgb, var(--ui-gantt-muted) 11%, transparent);
394
+ pointer-events: none;
395
+ }
396
+
397
+ .off-day.holiday {
398
+ background: color-mix(in srgb, var(--ui-color-warning, #d97706) 15%, transparent);
399
+ }
400
+
401
+ .tick.off {
402
+ background: color-mix(in srgb, var(--ui-gantt-muted) 9%, transparent);
403
+ }
404
+
405
+ /* The dots beside a bar that start a link (the linkable attribute), shown with the row's hover or focus. */
406
+ .connector {
407
+ position: absolute;
408
+ top: 15px;
409
+ inline-size: 12px;
410
+ block-size: 12px;
411
+ border: 2px solid var(--ui-gantt-accent);
412
+ border-radius: 50%;
413
+ background: var(--ui-gantt-panel);
414
+ cursor: crosshair;
415
+ opacity: 0;
416
+ z-index: 3;
417
+ touch-action: none;
418
+ transition: opacity 120ms ease;
419
+ }
420
+
421
+ .timeline-row:hover .connector,
422
+ .timeline-row:focus-within .connector,
423
+ .frame[data-linking] .connector {
424
+ opacity: 1;
425
+ }
426
+
427
+ .link-draft {
428
+ fill: none;
429
+ stroke: var(--ui-gantt-accent);
430
+ stroke-width: 2;
431
+ stroke-dasharray: 5 3;
432
+ stroke-linecap: round;
433
+ pointer-events: none;
434
+ }
435
+
436
+ .bar.link-target {
437
+ outline: 2px solid var(--ui-gantt-accent);
438
+ outline-offset: 2px;
439
+ }
440
+
441
+ .bar.link-target[data-link-side="start"] {
442
+ box-shadow: inset 7px 0 0 var(--ui-gantt-accent);
443
+ }
444
+
445
+ .bar.link-target[data-link-side="end"] {
446
+ box-shadow: inset -7px 0 0 var(--ui-gantt-accent);
447
+ }
448
+
449
+ .links path.selected:not(.link-hit) {
450
+ stroke: var(--ui-gantt-accent);
451
+ stroke-width: 2.4;
452
+ }
453
+
454
+ .links path.link-hit {
455
+ outline: 0;
456
+ }
457
+
458
+ .unit-line {
459
+ position: absolute;
460
+ inset-block: 0;
461
+ inline-size: 1px;
462
+ background: color-mix(in srgb, var(--ui-gantt-border) 90%, transparent);
463
+ pointer-events: none;
464
+ }
465
+
212
466
  .grid-row,
213
467
  .timeline-row {
214
- block-size: ${y}px;
468
+ block-size: ${S}px;
215
469
  border-bottom: 1px solid color-mix(in srgb, var(--ui-gantt-border) 56%, transparent);
216
470
  }
217
471
 
218
472
  .grid-row {
219
473
  display: grid;
220
- grid-template-columns: minmax(170px, 1fr) 82px 80px 44px;
474
+ grid-template-columns: var(--gantt-cols);
221
475
  color: var(--ui-gantt-text);
222
476
  font-size: 12px;
223
477
  }
224
478
 
479
+ .grid-row {
480
+ outline: 0;
481
+ }
482
+
483
+ .grid-row:focus-visible {
484
+ outline: 2px solid var(--ui-gantt-accent);
485
+ outline-offset: -2px;
486
+ }
487
+
225
488
  .grid-row.selected,
226
489
  .timeline-row.selected {
227
490
  background: var(--ui-gantt-selected);
@@ -251,6 +514,20 @@
251
514
  color: var(--ui-gantt-accent);
252
515
  }
253
516
 
517
+ .rename {
518
+ flex: 1 1 auto;
519
+ min-inline-size: 0;
520
+ block-size: 26px;
521
+ padding: 0 6px;
522
+ border: 1px solid var(--ui-gantt-accent);
523
+ border-radius: 6px;
524
+ background: var(--ui-gantt-panel);
525
+ color: var(--ui-gantt-text);
526
+ font: inherit;
527
+ font-weight: 650;
528
+ outline: 0;
529
+ }
530
+
254
531
  .name-text {
255
532
  overflow: hidden;
256
533
  text-overflow: ellipsis;
@@ -321,13 +598,15 @@
321
598
  overflow: visible;
322
599
  }
323
600
 
324
- .bar.split .progress {
601
+ /* A split bar shows the progress of each part, inside the part, and not one fill across the gaps. */
602
+ .bar.split > .progress {
325
603
  display: none;
326
604
  }
327
605
 
328
606
  .split-segment {
329
607
  position: absolute;
330
608
  inset-block: 0;
609
+ overflow: hidden;
331
610
  border-radius: 4px;
332
611
  background:
333
612
  linear-gradient(180deg, color-mix(in srgb, #ffffff 22%, transparent), transparent 42%),
@@ -401,13 +680,33 @@
401
680
  display: none;
402
681
  }
403
682
 
683
+ /* The done part of a bar: a solid, darker shade of the bar's tone with a light edge where it stops, so
684
+ the amount is readable from the bar itself and not only from the % column. */
404
685
  .progress {
405
686
  position: absolute;
406
687
  inset-block: 0;
407
688
  inset-inline-start: 0;
408
- background: linear-gradient(90deg, color-mix(in srgb, #000 22%, transparent), transparent);
409
- opacity: 0.3;
410
689
  inline-size: var(--progress, 0%);
690
+ background:
691
+ linear-gradient(180deg, color-mix(in srgb, #ffffff 16%, transparent), transparent 46%),
692
+ color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 58%, #0b1220);
693
+ box-shadow: inset -2px 0 0 color-mix(in srgb, #ffffff 62%, transparent);
694
+ }
695
+
696
+ .bar.complete .progress,
697
+ .progress.full {
698
+ box-shadow: none;
699
+ }
700
+
701
+ .bar.summary .progress {
702
+ background: color-mix(in srgb, #0b1220 58%, transparent);
703
+ }
704
+
705
+ :host([bar-variant="soft"]) .bar.task .progress {
706
+ background:
707
+ linear-gradient(180deg, color-mix(in srgb, #ffffff 24%, transparent), transparent 46%),
708
+ color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 62%, var(--ui-gantt-panel));
709
+ box-shadow: inset -2px 0 0 color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 85%, transparent);
411
710
  }
412
711
 
413
712
  .handle {
@@ -452,28 +751,75 @@
452
751
  opacity: 1;
453
752
  }
454
753
 
455
- .drag-tip {
754
+ /* A finger needs the 24px minimum target size, and a touch screen has no hover to reveal the handles:
755
+ task bars grow from 18 to 24px tall (centred on the same line, so links and baselines still meet them),
756
+ the resize handles from 14 to 24px wide and always show their grip. A very short bar keeps a middle to
757
+ grab by giving each handle at most 35% of it. */
758
+ @media (pointer: coarse) {
759
+ .bar.task {
760
+ block-size: 24px;
761
+ top: 9px;
762
+ }
763
+
764
+ .handle {
765
+ inline-size: min(24px, 35%);
766
+ opacity: 1;
767
+ }
768
+
769
+ .handle.start::after {
770
+ inset-inline-start: 8px;
771
+ }
772
+
773
+ .handle.end::after {
774
+ inset-inline-end: 8px;
775
+ }
776
+
777
+ .connector {
778
+ opacity: 1;
779
+ inline-size: 20px;
780
+ block-size: 20px;
781
+ top: 11px;
782
+ }
783
+ }
784
+
785
+ /* One tooltip for the whole chart, outside the bars (which clip their children), placed by script. It
786
+ repeats the bar's accessible name, so it is hidden from assistive technology. */
787
+ .bar-tip {
456
788
  position: absolute;
457
- z-index: 6;
458
- inset-block-start: -28px;
459
- inset-inline-start: 50%;
460
- transform: translateX(-50%);
461
- padding: 4px 7px;
462
- border-radius: 6px;
789
+ inset-block-start: 0;
790
+ inset-inline-start: 0;
791
+ z-index: 7;
792
+ max-inline-size: 280px;
793
+ padding: 6px 9px;
794
+ border-radius: 8px;
463
795
  background: #0f172a;
464
796
  color: #f8fafc;
465
797
  font-size: 11px;
466
- font-weight: 700;
467
- white-space: nowrap;
798
+ line-height: 1.4;
799
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.28);
468
800
  pointer-events: none;
469
801
  opacity: 0;
802
+ visibility: hidden;
803
+ transition: opacity 90ms ease;
470
804
  }
471
805
 
472
- .bar.dragging .drag-tip {
806
+ .bar-tip[data-open] {
473
807
  opacity: 1;
808
+ visibility: visible;
809
+ }
810
+
811
+ .bar-tip strong {
812
+ display: block;
813
+ font-weight: 750;
474
814
  }
475
815
 
476
- :host([bar-variant="soft"]) .bar.task {
816
+ .bar-tip span {
817
+ display: block;
818
+ opacity: 0.88;
819
+ }
820
+
821
+ :host([bar-variant="soft"]) .bar.task,
822
+ :host([bar-variant="soft"]) .split-segment {
477
823
  background:
478
824
  linear-gradient(180deg, color-mix(in srgb, #ffffff 38%, transparent), transparent 46%),
479
825
  color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 22%, var(--ui-gantt-panel));
@@ -492,7 +838,8 @@
492
838
  0 7px 16px color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 16%, transparent);
493
839
  }
494
840
 
495
- :host([bar-variant="striped"]) .bar.task {
841
+ :host([bar-variant="striped"]) .bar.task,
842
+ :host([bar-variant="striped"]) .split-segment {
496
843
  background:
497
844
  repeating-linear-gradient(135deg, color-mix(in srgb, #ffffff 24%, transparent) 0 7px, transparent 7px 14px),
498
845
  var(--tone, var(--ui-gantt-accent));
@@ -504,7 +851,8 @@
504
851
  var(--tone, var(--ui-gantt-accent));
505
852
  }
506
853
 
507
- :host([bar-variant="outline"]) .bar.task {
854
+ :host([bar-variant="outline"]) .bar.task,
855
+ :host([bar-variant="outline"]) .split-segment {
508
856
  background: color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 8%, var(--ui-gantt-panel));
509
857
  box-shadow:
510
858
  inset 0 0 0 1.5px color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 72%, transparent),
@@ -512,8 +860,8 @@
512
860
  }
513
861
 
514
862
  :host([bar-variant="outline"]) .bar.task .progress {
515
- background: color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 28%, transparent);
516
- opacity: 1;
863
+ background: color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 42%, transparent);
864
+ box-shadow: inset -2px 0 0 color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 85%, transparent);
517
865
  }
518
866
 
519
867
  :host([bar-variant="outline"]) .milestone-shape {
@@ -523,7 +871,8 @@
523
871
  0 7px 16px color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 10%, transparent);
524
872
  }
525
873
 
526
- :host([bar-variant="glass"]) .bar.task {
874
+ :host([bar-variant="glass"]) .bar.task,
875
+ :host([bar-variant="glass"]) .split-segment {
527
876
  background:
528
877
  linear-gradient(180deg, color-mix(in srgb, #ffffff 50%, transparent), color-mix(in srgb, #ffffff 10%, transparent)),
529
878
  color-mix(in srgb, var(--tone, var(--ui-gantt-accent)) 72%, transparent);
@@ -541,6 +890,19 @@
541
890
  backdrop-filter: blur(8px);
542
891
  }
543
892
 
893
+ /* The parts of a split bar carry the variant skin; the bar around them stays empty so the gaps are gaps. */
894
+ :host([bar-variant]) .bar.split {
895
+ background: transparent;
896
+ box-shadow: none;
897
+ backdrop-filter: none;
898
+ }
899
+
900
+ /* After the variant skins, which draw their own edge: a finished bar or part has no edge to show. */
901
+ :host([bar-variant]) .bar.complete .progress,
902
+ :host([bar-variant]) .bar .progress.full {
903
+ box-shadow: none;
904
+ }
905
+
544
906
  .today {
545
907
  position: absolute;
546
908
  inset-block: 0;
@@ -550,14 +912,22 @@
550
912
  pointer-events: none;
551
913
  }
552
914
 
553
- .today::before {
554
- content: "Today";
915
+ /* In the header, under the unit labels (which sit at the top of their row), centred on the today line
916
+ and kept inside the track at either end. */
917
+ .today-pill {
555
918
  position: absolute;
556
- inset-block-start: 4px;
557
- inset-inline-start: 6px;
558
- color: var(--ui-color-danger, #dc2626);
559
- font-size: 11px;
919
+ inset-block-end: 3px;
920
+ z-index: 3;
921
+ transform: translateX(-50%);
922
+ padding: 0 6px;
923
+ block-size: 14px;
924
+ border-radius: 7px;
925
+ background: var(--ui-color-danger, #dc2626);
926
+ color: #ffffff;
927
+ font-size: 10px;
560
928
  font-weight: 750;
929
+ line-height: 14px;
930
+ pointer-events: none;
561
931
  }
562
932
 
563
933
  .links {
@@ -590,6 +960,18 @@
590
960
  pointer-events: none;
591
961
  }
592
962
 
963
+ /* A dependency whose target starts or ends earlier than the link allows. */
964
+ .links path.violated:not(.link-hit) {
965
+ stroke: var(--ui-color-danger, #dc2626);
966
+ stroke-width: 1.8;
967
+ stroke-dasharray: 5 3;
968
+ marker-end: url(#ui-gantt-arrow-bad);
969
+ }
970
+
971
+ .links marker#ui-gantt-arrow-bad path {
972
+ fill: var(--ui-color-danger, #dc2626);
973
+ }
974
+
593
975
  .links marker path {
594
976
  fill: color-mix(in srgb, var(--ui-gantt-muted) 82%, transparent);
595
977
  stroke: none;
@@ -620,26 +1002,46 @@
620
1002
  display: none;
621
1003
  }
622
1004
 
623
- @media (max-width: 760px) {
624
- .surface {
625
- grid-template-columns: 270px minmax(560px, 1fr);
1005
+ @media (prefers-reduced-motion: reduce) {
1006
+ .bar,
1007
+ .progress {
1008
+ transition: none !important;
626
1009
  }
1010
+ }
627
1011
 
628
- .grid-head,
629
- .grid-row {
630
- grid-template-columns: minmax(150px, 1fr) 64px 56px;
1012
+ /* Print: the whole chart, not a scroll area. Controls and handles are for the screen; the sticky headers stay put on the
1013
+ page; colours print as they are. A wide timeline is cut at the page edge, so print with the fit zoom or use exportSvg(). */
1014
+ @media print {
1015
+ .frame {
1016
+ box-shadow: none;
1017
+ -webkit-print-color-adjust: exact;
1018
+ print-color-adjust: exact;
631
1019
  }
632
1020
 
633
- .grid-head span:nth-child(3),
634
- .grid-cell:nth-child(3) {
635
- display: none;
1021
+ .controls,
1022
+ .splitter-rail,
1023
+ .connector,
1024
+ .bar-tip,
1025
+ .handle {
1026
+ display: none !important;
636
1027
  }
637
- }
638
1028
 
639
- @media (prefers-reduced-motion: reduce) {
640
- .bar,
641
- .progress {
642
- transition: none !important;
1029
+ .viewport,
1030
+ :host([fill]) .viewport {
1031
+ overflow: visible;
1032
+ max-block-size: none;
1033
+ }
1034
+
1035
+ .grid-head,
1036
+ .timeline-head,
1037
+ .grid-body,
1038
+ .splitter-rail.head {
1039
+ position: static;
1040
+ }
1041
+
1042
+ .grid-row,
1043
+ .timeline-row {
1044
+ break-inside: avoid;
643
1045
  }
644
1046
  }
645
1047
 
@@ -662,89 +1064,102 @@
662
1064
  .bar,
663
1065
  .select,
664
1066
  .control,
665
- .zoom-button {
1067
+ .zoom-button,
1068
+ .today-button,
1069
+ .add-button {
666
1070
  forced-color-adjust: none;
667
1071
  box-shadow: none;
668
1072
  }
1073
+
1074
+ .bar-tip {
1075
+ forced-color-adjust: none;
1076
+ background: Canvas;
1077
+ color: CanvasText;
1078
+ border: 1px solid CanvasText;
1079
+ box-shadow: none;
1080
+ }
669
1081
  }
670
- `,mt={default:"var(--ui-color-primary, #2563eb)",info:"var(--ui-color-info, #0e7490)",success:"var(--ui-color-success, #15803d)",warning:"var(--ui-color-warning, #b45309)",danger:"var(--ui-color-danger, #dc2626)"};function b(a){return String(a??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function f(a){if(a instanceof Date){const n=a.getTime();return Number.isFinite(n)?F(n):null}const t=String(a||"").trim(),i=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(i){const n=Number(i[1]),s=Number(i[2]),l=Number(i[3]),p=new Date(n,s-1,l).getTime();return Number.isFinite(p)?F(p):null}const e=Date.parse(t);return Number.isFinite(e)?F(e):null}function F(a){const t=new Date(a);return t.setHours(0,0,0,0),t.getTime()}function x(a,t){return F(a+t*I)}function E(a){const t=new Date(a),i=t.getFullYear(),e=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${i}-${e}-${n}`}function O(a){return new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric"}).format(new Date(a))}function bt(a){return a==="day"||a==="month"||a==="quarter"||a==="year"?a:"week"}function W(a){return a==="start"||a==="end"||a==="label"||a==="progress"?a:"none"}function Dt(a){return a==="soft"||a==="striped"||a==="outline"||a==="glass"?a:"solid"}function Ft(a,t){if(!a)return[];try{const i=JSON.parse(a);return Array.isArray(i)?i.map((e,n)=>{if(!e||typeof e!="object")return null;const s=e,l=String(s.label||s.text||"").trim(),o=f(s.start),p=Number(s.duration);let u=f(s.end);if(u==null&&o!=null&&Number.isFinite(p)&&(u=x(o,Math.max(0,p))),!l||o==null)return null;const d=s.type==="summary"||s.type==="milestone"?s.type:"task",g=d==="milestone"?o:Math.max(u??x(o,1),x(o,1)),c=String(s.id||`task-${n+1}`),m=t.get(c)||{};return{id:c,label:l,start:m.start||E(o),end:m.end||E(g),progress:Number.isFinite(Number(s.progress))?Math.max(0,Math.min(100,Number(s.progress))):void 0,tone:typeof s.tone=="string"?s.tone:void 0,type:d,parent:s.parent!=null?String(s.parent):void 0,open:s.open!==!1,assignee:s.assignee!=null?String(s.assignee):s.owner!=null?String(s.owner):void 0,readonly:s.readonly===!0,baselineStart:s.baselineStart!=null?String(s.baselineStart):void 0,baselineEnd:s.baselineEnd!=null?String(s.baselineEnd):void 0,critical:s.critical===!0,segments:Array.isArray(s.segments)?s.segments:void 0}}).filter(Boolean):[]}catch{return[]}}function Rt(a){if(!a)return[];try{const t=JSON.parse(a);return Array.isArray(t)?t.map((i,e)=>{if(!i||typeof i!="object")return null;const n=i,s=String(n.source||"").trim(),l=String(n.target||"").trim();if(!s||!l)return null;const o=n.type==="s2s"||n.type==="e2e"||n.type==="s2e"?n.type:"e2s";return{id:String(n.id||`link-${e+1}`),source:s,target:l,type:o}}).filter(Boolean):[]}catch{return[]}}function qt(a,t){return t==="none"?a:[...a].sort((i,e)=>{if(t==="label")return i.label.localeCompare(e.label);if(t==="progress")return Number(e.progress??0)-Number(i.progress??0);const n=f(t==="start"?i.start:i.end)??0,s=f(t==="start"?e.start:e.end)??0;return n-s})}function Nt(a,t,i,e){const n=new Map,s=new Map(a.map(d=>[d.id,d]));a.forEach(d=>{const g=d.parent&&s.has(d.parent)?d.parent:"__root__",c=n.get(g)||[];c.push(d),n.set(g,c)});const l=i.trim().toLowerCase(),o=d=>!l||d.label.toLowerCase().includes(l)||(d.assignee||"").toLowerCase().includes(l)?!0:(n.get(d.id)||[]).some(o),p=[],u=(d,g)=>{qt(n.get(d)||[],e).forEach(c=>{if(!o(c))return;const m=f(c.start),h=f(c.end);if(m==null||h==null)return;const w=(n.get(c.id)||[]).length>0;p.push({...c,depth:g,hasChildren:w,startMs:m,endMs:h}),w&&!t.has(c.id)&&u(c.id,g+1)})};return u("__root__",0),p}function Ht(a,t,i,e,n=0,s=Number.POSITIVE_INFINITY){const l=Math.max(1,Math.ceil((t-a)/I)),o=e==="day"?1:e==="week"?7:e==="month"?30:e==="quarter"?91:365,p=Math.max(0,Math.floor(Math.max(0,n-480)/i/o)*o),u=Math.min(l,Math.ceil((n+s+960)/i/o)*o),d=[];for(let g=p;g<=u;g+=o){const c=g*i,m=x(a,g),h=e==="day"?O(m):new Intl.DateTimeFormat(void 0,{month:"short",year:e==="week"||e==="month"?void 0:"numeric"}).format(new Date(m));d.push(`<span class="tick" style="left:${c.toFixed(2)}px">${b(h)}</span>`)}return d.join("")}function H(a){return a.type==="summary"||a.hasChildren?"summary":a.type==="milestone"||a.startMs===a.endMs?"milestone":"task"}function ft(a){const t=H(a);return t==="summary"?17+9/2:t==="milestone"?7+N/2:12+18/2}function _t(a,t){return H(a)==="milestone"?t(a.startMs)-vt:t(a.startMs)}function jt(a,t){return H(a)==="milestone"?t(a.startMs)+vt:t(a.endMs)}function xt(a,t,i){return t==="start"?_t(a,i):jt(a,i)}function Vt(a="e2s"){return a==="s2s"?{source:"start",target:"start"}:a==="e2e"?{source:"end",target:"end"}:a==="s2e"?{source:"start",target:"end"}:{source:"end",target:"start"}}function Wt(a,t,i,e,n,s){const l=Vt(n),o=l.source==="start"?-1:1,p=l.target==="start"?1:-1,u=xt(a,l.source,s),d=xt(i,l.target,s),g=t*y+ft(a),c=e*y+ft(i),m=22,h=u+o*m,w=d-p*m,M=26;let k=(h+w)/2;if(o===p){const T=o===1?Math.max(h,w,u,d)+M:Math.min(h,w,u,d)-M;k=(o===1?w>h+M:w<h-M)?k:T}else(o===1?w<h:w>h)&&(k=o===1?Math.max(h,u,d)+M:Math.min(h,u,d)-M);const A=Math.abs(c-g)<1?l.target==="start"?c-16:c+16:c>g?c-y/2+3:c+y/2-3;return[[u,g],[h,g],[k,g],[k,A],[w,A],[w,c],[d,c]].map(([T,R],P)=>`${P===0?"M":"L"} ${T.toFixed(1)} ${R.toFixed(1)}`).join(" ")}class wt extends At.ElementBase{constructor(){super(...arguments),this.collapsed=new Set,this.overrides=new Map,this.drag=null,this.selectedId=null,this.internalFilter="",this.viewportTop=0,this.viewportLeft=0,this.viewportWidth=1800,this.viewportHeight=620,this.renderedFirstRow=0,this.renderedLastRow=0,this.scrollFrame=null,this.overridesVersion=0,this.taskCacheRaw=null,this.taskCacheVersion=-1,this.taskCache=[],this.linkCacheRaw=null,this.linkCache=[],this.visibleCacheKey="",this.visibleCache=[]}static get observedAttributes(){return["tasks","links","zoom","filter","sort","bar-variant","variant","readonly","show-toolbar","show-today","headless"]}render(){const t=this.getTasks(),i=this.getLinks(),e=bt(this.getAttribute("zoom")),n=W(this.getAttribute("sort")),s=Dt(this.getAttribute("bar-variant")),l=this.getAttribute("filter")??this.internalFilter,o=this.getVisibleTasks(t,l,n),p=this.hasAttribute("readonly"),u=this.getAttribute("show-toolbar")!=="false",d=this.getAttribute("show-today")!=="false";if(!t.length){this.setContent(`
671
- <style>${ht}</style>
1082
+ `,mt={default:"var(--ui-color-primary, #2563eb)",info:"var(--ui-color-info, #0e7490)",success:"var(--ui-color-success, #15803d)",warning:"var(--ui-color-warning, #b45309)",danger:"var(--ui-color-danger, #dc2626)"};function v(n){return String(n??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function $(n){if(n instanceof Date){const i=n.getTime();return Number.isFinite(i)?Y(i):null}const t=String(n||"").trim(),e=/^(\d{4})-(\d{2})-(\d{2})(?:[T\s].*)?$/.exec(t);if(e){const i=Number(e[1]),a=Number(e[2]),s=Number(e[3]),c=new Date(i,a-1,s).getTime();return Number.isFinite(c)?Y(c):null}const r=Date.parse(t);return Number.isFinite(r)?Y(r):null}function Y(n){const t=new Date(n);return t.setHours(0,0,0,0),t.getTime()}function A(n,t){return Y(n+t*D)}function W(n){const t=new Date(n),e=t.getFullYear(),r=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0");return`${e}-${r}-${i}`}function ht(n){return Z({month:"short",day:"numeric"}).format(new Date(n))}function qe(n){return n==="day"||n==="month"||n==="quarter"||n==="year"||n==="fit"?n:"week"}const Ne=.2,We=48,Be=680,Oe=160,He=7;function Pe(n){return n>=22?"day":n*7>=44?"week":n*30>=44?"month":n*91>=44?"quarter":"year"}function bt(n){return n==="start"||n==="end"||n==="label"||n==="progress"?n:"none"}function _e(n){return n==="soft"||n==="striped"||n==="outline"||n==="glass"?n:"solid"}const Qt=new Date(1970,0,1).getTime();function je(n,t,e=!1){if(!n)return[];try{const r=JSON.parse(n);return Array.isArray(r)?r.map((i,a)=>{if(!i||typeof i!="object")return null;const s=i,o=String(s.label||s.text||"").trim();let c=$(s.start);const h=Number(s.duration);let d=$(s.end);d==null&&c!=null&&Number.isFinite(h)&&(d=A(c,Math.max(0,h)));const g=e&&c==null&&s.type==="summary";if(g&&(c=Qt,d=A(Qt,1)),!o||c==null)return null;const u=s.type==="summary"||s.type==="milestone"?s.type:"task",b=u==="milestone"?c:Math.max(d??A(c,1),A(c,1)),m=String(s.id||`task-${a+1}`),p=t.get(m)||{};return{id:m,label:p.label||o,start:p.start||W(c),end:p.end||W(b),progress:Number.isFinite(Number(s.progress))?Math.max(0,Math.min(100,Number(s.progress))):void 0,tone:typeof s.tone=="string"?s.tone:void 0,type:u,parent:s.parent!=null?String(s.parent):void 0,open:s.open!==!1,assignee:s.assignee!=null?String(s.assignee):s.owner!=null?String(s.owner):void 0,readonly:s.readonly===!0,baselineStart:s.baselineStart!=null?String(s.baselineStart):void 0,baselineEnd:s.baselineEnd!=null?String(s.baselineEnd):void 0,critical:s.critical===!0,undated:g,segments:Array.isArray(s.segments)?s.segments:void 0}}).filter(Boolean):[]}catch{return[]}}function Zt(n){if(!n)return[];try{const t=JSON.parse(n);return Array.isArray(t)?t.map((e,r)=>{if(!e||typeof e!="object")return null;const i=e,a=String(i.source||"").trim(),s=String(i.target||"").trim();if(!a||!s)return null;const o=i.type==="s2s"||i.type==="e2e"||i.type==="s2e"?i.type:"e2s",c=Math.round(Number(i.lag));return{id:String(i.id||`link-${r+1}`),source:a,target:s,type:o,lag:Number.isFinite(c)?c:0}}).filter(Boolean):[]}catch{return[]}}function Ve(n,t){return t==="none"?n:[...n].sort((e,r)=>{if(t==="label")return e.label.localeCompare(r.label);if(t==="progress")return Number(r.progress??0)-Number(e.progress??0);const i=$(t==="start"?e.start:e.end)??0,a=$(t==="start"?r.start:r.end)??0;return i-a})}function Xe(n,t,e,r){const i=new Map,a=new Map(n.map(d=>[d.id,d]));n.forEach(d=>{const g=d.parent&&a.has(d.parent)?d.parent:"__root__",u=i.get(g)||[];u.push(d),i.set(g,u)});const s=e.trim().toLowerCase(),o=d=>!s||d.label.toLowerCase().includes(s)||(d.assignee||"").toLowerCase().includes(s)?!0:(i.get(d.id)||[]).some(o),c=[],h=(d,g)=>{Ve(i.get(d)||[],r).forEach(u=>{if(!o(u))return;const b=$(u.start),m=$(u.end);if(b==null||m==null)return;const p=(i.get(u.id)||[]).length>0;c.push({...u,depth:g,hasChildren:p,startMs:b,endMs:m}),p&&!t.has(u.id)&&h(u.id,g+1)})};return h("__root__",0),c}function Ye(){try{const n=Z({}).resolvedOptions().locale,t=new Intl.Locale(n),e=typeof t.getWeekInfo=="function"?t.getWeekInfo():t.weekInfo;if(e&&Number.isInteger(e.firstDay))return e.firstDay%7}catch{}return 1}function Ft(n){const t=n==null||n===""?NaN:Number(n);return Number.isInteger(t)&&t>=0&&t<=6?t:Ye()}function ue(n,t,e){const r=new Date(n);return r.setHours(0,0,0,0),t==="week"?r.setDate(r.getDate()-(r.getDay()-e+7)%7):t==="month"?r.setDate(1):t==="quarter"?r.setMonth(Math.floor(r.getMonth()/3)*3,1):t==="year"&&r.setMonth(0,1),r.getTime()}function pe(n,t){const e=new Date(n);return t==="day"?e.setDate(e.getDate()+1):t==="week"?e.setDate(e.getDate()+7):t==="month"?e.setMonth(e.getMonth()+1):t==="quarter"?e.setMonth(e.getMonth()+3):e.setFullYear(e.getFullYear()+1),e.getTime()}function kt(n,t,e,r,i,a,s){const o=[],c=e+Math.max(0,a-480)/i*D,h=a+s+960;let d=ue(Math.max(e,c),n,t);for(;d<r;){const g=pe(d,n),u=Math.max(d,e),b=Math.min(g,r),m=(u-e)/D*i;if(m>h)break;b>u&&o.push({left:m,width:(b-u)/D*i,start:d,label:""}),d=g}return o}const Ue={weekdays:new Set,holidays:new Map};function te(n,t){const e=new Set;if(n!=null){const i=n.trim();if(i==="")e.add(0),e.add(6);else{let a=i.split(",");try{const s=JSON.parse(i);Array.isArray(s)?a=s:typeof s=="number"&&(a=[s])}catch{}for(const s of a){const o=Number(typeof s=="string"?s.trim():s);Number.isInteger(o)&&o>=0&&o<=6&&e.add(o)}}}const r=new Map;if(t)try{const i=JSON.parse(t);if(Array.isArray(i))for(const a of i){const s=a&&typeof a=="object"?a:null,o=$(s?s.date:a);o!=null&&r.set(o,s&&typeof s.label=="string"?s.label:"")}}catch{}return{weekdays:e,holidays:r}}function ge(n,t){return t.holidays.has(n)||t.weekdays.has(new Date(n).getDay())}const fe=8;function Ke(n,t,e,r,i,a){if(e<fe||!r.weekdays.size&&!r.holidays.size)return"";const s=Math.max(0,Math.floor(Math.max(0,i-480)/e)),o=Math.min(Math.ceil((t-n)/D),Math.ceil((i+a+960)/e)),c=[];let h=-1,d="";const g=u=>{h>=0&&c.push(`<span class="off-day${d}" style="left:${(h*e).toFixed(2)}px;width:${((u-h)*e).toFixed(2)}px"></span>`),h=-1};for(let u=s;u<o;u+=1){const b=H(n,u),m=r.holidays.has(b)?" holiday":r.weekdays.has(new Date(b).getDay())?"":null;(m===null||h>=0&&m!==d)&&g(u),m!==null&&h<0&&(h=u,d=m)}return g(o),c.join("")}const It=36;function Je(n,t,e,r,i,a=0,s=Number.POSITIVE_INFINITY,o=Ue){const c=Y(Date.now()),h=Z({month:"long",year:"numeric"}),d=Z({month:"short"}),g=Z({weekday:"narrow"}),u=(y,w,x,M="")=>`<span class="${y}" style="left:${w.left.toFixed(2)}px;width:${w.width.toFixed(2)}px"${M?` title="${v(M)}"`:""}>${x}</span>`,m=kt(r,i,n,t,e,a,s).map(y=>{const w=new Date(y.start),x=y.width>=It;if(r==="day"){const M=y.start===c,T=o.holidays.get(y.start);return u(`tick day${M?" today-cell":""}${ge(y.start,o)?" off":""}`,y,`<span class="dow">${v(g.format(w))}</span><span class="num">${w.getDate()}</span>`,T||"")}return r==="week"?u("tick",y,x?`<span class="num">${w.getDate()}</span>`:"",ht(y.start)):r==="month"?u("tick",y,x?v(d.format(w)):"",h.format(w)):r==="quarter"?u("tick",y,x?`Q${Math.floor(w.getMonth()/3)+1}`:"",`Q${Math.floor(w.getMonth()/3)+1} ${w.getFullYear()}`):u("tick",y,x?String(w.getFullYear()):"")}).join("");if(r==="year")return`<div class="band bottom">${m}</div>`;const p=r==="day"||r==="week"?"month":"year";return`<div class="band top">${kt(p,i,n,t,e,a,s).map(y=>{const w=new Date(y.start),x=p==="month"?h.format(w):String(w.getFullYear()),M=y.width<It?"":p==="month"&&y.width<120?d.format(w):x;return u("band-cell",y,v(M),x)}).join("")}</div><div class="band bottom">${m}</div>`}function ee(n){const t=new Set;if(!n)return t;try{const e=JSON.parse(n);Array.isArray(e)&&e.forEach((r,i)=>{r&&typeof r=="object"&&t.add(String(r.id||`task-${i+1}`))})}catch{}return t}function Ge(n,t){for(const e of n)if(t.has(e))return!0;return!1}function Qe(n,t,e,r,i,a,s){return r==="day"?"":kt(r,i,n,t,e,a,s).filter(o=>o.start>=n).map(o=>`<span class="unit-line" style="left:${o.left.toFixed(2)}px"></span>`).join("")}function Ze(n,t){const e=i=>Math.max(0,Math.min(100,i));let r=n.reduce((i,a)=>a.progress==null?i+a.duration:i,0)*(e(t)/100);return n.map(i=>{if(i.progress!=null)return e(i.progress);const a=Math.min(i.duration,r);return r-=a,i.duration>0?a/i.duration*100:0})}function tr(n,t){const e=Math.max(D,n.endMs-n.startMs),r=[];for(const a of n.segments||[]){const s=$(a.start),o=$(a.end);if(s==null||o==null)continue;const c=Math.max(n.startMs,s),h=Math.min(n.endMs,o);if(h<=c)continue;const d=Math.max(0,Math.min(100,(c-n.startMs)/e*100)),g=Math.min(100-d,Math.max(1,(h-c)/e*100));if(g<=0)continue;const u=Number(a.progress);r.push({left:d,width:g,duration:h-c,progress:a.progress!=null&&Number.isFinite(u)?u:void 0})}const i=Ze(r,t);return r.map((a,s)=>`<span class="split-segment" style="left:${a.left.toFixed(2)}%;width:${a.width.toFixed(2)}%"><span class="progress${i[s]>=100?" full":""}" style="--progress:${i[s].toFixed(2)}%"></span></span>`).join("")}function ot(n){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(n):n.replace(/["\\]/g,"\\$&")}function Nt(n){return`.grid-row[data-task-id="${ot(n)}"]`}function At(n){return`.bar[data-task-id="${ot(n)}"]`}function er(n){return n.classList.contains("control")?".control":n.classList.contains("select")?".select":n.classList.contains("zoom-button")&&n.dataset.zoom?`.zoom-button[data-zoom="${ot(n.dataset.zoom)}"]`:n.classList.contains("today-button")?".today-button":n.classList.contains("add-button")?".add-button":n.classList.contains("rename")?".rename":n.classList.contains("head-button")&&n.dataset.sort?`.head-button[data-sort="${ot(n.dataset.sort)}"]`:n.classList.contains("splitter")&&n.getAttribute("role")==="separator"?'.splitter[role="separator"]':n.classList.contains("link-hit")&&n.dataset.linkId?`.link-hit[data-link-id="${ot(n.dataset.linkId)}"]`:n.classList.contains("bar")&&n.dataset.taskId?At(n.dataset.taskId):n.classList.contains("grid-row")&&n.dataset.taskId?Nt(n.dataset.taskId):n.classList.contains("expander")&&n.dataset.taskId?`.expander[data-task-id="${ot(n.dataset.taskId)}"]`:null}const Et={title:"Project schedule",tasksCount:"{shown}/{total} tasks",filterPlaceholder:"Filter tasks",filterLabel:"Filter tasks",sortLabel:"Sort tasks",sortManual:"Manual",sortStart:"Start date",sortEnd:"End date",sortName:"Name",sortProgress:"Progress",zoomDay:"day",zoomWeek:"week",zoomMonth:"month",zoomQuarter:"quarter",zoomYear:"year",zoomFit:"fit",zoomFitTitle:"Fit the whole project to the width",columnTask:"Task",columnOwner:"Owner",columnDates:"Dates",columnProgress:"%",columnStart:"Start",columnEnd:"End",columnDuration:"Days",splitter:"Resize the task list",scrollToToday:"Scroll to today",addTask:"Add task",rename:"Rename task",linkViolated:"dependency not met",empty:"No tasks in this range",noMatches:"No matching tasks",expand:"Expand",collapse:"Collapse",timeline:"Timeline",today:"Today",summary:"summary",milestone:"milestone",to:"to",complete:"complete",assigned:"assigned to",critical:"critical"},Rt={label:{title:"columnTask",sort:"label",width:170},assignee:{title:"columnOwner",width:82},dates:{title:"columnDates",sort:"start",width:80},start:{title:"columnStart",sort:"start",width:74},end:{title:"columnEnd",sort:"end",width:74},duration:{title:"columnDuration",width:56},progress:{title:"columnProgress",sort:"progress",width:44}},rr=["label","assignee","dates","progress"],re=96;function ir(n){let t=rr;if(n)try{const a=JSON.parse(n);Array.isArray(a)&&a.length&&(t=a)}catch{}const e=[],r=new Set;for(const a of t){const s=a&&typeof a=="object"?a:null;let o=typeof a=="string"?a:s?s.key:null;if(o==="owner"&&(o="assignee"),typeof o!="string"||!(o in Rt)||r.has(o))continue;r.add(o);const c=Rt[o],h=s?Number(s.width):NaN;e.push({key:o,title:c.title,custom:s&&typeof s.label=="string"&&s.label?s.label:void 0,sort:c.sort,width:Number.isFinite(h)&&h>=36?Math.min(Math.round(h),400):c.width})}const i=e.findIndex(a=>a.key==="label");return i>0&&e.unshift(e.splice(i,1)[0]),i<0&&e.unshift({key:"label",title:"columnTask",sort:"label",width:Rt.label.width}),e}function nr(n,t){const e=n.slice(1).reduce((a,s)=>a+s.width,0),r=t!=null?re:n[0].width,i=e+re;return{width:t!=null?Math.max(Math.round(t),i):e+n[0].width,min:i,template:n.map((a,s)=>s===0?`minmax(${r}px, 1fr)`:`${a.width}px`).join(" ")}}let Lt;function Z(n){try{return new Intl.DateTimeFormat(Lt,n)}catch{return new Intl.DateTimeFormat(void 0,n)}}function sr(n,t,e,r){const i=e.format(new Date(n.startMs)),a=t==="milestone"?i:`${i} ${r.to} ${e.format(new Date(n.endMs))}`,s=t==="summary"||t==="milestone"?r[t]:"",o=[];return n.progress!=null&&t!=="milestone"&&o.push(`${Math.round(n.progress)}% ${r.complete}`),n.assignee&&o.push(`${r.assigned} ${n.assignee}`),n.critical&&o.push(r.critical),{name:[n.label,s,a,...o].filter(Boolean).join(", "),title:n.label,kindWord:s,when:[s,a].filter(Boolean).join(" · "),more:o.join(" · ")}}function ar(n,t){return{day:t.zoomDay,week:t.zoomWeek,month:t.zoomMonth,quarter:t.zoomQuarter,year:t.zoomYear,fit:t.zoomFit}[n]}function or(n){const t=(n||"").trim();return t==="none"||/^\d*\.?\d+(px|em|rem|vh|dvh|svh|lvh|vw|%|ch)$/.test(t)?t:null}function Wt(n){return{id:n.id,source:n.source,target:n.target,type:n.type||"e2s",lag:n.lag??0}}function ie(n){return n==="auto"||n==="off"?n:"warn"}function yt(n){const t=$(n.start),e=$(n.end);return t==null||e==null?null:{id:n.id,start:t,end:e,parent:n.parent,type:n.type,readonly:n.readonly,progress:n.progress}}function lr(n){const t=Te(n.map(yt).filter(e=>e!=null));return n.map(e=>{const r=t.get(e.id);return r?{...e,undated:!1,start:W(r.start),end:W(r.end),progress:e.progress??r.progress}:e}).filter(e=>!e.undated)}function dr(n,t){const e=ze(n.map(yt).filter(r=>r!=null),t.map(Wt));return e.size?n.map(r=>e.has(r.id)&&!r.critical?{...r,critical:!0}:r):n}function qt(n){if(!n)return[];try{const t=JSON.parse(n);return Array.isArray(t)?t:[]}catch{return[]}}function xt(n){return n instanceof Date?Number.isFinite(n.getTime())?W(n.getTime()):void 0:n}function ne(n,t,e,r){if(!Array.isArray(e)){n.removeAttribute(t);return}const i=r?e.map(a=>{const s={...a};for(const o of["start","end","baselineStart","baselineEnd"])o in s&&(s[o]=xt(s[o]));return Array.isArray(s.segments)&&(s.segments=s.segments.map(o=>({...o,start:xt(o.start),end:xt(o.end)}))),s}):e;try{n.setAttribute(t,JSON.stringify(i))}catch{}}function cr(n){const t=n==null||n===""?NaN:Number(n);return Number.isFinite(t)&&t>0?t:null}function ut(n){return n.type==="summary"||n.hasChildren?"summary":n.type==="milestone"||n.startMs===n.endMs?"milestone":"task"}function se(n){const t=ut(n);return t==="summary"?17+9/2:t==="milestone"?7+vt/2:12+18/2}function hr(n,t){return ut(n)==="milestone"?t(n.startMs)-he:t(n.startMs)}function ur(n,t){return ut(n)==="milestone"?t(n.startMs)+he:t(n.endMs)}function ae(n,t,e){return t==="start"?hr(n,e):ur(n,e)}function pr(n="e2s"){return n==="s2s"?{source:"start",target:"start"}:n==="e2e"?{source:"end",target:"end"}:n==="s2e"?{source:"start",target:"end"}:{source:"end",target:"start"}}function oe(n,t,e,r,i,a){const s=pr(i),o=s.source==="start"?-1:1,c=s.target==="start"?1:-1,h=ae(n,s.source,a),d=ae(e,s.target,a),g=t*S+se(n),u=r*S+se(e),b=22,m=h+o*b,p=d-c*b,k=26;let y=(m+p)/2;if(o===c){const M=o===1?Math.max(m,p,h,d)+k:Math.min(m,p,h,d)-k;y=(o===1?p>m+k:p<m-k)?y:M}else(o===1?p<m:p>m)&&(y=o===1?Math.max(m,h,d)+k:Math.min(m,h,d)-k);const w=Math.abs(u-g)<1?s.target==="start"?u-16:u+16:u>g?u-S/2+3:u+S/2-3;return[[h,g],[m,g],[y,g],[y,w],[p,w],[p,u],[d,u]].map(([M,T],z)=>`${z===0?"M":"L"} ${M.toFixed(1)} ${T.toFixed(1)}`).join(" ")}class me extends Ee.ElementBase{constructor(){super(...arguments),this.focusRequest=null,this.collapsed=new Set,this.seededIds=new Set,this.overrides=new Map,this.drag=null,this.selectedId=null,this.internalFilter="",this.viewportTop=0,this.viewportLeft=0,this.viewportWidth=1800,this.hostWidth=0,this.renderedLeft=0,this.smoothTarget=null,this.selectedLinkId=null,this.linking=null,this.editingId=null,this.editingValue="",this.suppressBlur=!1,this.layoutInfo={min:0,dayWidth:13,gridWidth:Tt,rangeEnd:0},this.visibleIds=[],this.initialScrollPending=!0,this.pendingReveal=null,this.hostHeight=0,this.virtualizedNow=!1,this.gridBounds={min:0,max:0,width:Tt},this.descriptions=new Map,this.tipTimer=null,this.pointerFocus=!1,this.scrollbarWidth=0,this.dayWidthNow=Jt.week,this.resizeObserver=null,this.viewportHeight=620,this.renderedFirstRow=0,this.renderedLastRow=0,this.scrollFrame=null,this.overridesVersion=0,this.taskCacheRaw=null,this.taskCacheVersion=-1,this.taskCacheAuto=!1,this.taskCacheCritical=null,this.taskCache=[],this.linkCacheRaw=null,this.linkCache=[],this.visibleCacheKey="",this.visibleCache=[],this.labelsRaw=null,this.labelsCache=Et}static get observedAttributes(){return["tasks","links","zoom","filter","sort","bar-variant","variant","readonly","show-toolbar","show-today","headless","week-start","labels","locale","columns","grid-width","fill","max-height","snap","creatable","auto-summary","cascade","schedule","critical-path","non-working-days","holidays","linkable"]}connectedCallback(){for(const t of["tasks","links","holidays"])if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}super.connectedCallback(),!(typeof ResizeObserver>"u"||this.resizeObserver)&&(this.resizeObserver=new ResizeObserver(t=>{const e=t[t.length-1]?.contentRect,r=e?.width??0,i=e?.height??0,a=Math.abs(r-this.hostWidth)>=1,s=Math.abs(i-this.hostHeight)>=1&&(this.hasAttribute("fill")||this.virtualizedNow);this.hostHeight=i,!(!a&&!s)&&(a&&(this.hostWidth=Math.round(r)),this.captureViewport(),this.requestRender())}),this.resizeObserver.observe(this))}disconnectedCallback(){this.resizeObserver?.disconnect(),this.resizeObserver=null,this.tipTimer!=null&&window.clearTimeout(this.tipTimer),this.tipTimer=null,super.disconnectedCallback()}labelSet(){const t=this.getAttribute("labels");if(t===this.labelsRaw)return this.labelsCache;if(this.labelsRaw=t,this.labelsCache=Et,t)try{const e=JSON.parse(t);if(e&&typeof e=="object"){const r={...Et};for(const[i,a]of Object.entries(e))i in Et&&typeof a=="string"&&(r[i]=a);this.labelsCache=r}}catch{}return this.labelsCache}render(){this.suppressBlur=!0,queueMicrotask(()=>{this.suppressBlur=!1}),Lt=this.getAttribute("locale")||void 0;const t=this.labelSet(),e=this.getTasks(),r=this.getLinks(),i=qe(this.getAttribute("zoom")),a=bt(this.getAttribute("sort")),s=_e(this.getAttribute("bar-variant")),o=this.getAttribute("filter")??this.internalFilter,c=this.getVisibleTasks(e,o,a),h=this.hasAttribute("readonly"),d=this.hasAttribute("creatable")&&!h,g=this.hasAttribute("cascade"),u=this.hasAttribute("linkable")&&!h,b=this.getAttribute("show-toolbar")!=="false",m=this.getAttribute("show-today")!=="false";if(!e.length){this.setContent(`
1083
+ <style>${Gt}</style>
672
1084
  <section class="frame" part="frame">
673
- <div class="empty" part="empty">No tasks in this range</div>
1085
+ <div class="empty" part="empty">${v(t.empty)}</div>
674
1086
  </section>
675
- `);return}const g=t.map(r=>f(r.start)).filter(r=>r!=null),c=t.map(r=>f(r.end)).filter(r=>r!=null),m=x(Math.min(...g),-2),h=x(Math.max(...c),3),w=Math.max(7,Math.ceil((h-m)/I)),M=gt[e],k=Math.max(680,w*M),A=Math.max(o.length*y,y),S=this.getAttribute("virtualized")!=="false"&&o.length>240,T=Math.max(20,Math.ceil(Math.max(420,this.viewportHeight-V)/y)),R=160,P=Math.max(0,this.viewportTop-V),yt=Math.max(0,Math.floor(P/y)),X=Math.max(180,T*4),L=S?Math.max(0,Math.floor(yt/X)*X-R):0,B=S?Math.min(o.length,L+T+R*2+X):o.length,K=o.slice(L,B),_=L*y,j=Math.max(0,(o.length-B)*y);this.renderedFirstRow=L,this.renderedLastRow=B;const Q=new Map(o.map((r,$)=>[r.id,{task:r,index:$}])),tt=new Set(K.map(r=>r.id)),z=r=>(r-m)/I*M,kt=K.map((r,$)=>{const C=L+$,v=this.selectedId===r.id?" selected":"",D=H(r),G=r.progress==null?"-":`${Math.round(r.progress)}%`,U=D==="milestone"?O(r.startMs):`${O(r.startMs)} - ${O(r.endMs)}`;return`
676
- <div class="grid-row${v}" part="grid-row" data-task-id="${b(r.id)}" role="row" aria-rowindex="${C+2}" aria-level="${r.depth+1}" ${r.hasChildren?`aria-expanded="${!this.collapsed.has(r.id)}"`:""}>
677
- <div class="grid-cell task-name" role="gridcell" style="padding-left:${10+r.depth*18}px">
678
- ${r.hasChildren?`<button class="expander" data-action="toggle" data-task-id="${b(r.id)}" aria-label="${this.collapsed.has(r.id)?"Expand":"Collapse"} ${b(r.label)}">${this.collapsed.has(r.id)?"›":"⌄"}</button>`:'<span style="inline-size:22px"></span>'}
679
- <span class="name-text" title="${b(r.label)}">${b(r.label)}</span>
680
- </div>
681
- <div class="grid-cell badge" role="gridcell">${b(r.assignee||D)}</div>
682
- <div class="grid-cell badge" role="gridcell">${b(U)}</div>
683
- <div class="grid-cell badge" role="gridcell">${b(G)}</div>
1087
+ `);return}const p=e.map(l=>$(l.start)).filter(l=>l!=null),k=e.map(l=>$(l.end)).filter(l=>l!=null),y=A(Math.min(...p),-2),w=A(Math.max(...k),3),x=Math.max(7,Math.ceil((w-y)/D));this.hostWidth=this.clientWidth||this.hostWidth;const M=this.hostWidth-Fe;this.hostHeight=this.clientHeight||this.hostHeight;const T=or(this.getAttribute("max-height")),z=this.hostWidth>0&&M<=Ce,U=ir(this.getAttribute("columns")),P=nr(U,cr(this.getAttribute("grid-width"))),lt=z?De:P.width;this.gridBounds={min:P.min,max:Math.max(P.min,this.hostWidth>0?M-240:1200),width:P.width};const st=i==="fit",R=this.hostWidth>0?M-lt-this.scrollbarWidth:Be,q=st?Math.max(Ne,Math.min(We,R/x)):Jt[i],K=st?Pe(q):i;this.dayWidthNow=q;const J=Math.max(st?Oe:680,x*q),O=Math.max(c.length*S,S),V=this.getAttribute("virtualized")!=="false"&&c.length>240;this.virtualizedNow=V;const et=Math.max(20,Math.ceil(Math.max(420,this.viewportHeight-N)/S)),f=160;this.viewportTop=Math.min(this.viewportTop,Math.max(0,O+N-this.viewportHeight));const E=Math.max(0,this.viewportTop-N),L=Math.max(0,Math.floor(E/S)),_=Math.max(180,et*4),G=V?Math.max(0,Math.floor(L/_)*_-f):0,at=V?Math.min(c.length,G+et+f*2+_):c.length,dt=c.slice(G,at),rt=G*S,it=Math.max(0,(c.length-at)*S);this.renderedFirstRow=G,this.renderedLastRow=at;const $t=Z({dateStyle:"medium"}),pt=new Map,F=new Map(c.map((l,B)=>[l.id,{task:l,index:B}])),C=new Set(dt.map(l=>l.id)),tt=this.selectedId!=null&&C.has(this.selectedId)?this.selectedId:dt[0]?.id,nt=l=>(l-y)/D*q,be=dt.map((l,B)=>{const I=G+B,Q=this.selectedId===l.id?" selected":"",X=ut(l),ct=ft=>{switch(ft.key){case"label":return`<div class="grid-cell task-name" role="gridcell" style="padding-left:${10+l.depth*18}px">
1088
+ ${l.hasChildren?`<button class="expander" data-action="toggle" data-task-id="${v(l.id)}" aria-label="${v(this.collapsed.has(l.id)?t.expand:t.collapse)} ${v(l.label)}">${this.collapsed.has(l.id)?"›":"⌄"}</button>`:'<span style="inline-size:22px"></span>'}
1089
+ ${this.editingId===l.id?`<input class="rename" value="${v(this.editingValue)}" aria-label="${v(t.rename)}" />`:`<span class="name-text" title="${v(l.label)}">${v(l.label)}</span>`}
1090
+ </div>`;case"assignee":return`<div class="grid-cell badge" role="gridcell">${v(l.assignee||X)}</div>`;case"dates":return`<div class="grid-cell badge" role="gridcell">${v(X==="milestone"?ht(l.startMs):`${ht(l.startMs)} - ${ht(l.endMs)}`)}</div>`;case"start":return`<div class="grid-cell badge" role="gridcell">${v(ht(l.startMs))}</div>`;case"end":return`<div class="grid-cell badge" role="gridcell">${v(X==="milestone"?"-":ht(l.endMs))}</div>`;case"duration":return`<div class="grid-cell badge" role="gridcell">${X==="milestone"?"-":Math.max(0,Math.round((l.endMs-l.startMs)/D))}</div>`;default:return`<div class="grid-cell badge" role="gridcell">${l.progress==null?"-":`${Math.round(l.progress)}%`}</div>`}};return`
1091
+ <div class="grid-row${Q}" part="grid-row" data-task-id="${v(l.id)}" role="row" tabindex="${l.id===tt?0:-1}" aria-rowindex="${I+2}" aria-level="${l.depth+1}" ${Q?'aria-selected="true"':""} ${l.hasChildren?`aria-expanded="${!this.collapsed.has(l.id)}"`:""}>
1092
+ ${U.map(ct).join("")}
684
1093
  </div>
685
- `}).join(""),$t=K.map((r,$)=>{const C=L+$,v=H(r),D=this.selectedId===r.id?" selected":"",G=this.selectedId===r.id||!this.selectedId&&C===0,U=mt[r.tone||(v==="summary"?"info":"default")]||mt.default,rt=v==="milestone"?z(r.startMs)-N/2:z(r.startMs),zt=z(v==="milestone"?r.startMs:r.endMs),Ct=v==="milestone"?N:Math.max(12,zt-rt),Tt=Math.max(0,Math.min(100,Number(r.progress??0))),at=!p&&!r.readonly&&v!=="summary",nt=at&&v==="task",it=v==="task"&&r.segments?.length?r.segments.map(st=>{const ot=f(st.start),lt=f(st.end);if(ot==null||lt==null)return"";const dt=Math.max(I,r.endMs-r.startMs),Z=Math.max(r.startMs,ot),ct=Math.min(r.endMs,lt);if(ct<=Z)return"";const pt=Math.max(0,Math.min(100,(Z-r.startMs)/dt*100)),It=(ct-Z)/dt*100,ut=Math.min(100-pt,Math.max(1,It));return ut<=0?"":`<span class="split-segment" style="left:${pt.toFixed(2)}%;width:${ut.toFixed(2)}%"></span>`}).join(""):"";return`
686
- <div class="timeline-row${D}" part="timeline-row" data-task-id="${b(r.id)}">
687
- ${r.baselineStart&&r.baselineEnd?`<span class="baseline" style="left:${z(f(r.baselineStart)||r.startMs).toFixed(2)}px;width:${Math.max(4,z(f(r.baselineEnd)||r.endMs)-z(f(r.baselineStart)||r.startMs)).toFixed(2)}px"></span>`:""}
1094
+ `}).join(""),ve=dt.map((l,B)=>{const I=ut(l),Q=sr(l,I,$t,t);pt.set(l.id,Q);const X=this.selectedId===l.id?" selected":"",ct=l.id===tt,ft=l.critical?mt.danger:mt[l.tone||(I==="summary"?"info":"default")]||mt.default,Mt=I==="milestone"?nt(l.startMs)-vt/2:nt(l.startMs),Se=nt(I==="milestone"?l.startMs:l.endMs),Xt=I==="milestone"?vt:Math.max(12,Se-Mt),St=Math.max(0,Math.min(100,Number(l.progress??0))),Yt=!h&&!l.readonly&&(I!=="summary"||g),Ut=Yt&&I==="task",Kt=I==="task"&&l.segments?.length?tr(l,St):"";return`
1095
+ <div class="timeline-row${X}" part="timeline-row" data-task-id="${v(l.id)}">
1096
+ ${l.baselineStart&&l.baselineEnd?`<span class="baseline" style="left:${nt($(l.baselineStart)||l.startMs).toFixed(2)}px;width:${Math.max(4,nt($(l.baselineEnd)||l.endMs)-nt($(l.baselineStart)||l.startMs)).toFixed(2)}px"></span>`:""}
688
1097
  <button
689
- class="bar ${v}${r.critical?" critical":""}${it?" split":""}"
690
- part="bar ${v}"
691
- data-task-id="${b(r.id)}"
692
- data-kind="${v}"
693
- tabindex="${G?"0":"-1"}"
694
- ${this.selectedId===r.id?'aria-current="true"':""}
695
- style="left:${rt.toFixed(2)}px;width:${Ct.toFixed(2)}px;--tone:${U};--progress:${Tt.toFixed(2)}%"
696
- aria-label="${b(r.label)}"
697
- ${at?'data-draggable="true"':""}
1098
+ class="bar ${I}${l.critical?" critical":""}${Kt?" split":""}${St>=100?" complete":""}"
1099
+ part="bar ${I}"
1100
+ data-task-id="${v(l.id)}"
1101
+ data-kind="${I}"
1102
+ ${l.progress!=null?`data-progress="${Math.round(St)}"`:""}
1103
+ tabindex="${ct?"0":"-1"}"
1104
+ ${this.selectedId===l.id?'aria-current="true"':""}
1105
+ style="left:${Mt.toFixed(2)}px;width:${Xt.toFixed(2)}px;--tone:${ft};--progress:${St.toFixed(2)}%"
1106
+ aria-label="${v(Q.name)}"
1107
+ ${Yt?'data-draggable="true"':""}
698
1108
  >
699
- ${nt?'<span class="handle start" data-mode="resize-start"></span>':""}
1109
+ ${Ut?'<span class="handle start" data-mode="resize-start"></span>':""}
700
1110
  <span class="progress"></span>
701
- ${it}
702
- ${v==="milestone"?'<span class="milestone-shape"></span>':""}
703
- <span class="drag-tip"></span>
704
- ${nt?'<span class="handle end" data-mode="resize-end"></span>':""}
1111
+ ${Kt}
1112
+ ${I==="milestone"?'<span class="milestone-shape"></span>':""}
1113
+ ${Ut?'<span class="handle end" data-mode="resize-end"></span>':""}
705
1114
  </button>
1115
+ ${u?`<span class="connector" data-task-id="${v(l.id)}" data-side="start" style="left:${(Mt-18).toFixed(2)}px"></span><span class="connector" data-task-id="${v(l.id)}" data-side="end" style="left:${(Mt+Xt+6).toFixed(2)}px"></span>`:""}
706
1116
  </div>
707
- `}).join(""),et=i.map(r=>{const $=Q.get(r.source),C=Q.get(r.target);if(!$||!C||S&&!tt.has(r.source)&&!tt.has(r.target))return"";const v=Wt($.task,$.index,C.task,C.index,r.type,z),D=`${$.task.label} dependency to ${C.task.label}`;return`<path class="link-hit" d="${v}" data-link-id="${b(r.id)}" data-source-id="${b(r.source)}" data-target-id="${b(r.target)}" data-link-type="${b(r.type||"e2s")}" aria-label="${b(D)}" /><path d="${v}" />`}).join(""),Mt=et?'<defs><marker id="ui-gantt-arrow" markerWidth="9" markerHeight="9" refX="8.5" refY="4.5" orient="auto" markerUnits="userSpaceOnUse"><path d="M 0.5 0.75 L 8.5 4.5 L 0.5 8.25 z" /></marker></defs>':"",Y=F(Date.now()),Et=z(Y),St=d&&Y>=m&&Y<=h?`<div class="today" part="today" style="left:${Et.toFixed(2)}px"></div>`:"";this.setContent(`
708
- <style>${ht}</style>
709
- <section class="frame" part="frame" data-bar-variant="${s}">
710
- ${u?`
1117
+ `}).join("");this.descriptions=pt,this.selectedLinkId&&!r.some(l=>l.id===this.selectedLinkId)&&(this.selectedLinkId=null);const ye=ie(this.getAttribute("schedule"))==="off"?new Set:Le(e.map(yt).filter(l=>l!=null),r.map(Wt)),Ot=r.map(l=>{const B=F.get(l.source),I=F.get(l.target);if(!B||!I||V&&!C.has(l.source)&&!C.has(l.target))return"";const Q=oe(B.task,B.index,I.task,I.index,l.type,nt),X=ye.has(l.id),ct=this.selectedLinkId===l.id,ft=`${B.task.label} dependency to ${I.task.label}${X?`, ${t.linkViolated}`:""}`;return`<path class="link-hit${X?" violated":""}${ct?" selected":""}" tabindex="-1" d="${Q}" data-link-id="${v(l.id)}" data-source-id="${v(l.source)}" data-target-id="${v(l.target)}" data-link-type="${v(l.type||"e2s")}"${X?' data-violated="true"':""} aria-label="${v(ft)}" /><path class="${[X?"violated":"",ct?"selected":""].filter(Boolean).join(" ")}" d="${Q}" />`}).join(""),Ht=l=>`<marker id="${l}" markerWidth="9" markerHeight="9" refX="8.5" refY="4.5" orient="auto" markerUnits="userSpaceOnUse"><path d="M 0.5 0.75 L 8.5 4.5 L 0.5 8.25 z" /></marker>`,xe=Ot?`<defs>${Ht("ui-gantt-arrow")}${Ht("ui-gantt-arrow-bad")}</defs>`:"",Pt=Ft(this.getAttribute("week-start")),_t=te(this.getAttribute("non-working-days"),this.getAttribute("holidays")),we=Math.max(J,M-lt),gt=y+we/q*D;this.layoutInfo={min:y,dayWidth:q,gridWidth:lt,rangeEnd:gt},this.renderedLeft=this.viewportLeft,this.visibleIds=c.map(l=>l.id);const zt=Y(Date.now()),Ct=nt(zt),Dt=zt>=y&&zt<=gt,jt=m&&Dt,ke=jt?`<div class="today" part="today" style="left:${Ct.toFixed(2)}px"></div>`:"",$e=jt&&K!=="day"?`<span class="today-pill" part="today-pill" style="left:clamp(22px, ${Ct.toFixed(2)}px, calc(100% - 22px))">${v(t.today)}</span>`:"",Me=this.focusRequest??this.captureFocus();this.focusRequest=null;const Vt=this.root.querySelector(".frame");this.setContent(`
1118
+ <style>${Gt}</style>
1119
+ ${P.width!==Tt||P.template!==ce?`<style>@container ui-gantt (min-width: 641px) { .surface { --gantt-grid-w: ${P.width}px; --gantt-cols: ${P.template}; } }</style>`:""}
1120
+ <section class="frame" part="frame" data-bar-variant="${s}"${T?` style="--ui-gantt-max-height:${T}"`:""}>
1121
+ ${b?`
711
1122
  <header class="toolbar" part="toolbar">
712
- <div class="title">Project schedule <span class="meta">${o.length}/${t.length} tasks</span></div>
1123
+ <div class="title">${v(t.title)} <span class="meta">${v(t.tasksCount.replace("{shown}",String(c.length)).replace("{total}",String(e.length)))}</span></div>
713
1124
  <div class="controls">
714
- <input class="control" value="${b(l)}" placeholder="Filter tasks" aria-label="Filter tasks" />
715
- <select class="select" aria-label="Sort tasks">
716
- ${[["none","Manual"],["start","Start date"],["end","End date"],["label","Name"],["progress","Progress"]].map(([r,$])=>`<option value="${r}" ${n===r?"selected":""}>${$}</option>`).join("")}
1125
+ <input class="control" value="${v(o)}" placeholder="${v(t.filterPlaceholder)}" aria-label="${v(t.filterLabel)}" />
1126
+ <select class="select" aria-label="${v(t.sortLabel)}">
1127
+ ${[["none",t.sortManual],["start",t.sortStart],["end",t.sortEnd],["label",t.sortName],["progress",t.sortProgress]].map(([l,B])=>`<option value="${l}" ${a===l?"selected":""}>${v(B)}</option>`).join("")}
717
1128
  </select>
718
- ${["day","week","month","quarter","year"].map(r=>`<button class="zoom-button" data-zoom="${r}" aria-pressed="${e===r}">${r}</button>`).join("")}
1129
+ ${d?`<button class="add-button" data-action="add"><span aria-hidden="true">+</span> ${v(t.addTask)}</button>`:""}
1130
+ ${m?`<button class="today-button" data-action="today" title="${v(t.scrollToToday)}" aria-label="${v(t.scrollToToday)}"${Dt?"":" disabled"}>${v(t.today)}</button>`:""}
1131
+ ${["day","week","month","quarter","year","fit"].map(l=>`<button class="zoom-button" data-zoom="${l}" aria-pressed="${i===l}"${l==="fit"?` title="${v(t.zoomFitTitle)}"`:""}>${v(ar(l,t))}</button>`).join("")}
719
1132
  </div>
720
1133
  </header>
721
1134
  `:""}
722
1135
  <div class="viewport" part="viewport">
723
- <div class="surface" part="surface" style="--day-width:${M}px;grid-template-columns:${J}px ${k.toFixed(2)}px;inline-size:max(100%, ${(J+k).toFixed(2)}px)">
724
- <div class="grid-semantics" role="treegrid" aria-label="${b(this.getAttribute("aria-label")||"Project schedule")}" aria-rowcount="${o.length+1}" aria-colcount="4">
1136
+ <div class="surface" part="surface" style="--day-width:${q}px;grid-template-columns:var(--gantt-grid-w) minmax(${J.toFixed(2)}px, 1fr);inline-size:max(100%, calc(var(--gantt-grid-w) + ${J.toFixed(2)}px))">
1137
+ <div class="grid-semantics" role="treegrid" aria-label="${v(this.getAttribute("aria-label")||t.title)}" aria-rowcount="${c.length+1}" aria-colcount="${z?1:U.length}">
725
1138
  <div class="grid-head" part="grid-head" role="row">
726
- <div role="columnheader" aria-sort="${n==="label"?"ascending":"none"}" style="display:contents"><button class="head-button" data-sort="label">Task</button></div>
727
- <span role="columnheader">Owner</span>
728
- <div role="columnheader" aria-sort="${n==="start"?"ascending":"none"}" style="display:contents"><button class="head-button" data-sort="start">Dates</button></div>
729
- <div role="columnheader" aria-sort="${n==="progress"?"descending":"none"}" style="display:contents"><button class="head-button" data-sort="progress">%</button></div>
1139
+ ${U.map(l=>{const B=v(l.custom??t[l.title]);if(!l.sort)return`<span role="columnheader">${B}</span>`;const I=a===l.sort,Q=l.sort==="progress"?"descending":"ascending";return`<div role="columnheader" aria-sort="${I?Q:"none"}" style="display:contents"><button class="head-button" data-sort="${l.sort}">${B}</button></div>`}).join("")}
730
1140
  </div>
731
1141
  <div class="grid-body" part="grid-body" role="rowgroup">
732
- ${S&&_?`<div style="height:${_}px"></div>`:""}
733
- ${kt||'<div class="empty">No matching tasks</div>'}
734
- ${S&&j?`<div style="height:${j}px"></div>`:""}
1142
+ ${V&&rt?`<div style="height:${rt}px"></div>`:""}
1143
+ ${be||`<div class="empty">${v(t.noMatches)}</div>`}
1144
+ ${V&&it?`<div style="height:${it}px"></div>`:""}
735
1145
  </div>
736
1146
  </div>
1147
+ <div class="splitter-rail head"><div class="splitter" role="separator" aria-orientation="vertical" aria-label="${v(t.splitter)}" aria-valuemin="${P.min}" aria-valuemax="${this.gridBounds.max}" aria-valuenow="${P.width}" tabindex="0"></div></div>
1148
+ <div class="splitter-rail body"><div class="splitter" aria-hidden="true"></div></div>
737
1149
  <div class="timeline-head" part="timeline-head" aria-hidden="true">
738
- <div class="scale" style="width:${k.toFixed(2)}px">${Ht(m,h,M,e,this.viewportLeft,this.viewportWidth)}</div>
1150
+ <div class="scale" data-zoom="${K}" style="min-width:${J.toFixed(2)}px">${Je(y,gt,q,K,Pt,this.viewportLeft,this.viewportWidth,_t)}${$e}</div>
739
1151
  </div>
740
- <div class="timeline-body" part="timeline-body" role="group" aria-label="Timeline" style="width:${k.toFixed(2)}px;min-height:${A}px">
741
- <svg class="links" width="${k.toFixed(0)}" height="${A}" viewBox="0 0 ${k.toFixed(0)} ${A}" aria-hidden="true">${Mt}${et}</svg>
742
- ${St}
743
- ${S&&_?`<div style="height:${_}px"></div>`:""}
744
- ${$t}
745
- ${S&&j?`<div style="height:${j}px"></div>`:""}
1152
+ <div class="timeline-body" part="timeline-body" role="group" aria-label="${v(t.timeline)}" data-zoom="${K}" style="min-width:${J.toFixed(2)}px;min-height:${O}px">
1153
+ ${Ke(y,gt,q,_t,this.viewportLeft,this.viewportWidth)}
1154
+ ${Qe(y,gt,q,K,Pt,this.viewportLeft,this.viewportWidth)}
1155
+ <svg class="links" width="${J.toFixed(0)}" height="${O}" viewBox="0 0 ${J.toFixed(0)} ${O}" aria-hidden="true">${xe}${Ot}</svg>
1156
+ ${ke}
1157
+ ${V&&rt?`<div style="height:${rt}px"></div>`:""}
1158
+ ${ve}
1159
+ ${V&&it?`<div style="height:${it}px"></div>`:""}
1160
+ <div class="bar-tip" part="tip" aria-hidden="true"></div>
746
1161
  </div>
747
1162
  </div>
748
1163
  </div>
749
1164
  </section>
750
- `);const q=this.root.querySelector(".viewport");q&&(q.scrollTop=this.viewportTop,q.scrollLeft=this.viewportLeft,this.viewportWidth=q.clientWidth||this.viewportWidth,this.viewportHeight=q.clientHeight||this.viewportHeight),this.bindEvents()}bindEvents(){this.root.querySelectorAll("[data-task-id]").forEach(t=>{t.addEventListener("click",i=>{const e=i.target,n=i.currentTarget;if(!n.classList.contains("bar")&&e.closest(".bar"))return;if(this.drag?.moved){i.stopPropagation();return}const l=i.currentTarget.dataset.taskId;l&&(e.closest('[data-action="toggle"]')||(n.classList.contains("bar")&&i.stopPropagation(),this.selectTask(l)))})}),this.root.querySelectorAll('[data-action="toggle"]').forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation();const e=t.dataset.taskId;e&&(this.collapsed.has(e)?this.collapsed.delete(e):this.collapsed.add(e),this.requestRender())})}),this.root.querySelectorAll("[data-zoom]").forEach(t=>{t.addEventListener("click",()=>{const i=t.dataset.zoom||"week";this.setAttribute("zoom",i),this.dispatchEvent(new CustomEvent("zoomchange",{detail:{zoom:i},bubbles:!0,composed:!0}))})}),this.root.querySelectorAll(".head-button[data-sort]").forEach(t=>{t.addEventListener("click",()=>{const i=W(t.dataset.sort||null);i==="none"?this.removeAttribute("sort"):this.setAttribute("sort",i),this.dispatchEvent(new CustomEvent("sortchange",{detail:{sort:i},bubbles:!0,composed:!0}))})}),this.root.querySelector(".viewport")?.addEventListener("scroll",t=>{const i=t.currentTarget,e=i.scrollTop,n=i.scrollLeft,s=Math.max(20,Math.ceil(Math.max(420,this.viewportHeight-V)/y)),l=Math.max(0,Math.floor(Math.max(0,e-V)/y)),o=l<this.renderedFirstRow+64||l+s>this.renderedLastRow-64,p=Math.abs(n-this.viewportLeft)>=Math.max(480,this.viewportWidth*.6);this.viewportTop=e,this.viewportLeft=n,!(!o&&!p)&&this.scrollFrame==null&&(this.scrollFrame=window.setTimeout(()=>{this.scrollFrame=null,this.requestRender()},24))},{passive:!0}),this.root.querySelector(".control")?.addEventListener("input",t=>{this.internalFilter=t.currentTarget.value,this.dispatchEvent(new CustomEvent("filterchange",{detail:{filter:this.internalFilter},bubbles:!0,composed:!0})),this.requestRender()}),this.root.querySelector(".select")?.addEventListener("change",t=>{const i=W(t.currentTarget.value);i==="none"?this.removeAttribute("sort"):this.setAttribute("sort",i),this.dispatchEvent(new CustomEvent("sortchange",{detail:{sort:i},bubbles:!0,composed:!0}))}),this.root.querySelectorAll(".link-hit").forEach(t=>{t.addEventListener("click",i=>{i.stopPropagation(),this.dispatchEvent(new CustomEvent("linkselect",{detail:{id:t.dataset.linkId||"",source:t.dataset.sourceId||"",target:t.dataset.targetId||"",type:t.dataset.linkType||"e2s"},bubbles:!0,composed:!0}))})}),!this.hasAttribute("readonly")&&this.root.querySelectorAll('.bar[data-draggable="true"]').forEach(t=>{t.addEventListener("pointerdown",e=>{if(e.button!==0)return;const n=t.dataset.taskId;if(!n)return;const l=this.getTasks().find(h=>h.id===n),o=f(l?.start),p=f(l?.end);if(!l||o==null||p==null)return;e.preventDefault();const u=t.dataset.kind||"task",d=e.target.dataset.mode||"move",g=u==="milestone"?"move":d,c=bt(this.getAttribute("zoom")),m=this.selectedId!==n;this.selectedId=n,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:n},bubbles:!0,composed:!0})),this.drag={taskId:n,mode:g,startX:e.clientX,originalStart:o,originalEnd:p,kind:u,rangeMin:this.rangeMin(),dayWidth:gt[c],latestStart:o,latestEnd:p,frame:null,bar:t,moved:!1,selectedChanged:m},t.classList.add("dragging"),t.setPointerCapture(e.pointerId)}),t.addEventListener("pointermove",e=>{if(!this.drag||this.drag.taskId!==t.dataset.taskId)return;e.preventDefault();const n=e.clientX-this.drag.startX;Math.abs(n)>2&&(this.drag.moved=!0);let s=this.drag.originalStart,l=this.drag.originalEnd;if(this.drag.mode==="move"){const o=Math.round(n/this.drag.dayWidth);s=x(this.drag.originalStart,o),l=this.drag.kind==="milestone"?s:x(this.drag.originalEnd,o)}else if(this.drag.mode==="resize-start"){const o=Math.round(n/this.drag.dayWidth);s=Math.min(x(this.drag.originalStart,o),x(l,-1))}else{const o=Math.round(n/this.drag.dayWidth);l=Math.max(x(this.drag.originalEnd,o),x(s,1))}this.drag.latestStart=s,this.drag.latestEnd=l,this.drag.frame==null&&(this.drag.frame=requestAnimationFrame(()=>{if(!this.drag)return;this.drag.frame=null;const o=(this.drag.latestStart-this.drag.rangeMin)/I*this.drag.dayWidth-(this.drag.kind==="milestone"?N/2:0),p=this.drag.kind==="milestone"?N:Math.max(12,(this.drag.latestEnd-this.drag.latestStart)/I*this.drag.dayWidth);this.drag.bar.style.left=`${o.toFixed(2)}px`,this.drag.bar.style.width=`${p.toFixed(2)}px`;const u=this.drag.bar.querySelector(".drag-tip");u&&(u.textContent=this.drag.kind==="milestone"?E(this.drag.latestStart):`${E(this.drag.latestStart)} - ${E(this.drag.latestEnd)}`)}))});const i=()=>{if(!this.drag)return;this.drag.frame!=null&&cancelAnimationFrame(this.drag.frame);const e=this.drag;if(e.bar.classList.remove("dragging"),this.drag=null,!e.moved){e.selectedChanged&&this.requestRender();return}const n={id:e.taskId,start:E(e.latestStart),end:E(e.latestEnd)};this.overrides.set(e.taskId,{start:n.start,end:n.end}),this.bumpOverrides(),this.dispatchEvent(new CustomEvent("taskchange",{detail:n,bubbles:!0,composed:!0})),this.requestRender()};t.addEventListener("pointerup",i),t.addEventListener("pointercancel",i),t.addEventListener("keydown",e=>{const n=t.dataset.taskId;if(!n)return;if(e.key==="Delete"||e.key==="Backspace"){e.preventDefault(),this.dispatchEvent(new CustomEvent("taskdelete",{detail:{id:n},bubbles:!0,composed:!0}));return}if(e.key==="Enter"||e.key===" "){e.preventDefault(),this.selectTask(n);return}if(e.key==="ArrowUp"||e.key==="ArrowDown"){e.preventDefault(),this.selectAdjacentTask(n,e.key==="ArrowDown"?1:-1);return}if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const l=this.getTasks().find(h=>h.id===n),o=f(l?.start),p=f(l?.end);if(!l||o==null||p==null)return;e.preventDefault();const u=e.key==="ArrowLeft"?-1:1,d=t.dataset.kind==="milestone",g=e.shiftKey&&!d?o:x(o,u),c=d?g:e.shiftKey?Math.max(x(p,u),x(o,1)):x(p,u),m={id:n,start:E(g),end:E(c)};this.overrides.set(n,{start:m.start,end:m.end}),this.bumpOverrides(),this.dispatchEvent(new CustomEvent("taskchange",{detail:m,bubbles:!0,composed:!0})),this.requestRender()})})}rangeMin(){const i=this.getTasks().map(e=>f(e.start)).filter(e=>e!=null);return i.length?x(Math.min(...i),-2):F(Date.now())}selectTask(t){if(this.captureViewport(),this.selectedId===t){this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:t},bubbles:!0,composed:!0}));return}this.selectedId=t,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:t},bubbles:!0,composed:!0})),this.requestRender()}selectAdjacentTask(t,i){const e=this.getVisibleTasks(this.getTasks(),this.getAttribute("filter")??this.internalFilter,W(this.getAttribute("sort"))),n=e.findIndex(l=>l.id===t),s=e[Math.max(0,Math.min(e.length-1,n+i))];!s||s.id===t||(this.selectedId=s.id,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:s.id},bubbles:!0,composed:!0})),this.requestRender(),window.requestAnimationFrame(()=>{this.root.querySelector(`.bar[data-task-id="${CSS.escape(s.id)}"]`)?.focus()}))}captureViewport(){const t=this.root.querySelector(".viewport");t&&(this.viewportTop=t.scrollTop,this.viewportLeft=t.scrollLeft,this.viewportWidth=t.clientWidth||this.viewportWidth,this.viewportHeight=t.clientHeight||this.viewportHeight)}getTasks(){const t=this.getAttribute("tasks");return t===this.taskCacheRaw&&this.taskCacheVersion===this.overridesVersion?this.taskCache:(this.taskCacheRaw=t,this.taskCacheVersion=this.overridesVersion,this.taskCache=Ft(t,this.overrides),this.visibleCacheKey="",this.taskCache)}getLinks(){const t=this.getAttribute("links");return t===this.linkCacheRaw?this.linkCache:(this.linkCacheRaw=t,this.linkCache=Rt(t),this.linkCache)}getVisibleTasks(t,i,e){const n=Array.from(this.collapsed).sort().join(","),s=`${this.taskCacheRaw||""}|${this.overridesVersion}|${i}|${e}|${n}`;return s===this.visibleCacheKey?this.visibleCache:(this.visibleCacheKey=s,this.visibleCache=Nt(t,this.collapsed,i,e),this.visibleCache)}bumpOverrides(){this.overridesVersion+=1,this.taskCacheVersion=-1,this.visibleCacheKey=""}shouldRenderOnAttributeChange(t,i,e){return t==="tasks"&&(this.overrides.clear(),this.bumpOverrides(),this.viewportTop=0,this.viewportLeft=0),t==="links"&&(this.linkCacheRaw=null),!0}}typeof customElements<"u"&&!customElements.get("ui-gantt")&&customElements.define("ui-gantt",wt);exports.UIGantt=wt;
1165
+ `);const j=this.root.querySelector(".viewport");if(j){this.root.querySelector(".frame")!==Vt&&(j.scrollTop=this.viewportTop,j.scrollLeft=this.viewportLeft,this.smoothTarget&&typeof j.scrollTo=="function"&&j.scrollTo({...this.smoothTarget,behavior:"smooth"})),this.viewportWidth=j.clientWidth||this.viewportWidth,this.viewportHeight=j.clientHeight||this.viewportHeight;const l=Math.max(0,j.offsetWidth-j.clientWidth);l!==this.scrollbarWidth&&(this.scrollbarWidth=l,st&&this.requestRender())}if(this.root.querySelector(".frame")!==Vt&&this.bindEvents(),this.restoreFocus(Me),j&&j.clientWidth>0&&this.initialScrollPending&&(this.initialScrollPending=!1,this.getAttribute("initial-scroll")!=="start"&&!st&&m&&Dt&&Ct>j.clientWidth-lt-48&&this.scrollToDate("today",{behavior:"auto"})),this.pendingReveal){const l=this.pendingReveal;this.pendingReveal=null,this.reveal(l.id,l.behavior)}}captureFocus(){const t=this.root.activeElement;if(!t)return null;const e=er(t);if(!e)return null;const r={selector:e};return t instanceof HTMLInputElement&&(r.selection=[t.selectionStart,t.selectionEnd,t.selectionDirection]),r}restoreFocus(t){if(!t)return;const e=this.root.querySelector(t.selector);if(!e&&t.reveal&&(t.retries??0)<5){this.focusRequest={...t,retries:(t.retries??0)+1};return}if(!(!e||this.root.activeElement===e)&&(e.focus({preventScroll:!t.reveal}),t.selectAll&&e instanceof HTMLInputElement&&e.select(),t.selection&&e instanceof HTMLInputElement))try{e.setSelectionRange(t.selection[0],t.selection[1],t.selection[2]??void 0)}catch{}}bindEvents(){this.root.querySelectorAll("[data-task-id]").forEach(t=>{t.addEventListener("click",e=>{const r=e.target,i=e.currentTarget;if(!i.classList.contains("bar")&&r.closest(".bar"))return;if(this.drag?.moved){e.stopPropagation();return}const s=e.currentTarget.dataset.taskId;s&&(r.closest('[data-action="toggle"]')||(i.classList.contains("bar")&&e.stopPropagation(),this.selectTask(s)))})}),this.root.querySelectorAll('[data-action="toggle"]').forEach(t=>{t.addEventListener("click",e=>{e.stopPropagation();const r=t.dataset.taskId;r&&this.toggleTask(r)})}),this.root.querySelector(".today-button")?.addEventListener("click",()=>{this.scrollToDate("today",{behavior:"smooth",align:"center"})}),this.root.querySelectorAll(".zoom-button[data-zoom]").forEach(t=>{t.addEventListener("click",()=>{const e=t.dataset.zoom||"week";this.setAttribute("zoom",e),this.dispatchEvent(new CustomEvent("zoomchange",{detail:{zoom:e},bubbles:!0,composed:!0}))})}),this.root.querySelectorAll(".head-button[data-sort]").forEach(t=>{t.addEventListener("click",()=>{const e=bt(t.dataset.sort||null);e==="none"?this.removeAttribute("sort"):this.setAttribute("sort",e),this.dispatchEvent(new CustomEvent("sortchange",{detail:{sort:e},bubbles:!0,composed:!0}))})});for(const t of["wheel","pointerdown","touchstart","keydown"])this.root.querySelector(".viewport")?.addEventListener(t,()=>{this.smoothTarget=null},{passive:!0});this.root.querySelector(".viewport")?.addEventListener("scroll",t=>{const e=t.currentTarget,r=e.scrollTop,i=e.scrollLeft,a=Math.max(20,Math.ceil(Math.max(420,this.viewportHeight-N)/S)),s=Math.max(0,Math.floor(Math.max(0,r-N)/S)),o=this.virtualizedNow&&(s<this.renderedFirstRow+64||s+a>this.renderedLastRow-64),c=Math.abs(i-this.renderedLeft)>=400;this.viewportTop=r,this.viewportLeft=i;const h=this.smoothTarget;h&&(h.left==null||Math.abs(i-h.left)<2)&&(h.top==null||Math.abs(r-h.top)<2)&&(this.smoothTarget=null),!(this.drag||this.linking||!o&&!c)&&this.scrollFrame==null&&(this.scrollFrame=window.setTimeout(()=>{this.scrollFrame=null,this.requestRender()},24))},{passive:!0}),this.root.querySelector(".control")?.addEventListener("input",t=>{this.internalFilter=t.currentTarget.value,this.dispatchEvent(new CustomEvent("filterchange",{detail:{filter:this.internalFilter},bubbles:!0,composed:!0})),this.requestRender()}),this.root.querySelector(".select")?.addEventListener("change",t=>{const e=bt(t.currentTarget.value);e==="none"?this.removeAttribute("sort"):this.setAttribute("sort",e),this.dispatchEvent(new CustomEvent("sortchange",{detail:{sort:e},bubbles:!0,composed:!0}))}),this.bindLinks(),this.root.querySelectorAll(".bar").forEach(t=>{t.addEventListener("keydown",e=>this.handleBarKeydown(t,e))}),this.bindTooltips(),this.bindSplitters(),this.bindRows(),this.bindEditing(),!this.hasAttribute("readonly")&&this.root.querySelectorAll('.bar[data-draggable="true"]').forEach(t=>{t.addEventListener("pointerdown",e=>this.startDrag(t,e)),t.addEventListener("pointermove",e=>{!this.drag||this.drag.bar!==t||(e.preventDefault(),this.drag.lastClientX=e.clientX,this.updateDrag())}),t.addEventListener("pointerup",()=>this.endDrag(!0)),t.addEventListener("pointercancel",()=>this.endDrag(!1))})}snapUnit(){const t=this.getAttribute("snap");return t==="week"||t==="month"?t:"day"}snapDate(t){const e=this.snapUnit();if(e==="day")return t;const r=Ft(this.getAttribute("week-start")),i=ue(t,e,r),a=pe(i,e);return t-i<a-t?i:a}startDrag(t,e){if(e.button!==0)return;const r=t.dataset.taskId;if(!r)return;const i=this.getTasks().find(u=>u.id===r),a=$(i?.start),s=$(i?.end);if(!i||a==null||s==null)return;e.preventDefault();const o=t.dataset.kind||"task",c=e.target.dataset.mode||"move",h=o==="milestone"?"move":c,d=this.selectedId!==r;this.selectedId=r,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:r},bubbles:!0,composed:!0}));const g=u=>{u.key==="Escape"&&(u.preventDefault(),u.stopPropagation(),this.endDrag(!1))};this.drag={taskId:r,mode:h,startX:e.clientX,startScroll:this.root.querySelector(".viewport")?.scrollLeft??0,lastClientX:e.clientX,originalStart:a,originalEnd:s,kind:o,rangeMin:this.rangeMin(),dayWidth:this.dayWidthNow,latestStart:a,latestEnd:s,frame:null,scrollFrame:null,bar:t,originalLeft:t.style.left,originalWidth:t.style.width,moved:!1,selectedChanged:d,onKey:g},window.addEventListener("keydown",g,!0),t.classList.add("dragging"),t.setPointerCapture(e.pointerId),this.autoScrollLoop()}updateDrag(){const t=this.drag;if(!t)return;const e=this.root.querySelector(".viewport"),r=t.lastClientX-t.startX+(e?e.scrollLeft-t.startScroll:0);Math.abs(r)>2&&(t.moved=!0);const i=Math.round(r/t.dayWidth);let a=t.originalStart,s=t.originalEnd;if(t.mode==="move"){const o=Math.round((this.snapDate(A(t.originalStart,i))-t.originalStart)/D);a=A(t.originalStart,o),s=t.kind==="milestone"?a:A(t.originalEnd,o)}else t.mode==="resize-start"?a=Math.min(this.snapDate(A(t.originalStart,i)),A(s,-1)):s=Math.max(this.snapDate(A(t.originalEnd,i)),A(a,1));t.latestStart=a,t.latestEnd=s,t.frame==null&&(t.frame=requestAnimationFrame(()=>{const o=this.drag;if(!o)return;o.frame=null;const c=(o.latestStart-o.rangeMin)/D*o.dayWidth-(o.kind==="milestone"?vt/2:0),h=o.kind==="milestone"?vt:Math.max(12,(o.latestEnd-o.latestStart)/D*o.dayWidth);o.bar.style.left=`${c.toFixed(2)}px`,o.bar.style.width=`${h.toFixed(2)}px`,Lt=this.getAttribute("locale")||void 0;const d=Z({dateStyle:"medium"}),g=this.labelSet();this.showTip(o.bar,o.kind==="milestone"?d.format(new Date(o.latestStart)):`${d.format(new Date(o.latestStart))} ${g.to} ${d.format(new Date(o.latestEnd))}`)}))}autoScrollLoop(){const t=this.drag;t&&(t.scrollFrame=requestAnimationFrame(()=>{const e=this.drag;if(!e)return;const r=this.root.querySelector(".viewport");if(r&&r.clientWidth>0&&e.moved){const i=r.getBoundingClientRect(),a=56,s=Math.max(i.left,this.root.querySelector(".grid-body")?.getBoundingClientRect().right??i.left);let o=0;e.lastClientX>i.right-a?o=(e.lastClientX-(i.right-a))/a:e.lastClientX<s+a&&r.scrollLeft>0&&(o=-(s+a-e.lastClientX)/a),o&&(r.scrollLeft+=Math.max(-1.5,Math.min(1.5,o))*16,this.updateDrag())}this.autoScrollLoop()}))}endDrag(t){const e=this.drag;if(!e)return;e.frame!=null&&cancelAnimationFrame(e.frame),e.scrollFrame!=null&&cancelAnimationFrame(e.scrollFrame),window.removeEventListener("keydown",e.onKey,!0),e.bar.classList.remove("dragging"),this.drag=null,this.hideTip();const r=()=>{e.bar.style.left=e.originalLeft,e.bar.style.width=e.originalWidth};if(!e.moved){e.selectedChanged&&this.requestRender();return}if(!t){r(),this.requestRender();return}if(e.latestStart===e.originalStart&&e.latestEnd===e.originalEnd){r();return}this.applyChanges(this.plan({id:e.taskId,start:e.latestStart,end:e.latestEnd,previousStart:e.originalStart,previousEnd:e.originalEnd}),e.mode==="move"?"drag":"resize")||r()}plan(t){const e=this.withCascade(t);if(ie(this.getAttribute("schedule"))!=="auto")return e;const r=this.getLinks();if(!r.length)return e;const i=this.getTasks().map(yt).filter(c=>c!=null),a=new Map(i.map(c=>[c.id,c])),s=new Map(e.map(c=>[c.id,{start:c.start,end:c.end}])),o=[...e];for(const c of Ie(i,r.map(Wt),s,this.hasAttribute("cascade"))){const h=o.findIndex(d=>d.id===c.id);if(h>=0)o[h]={...o[h],start:c.start,end:c.end};else{const d=a.get(c.id);d&&o.push({id:c.id,start:c.start,end:c.end,previousStart:d.start,previousEnd:d.end})}}return o}withCascade(t){if(!this.hasAttribute("cascade"))return[t];const e=wt(t.previousStart,t.start);if(e===0||t.end-t.start!==t.previousEnd-t.previousStart)return[t];const r=this.getTasks(),i=de(r.map(yt).filter(s=>s!=null),t.id);if(!i.length)return[t];const a=i.filter(s=>!s.readonly).map(s=>({id:s.id,start:H(s.start,e),end:H(s.end,e),previousStart:s.start,previousEnd:s.end}));return[t,...a]}applyChanges(t,e){const[r,...i]=t,a=o=>({id:o.id,start:W(o.start),end:W(o.end),previousStart:W(o.previousStart),previousEnd:W(o.previousEnd)});if(!this.dispatchEvent(new CustomEvent("beforetaskchange",{detail:{...a(r),source:e,affected:i.map(a)},bubbles:!0,composed:!0,cancelable:!0})))return this.requestRender(),!1;for(const o of t)this.overrides.set(o.id,{...this.overrides.get(o.id),start:W(o.start),end:W(o.end)});this.bumpOverrides();for(const o of t)this.dispatchEvent(new CustomEvent("taskchange",{detail:{id:o.id,start:W(o.start),end:W(o.end)},bubbles:!0,composed:!0}));return this.requestRender(),!0}handleBarKeydown(t,e){const r=t.dataset.taskId;if(!r)return;const i=t.dataset.draggable==="true"&&!this.hasAttribute("readonly");if(e.key==="Escape"){this.hideTip();return}if(e.key==="F2"){e.preventDefault(),this.startRename(r);return}if(e.key==="Enter"||e.key===" "){e.preventDefault(),this.selectTask(r);return}if(["ArrowUp","ArrowDown","Home","End","PageUp","PageDown"].includes(e.key)){e.preventDefault(),this.navigate(r,e.key,"bar");return}if(!i)return;if(e.key==="Delete"||e.key==="Backspace"){e.preventDefault(),this.dispatchEvent(new CustomEvent("taskdelete",{detail:{id:r},bubbles:!0,composed:!0}));return}if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const a=this.getTasks().find(b=>b.id===r),s=$(a?.start),o=$(a?.end);if(!a||s==null||o==null)return;e.preventDefault();const c=e.key==="ArrowLeft"?-1:1,h=t.dataset.kind==="milestone",d=e.shiftKey&&!h&&t.dataset.kind!=="summary",g=d?s:A(s,c),u=h?g:d?Math.max(A(o,c),A(s,1)):A(o,c);this.applyChanges(this.plan({id:r,start:g,end:u,previousStart:s,previousEnd:o}),"keyboard")}showTip(t,e){const r=this.root.querySelector(".bar-tip"),i=this.root.querySelector(".timeline-body"),a=this.root.querySelector(".viewport"),s=this.root.querySelector(".grid-body"),o=this.descriptions.get(t.dataset.taskId||"");if(!r||!i||!a||!o)return;r.innerHTML=`<strong>${v(o.title)}</strong><span>${v(e?[o.kindWord,e].filter(Boolean).join(" · "):o.when)}</span>`+(o.more?`<span>${v(o.more)}</span>`:""),r.setAttribute("data-open","");const c=i.getBoundingClientRect(),h=t.getBoundingClientRect(),d=a.getBoundingClientRect(),g=Math.max(d.left,s?s.getBoundingClientRect().right:d.left)+4,u=d.right-4,b=r.offsetWidth,m=r.offsetHeight,p=(Math.max(h.left,g)+Math.min(h.right,u))/2,k=Math.max(g,Math.min(p-b/2,u-b)),w=h.top-(d.top+N)>=m+8?h.top-m-6:h.bottom+6;r.style.left=`${(k-c.left).toFixed(1)}px`,r.style.top=`${(w-c.top).toFixed(1)}px`}hideTip(){this.tipTimer!=null&&(window.clearTimeout(this.tipTimer),this.tipTimer=null),this.root.querySelector(".bar-tip")?.removeAttribute("data-open")}bindLinks(){const t=e=>({id:e.dataset.linkId||"",source:e.dataset.sourceId||"",target:e.dataset.targetId||"",type:e.dataset.linkType||"e2s"});this.root.querySelectorAll(".link-hit").forEach(e=>{e.addEventListener("click",r=>{r.stopPropagation(),this.selectedLinkId=e.dataset.linkId||null,this.focusRequest={selector:`.link-hit[data-link-id="${ot(e.dataset.linkId||"")}"]`},this.dispatchEvent(new CustomEvent("linkselect",{detail:t(e),bubbles:!0,composed:!0})),this.requestRender()}),e.addEventListener("keydown",r=>{if(r.key==="Delete"||r.key==="Backspace"){if(this.hasAttribute("readonly"))return;r.preventDefault(),this.dispatchEvent(new CustomEvent("linkdelete",{detail:t(e),bubbles:!0,composed:!0}))}else r.key==="Enter"||r.key===" "?(r.preventDefault(),this.dispatchEvent(new CustomEvent("linkselect",{detail:t(e),bubbles:!0,composed:!0}))):r.key==="Escape"&&(this.selectedLinkId=null,this.requestRender())})}),this.root.querySelectorAll(".connector").forEach(e=>{e.addEventListener("pointerdown",r=>this.startLink(e,r)),e.addEventListener("pointermove",r=>this.updateLink(r)),e.addEventListener("pointerup",()=>this.endLink(!0)),e.addEventListener("pointercancel",()=>this.endLink(!1))})}startLink(t,e){if(e.button!==0)return;const r=t.dataset.taskId,i=t.dataset.side==="start"?"start":"end",a=this.root.querySelector(".timeline-body"),s=this.root.querySelector("svg.links"),o=r?this.root.querySelector(At(r)):null;if(!r||!a||!s||!o)return;e.preventDefault();const c=a.getBoundingClientRect(),h=o.getBoundingClientRect(),d=document.createElementNS("http://www.w3.org/2000/svg","path");d.setAttribute("class","link-draft"),s.appendChild(d);const g=u=>{u.key==="Escape"&&(u.preventDefault(),u.stopPropagation(),this.endLink(!1))};this.linking={sourceId:r,side:i,fromX:(i==="start"?h.left:h.right)-c.left,fromY:h.top+h.height/2-c.top,draft:d,targetId:null,targetSide:null,onKey:g},window.addEventListener("keydown",g,!0),this.root.querySelector(".frame")?.setAttribute("data-linking",""),t.setPointerCapture(e.pointerId),this.updateLink(e)}updateLink(t){const e=this.linking,r=this.root.querySelector(".timeline-body");if(!e||!r)return;const i=r.getBoundingClientRect();e.draft.setAttribute("d",`M ${e.fromX.toFixed(1)} ${e.fromY.toFixed(1)} L ${(t.clientX-i.left).toFixed(1)} ${(t.clientY-i.top).toFixed(1)}`),this.root.querySelectorAll(".bar.link-target").forEach(d=>{d.classList.remove("link-target"),d.removeAttribute("data-link-side")}),e.targetId=null,e.targetSide=null;const a=this.root.elementFromPoint(t.clientX,t.clientY),s=a?.closest?.(".connector"),o=s?this.root.querySelector(At(s.dataset.taskId||"")):a?.closest?.(".bar"),c=o?.dataset.taskId;if(!o||!c||c===e.sourceId)return;const h=o.getBoundingClientRect();e.targetId=c,e.targetSide=s?s.dataset.side==="start"?"start":"end":t.clientX<h.left+h.width/2?"start":"end",o.classList.add("link-target"),o.setAttribute("data-link-side",e.targetSide)}endLink(t){const e=this.linking;if(!e||(window.removeEventListener("keydown",e.onKey,!0),this.linking=null,e.draft.remove(),this.root.querySelector(".frame")?.removeAttribute("data-linking"),this.root.querySelectorAll(".bar.link-target").forEach(i=>{i.classList.remove("link-target"),i.removeAttribute("data-link-side")}),!t||!e.targetId||!e.targetSide))return;const r=`${e.side==="start"?"s":"e"}2${e.targetSide==="start"?"s":"e"}`;this.getLinks().some(i=>i.source===e.sourceId&&i.target===e.targetId&&(i.type||"e2s")===r)||this.dispatchEvent(new CustomEvent("linkcreate",{detail:{source:e.sourceId,target:e.targetId,type:r},bubbles:!0,composed:!0}))}startRename(t){if(this.hasAttribute("readonly"))return;const e=this.getTasks().find(r=>r.id===t);!e||e.readonly||(this.editingId=t,this.editingValue=e.label,this.focusRequest={selector:".rename",reveal:!0,retries:0,selectAll:!0},this.reveal(t,"auto"),this.requestRender())}finishRename(t){const e=this.editingId;if(!e)return;const r=this.editingValue.trim(),i=this.getTasks().find(a=>a.id===e)?.label;this.editingId=null,t&&r&&i!=null&&r!==i&&this.dispatchEvent(new CustomEvent("taskrename",{detail:{id:e,label:r,previousLabel:i},bubbles:!0,composed:!0,cancelable:!0}))&&(this.overrides.set(e,{...this.overrides.get(e),label:r}),this.bumpOverrides()),this.focusRequest={selector:Nt(e)},this.requestRender()}requestCreate(t,e){const r=e?this.getTasks().find(i=>i.id===e):void 0;this.dispatchEvent(new CustomEvent("taskcreate",{detail:{start:W(t),end:W(A(t,He)),parent:r?.parent,after:r?.id},bubbles:!0,composed:!0}))}bindEditing(){this.root.querySelectorAll(".grid-row .task-name").forEach(e=>{e.addEventListener("dblclick",r=>{if(r.target.closest(".expander, .rename"))return;const i=e.closest(".grid-row")?.dataset.taskId;i&&this.startRename(i)})});const t=this.root.querySelector(".rename");t&&(t.addEventListener("input",()=>{this.editingValue=t.value}),t.addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Enter"?(e.preventDefault(),this.finishRename(!0)):e.key==="Escape"&&(e.preventDefault(),this.finishRename(!1))}),t.addEventListener("blur",()=>{this.suppressBlur||this.finishRename(!0)})),this.root.querySelector(".add-button")?.addEventListener("click",()=>{const{min:e,rangeEnd:r}=this.layoutInfo,i=Y(Date.now());this.requestCreate(i>=e&&i<=r?i:e,this.selectedId??void 0)}),this.hasAttribute("creatable")&&!this.hasAttribute("readonly")&&this.root.querySelectorAll(".timeline-row").forEach(e=>{e.addEventListener("dblclick",r=>{if(r.target!==e)return;const i=this.root.querySelector(".timeline-body");if(!i)return;const{min:a,dayWidth:s}=this.layoutInfo,o=Math.floor((r.clientX-i.getBoundingClientRect().left)/s);this.requestCreate(A(a,o),e.dataset.taskId)})})}bindRows(){this.root.querySelectorAll(".grid-row").forEach(t=>{t.addEventListener("keydown",e=>{if(e.target!==t)return;const r=t.dataset.taskId;if(r){if(e.key==="Enter"||e.key===" "){e.preventDefault(),this.selectTask(r);return}if(e.key==="F2"){e.preventDefault(),this.startRename(r);return}this.navigate(r,e.key,"row")&&e.preventDefault()}})})}bindSplitters(){const t=this.root.querySelector(".surface"),e=this.root.querySelectorAll(".splitter"),r=i=>{const a=Math.round(Math.max(this.gridBounds.min,Math.min(this.gridBounds.max,i)));a!==this.gridBounds.width&&(this.setAttribute("grid-width",String(a)),this.dispatchEvent(new CustomEvent("gridresize",{detail:{width:a},bubbles:!0,composed:!0})))};e.forEach(i=>{i.addEventListener("pointerdown",a=>{if(a.button!==0||!t)return;a.preventDefault();const s=a.clientX,{min:o,max:c,width:h}=this.gridBounds;let d=h;i.setPointerCapture(a.pointerId),e.forEach(b=>b.classList.add("dragging"));const g=b=>{d=Math.max(o,Math.min(c,h+b.clientX-s)),t.style.setProperty("--gantt-grid-w",`${d}px`)},u=b=>{if(i.removeEventListener("pointermove",g),i.removeEventListener("pointerup",u),i.removeEventListener("pointercancel",u),e.forEach(m=>m.classList.remove("dragging")),b.type==="pointercancel"){t.style.removeProperty("--gantt-grid-w");return}r(d)};i.addEventListener("pointermove",g),i.addEventListener("pointerup",u),i.addEventListener("pointercancel",u)}),i.addEventListener("keydown",a=>{if(i.getAttribute("role")!=="separator")return;const s=a.shiftKey?64:16,{min:o,max:c,width:h}=this.gridBounds,d=a.key==="ArrowLeft"?h-s:a.key==="ArrowRight"?h+s:a.key==="Home"?o:a.key==="End"?c:null;d!=null&&(a.preventDefault(),r(d))})})}bindTooltips(){this.root.querySelectorAll(".bar").forEach(t=>{t.addEventListener("pointerenter",e=>{e.pointerType!=="touch"&&(this.hideTip(),this.tipTimer=window.setTimeout(()=>{this.tipTimer=null,this.showTip(t)},150))}),t.addEventListener("pointerleave",()=>this.hideTip()),t.addEventListener("pointerdown",()=>{this.pointerFocus=!0,window.setTimeout(()=>{this.pointerFocus=!1},0),this.hideTip()}),t.addEventListener("blur",()=>this.hideTip()),t.addEventListener("focus",()=>{this.pointerFocus||this.showTip(t)})})}get tasks(){return qt(this.getAttribute("tasks"))}set tasks(t){ne(this,"tasks",t,!0)}get holidays(){return qt(this.getAttribute("holidays"))}set holidays(t){if(!Array.isArray(t)){this.removeAttribute("holidays");return}try{this.setAttribute("holidays",JSON.stringify(t.map(e=>e&&typeof e=="object"&&!(e instanceof Date)?{...e,date:xt(e.date)}:xt(e))))}catch{}}get links(){return qt(this.getAttribute("links"))}set links(t){ne(this,"links",t,!1)}resolveBehavior(t){return t==="smooth"&&typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches?"auto":t??"auto"}scrollViewport(t,e){const r=this.root.querySelector(".viewport");if(!r)return;const i=this.resolveBehavior(e);if(this.smoothTarget=i==="smooth"?t:null,this.smoothTarget){const a=this.smoothTarget;window.setTimeout(()=>{this.smoothTarget===a&&(this.smoothTarget=null)},2e3)}if(i!=="smooth"&&(t.left!=null&&(this.viewportLeft=t.left),t.top!=null&&(this.viewportTop=t.top)),typeof r.scrollTo=="function"){r.scrollTo({...t,behavior:i});return}t.left!=null&&(r.scrollLeft=t.left),t.top!=null&&(r.scrollTop=t.top)}scrollToDate(t,e={}){const r=t==="today"?Y(Date.now()):typeof t=="number"?Number.isFinite(t)?Y(t):null:$(t),i=this.root.querySelector(".viewport");r==null||!i||this.scrollViewport({left:this.leftFor(i,r,e.align??"center")},e.behavior)}leftFor(t,e,r){const{min:i,dayWidth:a,gridWidth:s}=this.layoutInfo,o=(e-i)/D*a,c=r==="start"?o-24:o-Math.max(0,t.clientWidth-s)/2;return Math.max(0,Math.min(c,Math.max(0,t.scrollWidth-t.clientWidth)))}scrollToTask(t,e={}){const r=this.getTasks(),i=new Map(r.map(d=>[d.id,d])),a=i.get(t);if(!a)return!1;let s=!1,o=a.parent;for(let d=0;o&&d<1e3;d+=1)this.collapsed.has(o)&&(this.collapsed.delete(o),this.dispatchEvent(new CustomEvent("tasktoggle",{detail:{id:o,open:!0},bubbles:!0,composed:!0})),s=!0),o=i.get(o)?.parent;const c=this.getAttribute("filter")??this.internalFilter;return this.getVisibleTasks(r,c,bt(this.getAttribute("sort"))).some(d=>d.id===t)?s||!this.visibleIds.includes(t)?(this.pendingReveal={id:t,behavior:e.behavior??"auto"},this.requestRender(),!0):this.reveal(t,e.behavior??"auto"):!1}reveal(t,e){const r=this.visibleIds.indexOf(t),i=this.root.querySelector(".viewport"),a=this.getTasks().find(g=>g.id===t);if(r<0||!i||!a)return!1;const s={},o=N+r*S;if(!(o>=i.scrollTop+N&&o+S<=i.scrollTop+i.clientHeight)){const g=r*S+S/2-(i.clientHeight-N)/2;s.top=Math.max(0,Math.min(g,Math.max(0,i.scrollHeight-i.clientHeight)))}const h=$(a.start),d=$(a.end);if(h!=null){const{min:g,dayWidth:u,gridWidth:b}=this.layoutInfo,m=(h-g)/D*u,p=((d??h)-g)/D*u,k=i.scrollLeft;(m<k||p>k+i.clientWidth-b)&&(s.left=this.leftFor(i,h,"start"))}return(s.left!=null||s.top!=null)&&this.scrollViewport(s,e),!0}toggleTask(t,e){const r=!this.collapsed.has(t),i=e??!r;i!==r&&(i?this.collapsed.delete(t):this.collapsed.add(t),this.dispatchEvent(new CustomEvent("tasktoggle",{detail:{id:t,open:i},bubbles:!0,composed:!0})),this.requestRender())}expandAll(){for(const t of[...this.collapsed])this.toggleTask(t,!0)}collapseAll(){const t=new Set(this.getTasks().map(e=>e.parent).filter(e=>!!e));for(const e of t)this.toggleTask(e,!1)}exportSvg(){Lt=this.getAttribute("locale")||void 0;const t=this.labelSet(),e=this.getTasks(),{min:r,dayWidth:i}=this.layoutInfo;if(!e.length||r===0)return"";const a=this.getVisibleTasks(e,this.getAttribute("filter")??this.internalFilter,bt(this.getAttribute("sort")));if(!a.length)return"";const s=getComputedStyle(this),o=f=>{const E=/^var\((--[\w-]+),\s*([^)]+)\)$/.exec(f);return E?s.getPropertyValue(E[1]).trim()||E[2].trim():f},c=o("var(--ui-color-text, #0f172a)"),h=o("var(--ui-color-muted, #526175)"),d=o("var(--ui-color-border, #cbd5e1)"),g=o("var(--ui-color-surface, #ffffff)");o("var(--ui-color-primary, #2563eb)");const u=o("var(--ui-color-danger, #dc2626)"),b=this.root.querySelector(".scale")?.getAttribute("data-zoom")||"week",m=Ft(this.getAttribute("week-start")),p=te(this.getAttribute("non-working-days"),this.getAttribute("holidays")),k=A(Math.max(...e.map(f=>$(f.end)??0)),3),y=Math.max(320,(k-r)/D*i),w=r+y/i*D,x=260,M=x+y,T=N+a.length*S,z=f=>(f-r)/D*i,U=Z({dateStyle:"medium"}),P=Z({month:"long",year:"numeric"}),lt=Z({month:"short"}),st=(f,E)=>{const L=new Date(f);return E==="day"||E==="week"?String(L.getDate()):E==="month"?lt.format(L):E==="quarter"?`Q${Math.floor(L.getMonth()/3)+1}`:String(L.getFullYear())},R=[],q=(f,E,L,_,G)=>`<rect x="${f.toFixed(1)}" y="${E.toFixed(1)}" width="${Math.max(0,L).toFixed(1)}" height="${_}" ${G}/>`;R.push(q(0,0,M,T,`fill="${g}"`));const K=b==="year"?null:b==="day"||b==="week"?"month":"year";if(K)for(const f of kt(K,m,r,w,i,0,Number.POSITIVE_INFINITY)){const E=K==="month"?P.format(new Date(f.start)):String(new Date(f.start).getFullYear());R.push(`<line x1="${(x+f.left).toFixed(1)}" y1="0" x2="${(x+f.left).toFixed(1)}" y2="26" stroke="${d}"/>`),f.width>=It&&R.push(`<text x="${(x+f.left+8).toFixed(1)}" y="17" font-size="11" font-weight="700" fill="${c}">${v(E)}</text>`)}const J=K?26:0;for(const f of kt(b,m,r,w,i,0,Number.POSITIVE_INFINITY))R.push(`<line x1="${(x+f.left).toFixed(1)}" y1="${J}" x2="${(x+f.left).toFixed(1)}" y2="${T}" stroke="${d}" stroke-opacity=".45"/>`),(f.width>=It||b==="day")&&R.push(`<text x="${(x+f.left+8).toFixed(1)}" y="${J+18}" font-size="11" font-weight="650" fill="${h}">${v(st(f.start,b))}</text>`);if(R.push(`<line x1="0" y1="${N}" x2="${M}" y2="${N}" stroke="${d}"/>`),R.push(`<text x="10" y="${N/2+4}" font-size="11" font-weight="700" fill="${h}">${v(t.columnTask.toUpperCase())}</text>`),i>=fe&&(p.weekdays.size||p.holidays.size))for(let f=r;f<w;f=A(f,1))ge(f,p)&&R.push(q(x+z(f),N,i,a.length*S,`fill="${p.holidays.has(f)?"#d97706":h}" fill-opacity="${p.holidays.has(f)?".15":".1"}"`));a.forEach((f,E)=>{const L=N+E*S;R.push(`<line x1="0" y1="${L+S}" x2="${M}" y2="${L+S}" stroke="${d}" stroke-opacity=".5"/>`),R.push(`<text x="${10+f.depth*18}" y="${L+S/2+4}" font-size="12" font-weight="650" fill="${c}">${v(f.label.length>34-f.depth*2?`${f.label.slice(0,33-f.depth*2)}…`:f.label)}</text>`)}),R.push(`<line x1="${x}" y1="0" x2="${x}" y2="${T}" stroke="${d}"/>`);const O=[],V=new Map(a.map((f,E)=>[f.id,{task:f,index:E}]));for(const f of this.getLinks()){const E=V.get(f.source),L=V.get(f.target);!E||!L||O.push(`<path d="${oe(E.task,E.index,L.task,L.index,f.type,z)}" fill="none" stroke="${h}" stroke-width="1.35" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow)"/>`)}a.forEach((f,E)=>{const L=E*S,_=ut(f),G=f.critical?u:o(mt[f.tone||(_==="summary"?"info":"default")]||mt.default),at=z(f.startMs),dt=Math.max(12,z(f.endMs)-at);if(f.baselineStart&&f.baselineEnd){const F=$(f.baselineStart)??f.startMs,C=$(f.baselineEnd)??f.endMs;O.push(q(z(F),L+33,Math.max(4,z(C)-z(F)),4,`rx="2" fill="${h}" fill-opacity=".5"`))}if(_==="milestone"){const F=at,C=L+21;O.push(`<polygon points="${F},${C-10} ${F+10},${C} ${F},${C+10} ${F-10},${C}" fill="${G}"/>`);return}const rt=_==="summary"?L+17:L+12,it=_==="summary"?9:18,$t=Math.max(0,Math.min(100,Number(f.progress??0))),pt=(F,C,tt)=>{O.push(q(F,rt,C,it,`rx="4" fill="${G}"`)),_==="summary"&&O.push(q(F,rt,C,it,'rx="3" fill="#000" fill-opacity=".2"')),tt>0&&O.push(q(F,rt,C*tt/100,it,'rx="4" fill="#000" fill-opacity=".28"'))};if(_==="task"&&f.segments?.length)for(const F of f.segments){const C=$(F.start),tt=$(F.end);C==null||tt==null||tt<=C||pt(z(Math.max(f.startMs,C)),z(Math.min(f.endMs,tt))-z(Math.max(f.startMs,C)),F.progress??$t)}else pt(at,dt,$t)});const et=Y(Date.now());return this.getAttribute("show-today")!=="false"&&et>=r&&et<=w&&(O.push(`<line x1="${z(et).toFixed(1)}" y1="0" x2="${z(et).toFixed(1)}" y2="${a.length*S}" stroke="${u}" stroke-width="2"/>`),R.push(`<text x="${(x+z(et)).toFixed(1)}" y="${N-6}" font-size="10" font-weight="700" text-anchor="middle" fill="${u}">${v(t.today)}</text>`)),R.push(`<g transform="translate(${x} ${N})">${O.join("")}</g>`),R.push(`<title>${v(this.getAttribute("aria-label")||t.title)} (${v(U.format(new Date(r)))} – ${v(U.format(new Date(k)))})</title>`),`<svg xmlns="http://www.w3.org/2000/svg" width="${Math.round(M)}" height="${T}" viewBox="0 0 ${Math.round(M)} ${T}" font-family="system-ui, -apple-system, 'Segoe UI', sans-serif"><defs><marker id="arrow" markerWidth="9" markerHeight="9" refX="8.5" refY="4.5" orient="auto" markerUnits="userSpaceOnUse"><path d="M 0.5 0.75 L 8.5 4.5 L 0.5 8.25 z" fill="${h}"/></marker></defs>`+R.join("")+"</svg>"}rangeMin(){const e=this.getTasks().map(r=>$(r.start)).filter(r=>r!=null);return e.length?A(Math.min(...e),-2):Y(Date.now())}selectTask(t){if(this.captureViewport(),this.selectedLinkId=null,this.selectedId===t){this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:t},bubbles:!0,composed:!0}));return}this.selectedId=t,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:t},bubbles:!0,composed:!0})),this.requestRender()}focusTask(t,e){this.selectedId!==t&&(this.selectedId=t,this.dispatchEvent(new CustomEvent("taskselect",{detail:{id:t},bubbles:!0,composed:!0}))),this.focusRequest={selector:e==="row"?Nt(t):At(t),reveal:!0,retries:0},this.reveal(t,"auto"),this.requestRender()}navigate(t,e,r){const i=this.visibleIds,a=i.indexOf(t);if(a<0)return!1;let s;switch(e){case"ArrowUp":s=i[a-1];break;case"ArrowDown":s=i[a+1];break;case"Home":s=i[0];break;case"End":s=i[i.length-1];break;case"PageUp":s=i[Math.max(0,a-10)];break;case"PageDown":s=i[Math.min(i.length-1,a+10)];break;case"ArrowRight":case"ArrowLeft":{if(r!=="row")return!1;const o=this.getTasks(),h=new Set(o.map(d=>d.parent).filter(d=>!!d)).has(t);if(e==="ArrowRight"){if(!h)return!0;this.collapsed.has(t)?this.toggleTask(t,!0):s=i[a+1]}else if(h&&!this.collapsed.has(t))this.toggleTask(t,!1);else{const d=o.find(g=>g.id===t)?.parent;d&&i.includes(d)&&(s=d)}break}default:return!1}return s&&s!==t&&this.focusTask(s,r),!0}captureViewport(){const t=this.root.querySelector(".viewport");t&&(this.viewportTop=t.scrollTop,this.viewportLeft=t.scrollLeft,this.viewportWidth=t.clientWidth||this.viewportWidth,this.viewportHeight=t.clientHeight||this.viewportHeight)}getTasks(){const t=this.getAttribute("tasks"),e=this.hasAttribute("auto-summary"),r=this.hasAttribute("critical-path")?this.getAttribute("links")??"":null;return t===this.taskCacheRaw&&this.taskCacheVersion===this.overridesVersion&&e===this.taskCacheAuto&&r===this.taskCacheCritical?this.taskCache:(this.taskCacheRaw=t,this.taskCacheVersion=this.overridesVersion,this.taskCacheAuto=e,this.taskCacheCritical=r,this.taskCache=je(t,this.overrides,e),e&&(this.taskCache=lr(this.taskCache)),r!==null&&(this.taskCache=dr(this.taskCache,Zt(r))),this.seedCollapsed(this.taskCache),this.visibleCacheKey="",this.taskCache)}seedCollapsed(t){for(const e of t)this.seededIds.has(e.id)||(this.seededIds.add(e.id),e.open===!1&&this.collapsed.add(e.id))}getLinks(){const t=this.getAttribute("links");return t===this.linkCacheRaw?this.linkCache:(this.linkCacheRaw=t,this.linkCache=Zt(t),this.linkCache)}getVisibleTasks(t,e,r){const i=Array.from(this.collapsed).sort().join(","),a=`${this.taskCacheRaw||""}|${this.overridesVersion}|${e}|${r}|${i}`;return a===this.visibleCacheKey?this.visibleCache:(this.visibleCacheKey=a,this.visibleCache=Xe(t,this.collapsed,e,r),this.visibleCache)}bumpOverrides(){this.overridesVersion+=1,this.taskCacheVersion=-1,this.visibleCacheKey=""}shouldRenderOnAttributeChange(t,e,r){if(t==="tasks"){this.overrides.clear(),this.bumpOverrides();const i=ee(r);Ge(ee(e),i)||(this.viewportTop=0,this.viewportLeft=0,this.initialScrollPending=!0,this.collapsed.clear(),this.seededIds.clear()),this.selectedId!=null&&!i.has(this.selectedId)&&(this.selectedId=null)}return t==="links"&&(this.linkCacheRaw=null),(t==="auto-summary"||t==="cascade")&&this.bumpOverrides(),!0}}typeof customElements<"u"&&!customElements.get("ui-gantt")&&customElements.define("ui-gantt",me);exports.UIGantt=me;