@esportsplus/ui 0.57.0 → 0.58.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 (490) hide show
  1. package/README.md +123 -39
  2. package/build/components/accordion/group.d.ts +14 -0
  3. package/build/components/accordion/group.js +21 -0
  4. package/build/components/accordion/index.d.ts +9 -0
  5. package/build/components/accordion/index.js +20 -3
  6. package/build/components/accordion/scss/index.scss +1 -1
  7. package/build/components/announcement/scss/index.scss +1 -1
  8. package/build/components/breadcrumb/scss/index.scss +1 -1
  9. package/build/components/button/scss/index.scss +1 -1
  10. package/build/components/button/sidebar.d.ts +3 -0
  11. package/build/components/button/sidebar.js +40 -10
  12. package/build/components/capslock/index.js +1 -1
  13. package/build/components/capslock/scss/index.scss +1 -1
  14. package/build/components/card/scss/index.scss +1 -1
  15. package/build/components/cc/scss/index.scss +1 -1
  16. package/build/components/chat-minimap/scss/index.scss +1 -1
  17. package/build/components/checkbox/scss/index.scss +1 -1
  18. package/build/components/color-picker/index.d.ts +1 -0
  19. package/build/components/color-picker/index.js +166 -136
  20. package/build/components/color-picker/scss/index.scss +1 -1
  21. package/build/components/command/index.d.ts +0 -1
  22. package/build/components/command/index.js +3 -2
  23. package/build/components/command/scss/index.scss +1 -1
  24. package/build/components/copy/scss/index.scss +1 -1
  25. package/build/components/counter/scss/index.scss +1 -1
  26. package/build/components/datalist/index.js +3 -3
  27. package/build/components/datalist/scss/index.scss +1 -1
  28. package/build/components/dock/scss/index.scss +1 -1
  29. package/build/components/editor/code/index.d.ts +0 -1
  30. package/build/components/editor/code/index.js +0 -1
  31. package/build/components/editor/code/minimap.d.ts +2 -1
  32. package/build/components/editor/code/minimap.js +5 -2
  33. package/build/components/editor/code/view.d.ts +3 -1
  34. package/build/components/editor/code/view.js +37 -26
  35. package/build/components/editor/diffs/index.d.ts +0 -1
  36. package/build/components/editor/diffs/index.js +0 -1
  37. package/build/components/editor/diffs/merge.js +7 -3
  38. package/build/components/editor/diffs/view.js +3 -1
  39. package/build/components/editor/index.d.ts +4 -1
  40. package/build/components/editor/index.js +2 -1
  41. package/build/components/editor/markdown/editing.js +22 -3
  42. package/build/components/editor/markdown/erase.d.ts +9 -0
  43. package/build/components/editor/markdown/erase.js +78 -0
  44. package/build/components/editor/markdown/index.d.ts +0 -1
  45. package/build/components/editor/markdown/index.js +0 -1
  46. package/build/components/editor/markdown/layout.d.ts +2 -9
  47. package/build/components/editor/markdown/layout.js +2 -7
  48. package/build/components/editor/markdown/render.d.ts +0 -1
  49. package/build/components/editor/markdown/render.js +287 -235
  50. package/build/components/editor/markdown/view.js +566 -667
  51. package/build/components/editor/viewer/index.d.ts +27 -0
  52. package/build/components/editor/viewer/index.js +250 -0
  53. package/build/components/editor/viewer/model.d.ts +15 -0
  54. package/build/components/editor/viewer/model.js +73 -0
  55. package/build/components/editor/workspace/index.d.ts +6 -2
  56. package/build/components/editor/workspace/index.js +243 -137
  57. package/build/components/editor/workspace/keybindings.d.ts +37 -0
  58. package/build/components/editor/workspace/keybindings.js +288 -0
  59. package/build/components/editor/workspace/model.d.ts +55 -2
  60. package/build/components/editor/workspace/model.js +141 -3
  61. package/build/components/editor/workspace/navigate.d.ts +19 -0
  62. package/build/components/editor/workspace/navigate.js +118 -0
  63. package/build/components/editor/workspace/session.d.ts +29 -0
  64. package/build/components/editor/workspace/session.js +373 -0
  65. package/build/components/editor/workspace/shortcuts.d.ts +19 -0
  66. package/build/components/editor/workspace/shortcuts.js +185 -0
  67. package/build/components/editor/workspace/status.d.ts +34 -0
  68. package/build/components/editor/workspace/status.js +193 -0
  69. package/build/components/editor/workspace/statusbar.d.ts +15 -0
  70. package/build/components/editor/workspace/statusbar.js +190 -0
  71. package/build/components/editor/workspace/strip.d.ts +27 -0
  72. package/build/components/editor/workspace/strip.js +239 -0
  73. package/build/components/editor/workspace/tabs.d.ts +15 -0
  74. package/build/components/editor/workspace/tabs.js +63 -0
  75. package/build/components/error/index.js +1 -1
  76. package/build/components/error/scss/index.scss +1 -1
  77. package/build/components/filter/index.js +5 -3
  78. package/build/components/filter/scss/index.scss +1 -1
  79. package/build/components/frame/scss/index.scss +1 -1
  80. package/build/components/heatmap/index.js +3 -3
  81. package/build/components/heatmap/scss/index.scss +1 -1
  82. package/build/components/highlight/scss/index.scss +1 -1
  83. package/build/components/icon/scss/index.scss +1 -1
  84. package/build/components/image/scss/index.scss +1 -1
  85. package/build/components/index.d.ts +2 -0
  86. package/build/components/index.js +2 -0
  87. package/build/components/inline-edit/scss/index.scss +1 -1
  88. package/build/components/input/scss/index.scss +1 -1
  89. package/build/components/link/scss/index.scss +1 -1
  90. package/build/components/loading/scss/index.scss +1 -1
  91. package/build/components/marquee/scss/index.scss +1 -1
  92. package/build/components/metric/scss/index.scss +1 -1
  93. package/build/components/nav/index.d.ts +1 -1
  94. package/build/components/nav/scss/index.scss +1 -1
  95. package/build/components/nav/tree.d.ts +3 -1
  96. package/build/components/nav/tree.js +30 -60
  97. package/build/components/notification/scss/index.scss +1 -1
  98. package/build/components/overlay/scss/index.scss +1 -1
  99. package/build/components/page/scss/index.scss +1 -1
  100. package/build/components/pagination/arrows.d.ts +15 -0
  101. package/build/components/pagination/arrows.js +65 -0
  102. package/build/components/pagination/cards.d.ts +23 -0
  103. package/build/components/pagination/cards.js +66 -0
  104. package/build/components/pagination/index.d.ts +5 -0
  105. package/build/components/pagination/index.js +3 -1
  106. package/build/components/pagination/scss/index.scss +1 -1
  107. package/build/components/progress/scss/index.scss +1 -1
  108. package/build/components/pull-to-refresh/scss/index.scss +1 -1
  109. package/build/components/range/index.js +1 -1
  110. package/build/components/range/scss/index.scss +1 -1
  111. package/build/components/relative-time/scss/index.scss +1 -1
  112. package/build/components/root/scss/index.scss +1 -1
  113. package/build/components/section/scss/index.scss +2 -0
  114. package/build/components/select/index.d.ts +1 -0
  115. package/build/components/select/index.js +16 -11
  116. package/build/components/select/scss/index.scss +1 -1
  117. package/build/components/shortcut-recorder/scss/index.scss +1 -1
  118. package/build/components/sortable/scss/index.scss +1 -1
  119. package/build/components/sticky-header/index.js +3 -3
  120. package/build/components/sticky-header/scss/index.scss +1 -1
  121. package/build/components/story/scss/index.scss +1 -1
  122. package/build/components/surface-field/scss/index.scss +1 -1
  123. package/build/components/tasklist/scss/index.scss +1 -1
  124. package/build/components/text/scss/index.scss +1 -1
  125. package/build/components/textarea/scss/index.scss +1 -1
  126. package/build/{css-utilities → components}/theme/index.d.ts +1 -1
  127. package/build/{css-utilities → components}/theme/index.js +15 -5
  128. package/build/components/theme/scss/index.scss +2 -0
  129. package/build/components/theme-picker/index.d.ts +52 -0
  130. package/build/components/theme-picker/index.js +167 -0
  131. package/build/components/theme-picker/scss/index.scss +2 -0
  132. package/build/components/toast/index.js +3 -5
  133. package/build/components/toast/scss/index.scss +1 -1
  134. package/build/components/tooltip/menu.js +3 -1
  135. package/build/components/tooltip/scss/index.scss +1 -1
  136. package/build/components/typewriter/scss/index.scss +1 -1
  137. package/build/components/uptime/scss/index.scss +1 -1
  138. package/build/components/usage-meter/scss/index.scss +1 -1
  139. package/build/{css-utilities → modifiers}/glass/index.d.ts +2 -2
  140. package/build/modifiers/glass/index.js +28 -0
  141. package/build/modifiers/glass/scss/index.scss +2 -0
  142. package/build/{css-utilities → modifiers}/index.d.ts +0 -1
  143. package/build/{css-utilities → modifiers}/index.js +0 -1
  144. package/build/modifiers/scrollbar/index.d.ts +72 -0
  145. package/build/{css-utilities → modifiers}/scrollbar/index.js +52 -19
  146. package/build/modifiers/scrollbar/scss/index.scss +2 -0
  147. package/build/normalize/scss/index.scss +1 -2
  148. package/layer.scss +1 -1
  149. package/package.json +11 -18
  150. package/scripts/code-editor-markdown.test.mjs +45 -14
  151. package/scripts/code-viewer.test.mjs +69 -0
  152. package/scripts/workspace-keybindings.test.mjs +273 -0
  153. package/scripts/workspace-session.test.mjs +349 -0
  154. package/scripts/workspace-status.test.mjs +229 -0
  155. package/scripts/workspace-tabs.test.mjs +142 -0
  156. package/src/components/accordion/group.ts +39 -0
  157. package/src/components/accordion/index.ts +32 -6
  158. package/src/components/accordion/scss/index.scss +12 -21
  159. package/src/components/accordion/scss/variables.scss +18 -3
  160. package/src/components/announcement/scss/index.scss +4 -4
  161. package/src/components/announcement/scss/variables.scss +6 -6
  162. package/src/components/banner/scss/index.scss +1 -1
  163. package/src/components/breadcrumb/scss/index.scss +35 -50
  164. package/src/components/breadcrumb/scss/variables.scss +23 -31
  165. package/src/components/button/scss/_fan.scss +39 -43
  166. package/src/components/button/scss/_morph.scss +66 -78
  167. package/src/components/button/scss/_sidebar.scss +41 -30
  168. package/src/components/button/scss/_split.scss +9 -9
  169. package/src/components/button/scss/index.scss +23 -19
  170. package/src/components/button/scss/variables.scss +94 -90
  171. package/src/components/button/sidebar.ts +36 -24
  172. package/src/components/capslock/index.ts +2 -2
  173. package/src/components/capslock/scss/index.scss +11 -6
  174. package/src/components/capslock/scss/variables.scss +3 -5
  175. package/src/components/card/scss/_expand.scss +58 -64
  176. package/src/components/card/scss/index.scss +40 -21
  177. package/src/components/card/scss/variables.scss +40 -31
  178. package/src/components/cc/scss/index.scss +68 -68
  179. package/src/components/cc/scss/variables.scss +13 -14
  180. package/src/components/chat-minimap/scss/index.scss +24 -16
  181. package/src/components/chat-minimap/scss/variables.scss +37 -37
  182. package/src/components/checkbox/scss/index.scss +54 -52
  183. package/src/components/checkbox/scss/variables.scss +37 -39
  184. package/src/components/color-picker/index.ts +157 -120
  185. package/src/components/color-picker/scss/index.scss +159 -96
  186. package/src/components/color-picker/scss/variables.scss +33 -15
  187. package/src/components/command/index.ts +3 -2
  188. package/src/components/command/scss/index.scss +10 -14
  189. package/src/components/command/scss/variables.scss +12 -35
  190. package/src/components/copy/scss/index.scss +6 -6
  191. package/src/components/copy/scss/variables.scss +12 -15
  192. package/src/components/counter/scss/index.scss +14 -14
  193. package/src/components/counter/scss/variables.scss +1 -1
  194. package/src/components/datalist/index.ts +3 -3
  195. package/src/components/datalist/scss/index.scss +7 -6
  196. package/src/components/datalist/scss/variables.scss +7 -3
  197. package/src/components/dock/scss/index.scss +10 -15
  198. package/src/components/dock/scss/variables.scss +29 -25
  199. package/src/components/editor/code/index.ts +0 -1
  200. package/src/components/editor/code/minimap.ts +13 -5
  201. package/src/components/editor/code/scss/_editor.scss +83 -81
  202. package/src/components/editor/code/scss/_features.scss +106 -97
  203. package/src/components/editor/code/scss/_services.scss +27 -25
  204. package/src/components/editor/code/scss/index.scss +0 -1
  205. package/src/components/editor/code/scss/variables.scss +30 -26
  206. package/src/components/editor/code/view.ts +14 -5
  207. package/src/components/editor/diffs/index.ts +0 -1
  208. package/src/components/editor/diffs/merge.ts +2 -1
  209. package/src/components/editor/diffs/scss/_diffs.scss +67 -57
  210. package/src/components/editor/diffs/scss/_merge.scss +17 -14
  211. package/src/components/editor/diffs/scss/index.scss +0 -1
  212. package/src/components/editor/diffs/scss/variables.scss +25 -18
  213. package/src/components/editor/diffs/view.ts +2 -1
  214. package/src/components/editor/index.ts +7 -1
  215. package/src/components/editor/markdown/editing.ts +38 -3
  216. package/src/components/editor/markdown/erase.ts +124 -0
  217. package/src/components/editor/markdown/index.ts +0 -1
  218. package/src/components/editor/markdown/layout.ts +3 -12
  219. package/src/components/editor/markdown/render.ts +65 -37
  220. package/src/components/editor/markdown/scss/index.scss +92 -124
  221. package/src/components/editor/markdown/scss/variables.scss +39 -19
  222. package/src/components/editor/markdown/view.ts +737 -786
  223. package/src/components/editor/tree/scss/index.scss +121 -110
  224. package/src/components/editor/tree/scss/variables.scss +48 -54
  225. package/src/components/editor/viewer/index.ts +321 -0
  226. package/src/components/editor/viewer/model.ts +130 -0
  227. package/src/components/editor/viewer/scss/_viewer.scss +302 -0
  228. package/src/components/editor/viewer/scss/index.scss +2 -0
  229. package/src/components/editor/viewer/scss/variables.scss +69 -0
  230. package/src/components/editor/workspace/index.ts +159 -31
  231. package/src/components/editor/workspace/keybindings.ts +447 -0
  232. package/src/components/editor/workspace/model.ts +233 -3
  233. package/src/components/editor/workspace/navigate.ts +194 -0
  234. package/src/components/editor/workspace/scss/index.scss +72 -59
  235. package/src/components/editor/workspace/scss/keybindings.scss +190 -0
  236. package/src/components/editor/workspace/scss/status.scss +122 -0
  237. package/src/components/editor/workspace/scss/tabs.scss +56 -0
  238. package/src/components/editor/workspace/session.ts +551 -0
  239. package/src/components/editor/workspace/shortcuts.ts +255 -0
  240. package/src/components/editor/workspace/status.ts +259 -0
  241. package/src/components/editor/workspace/statusbar.ts +255 -0
  242. package/src/components/editor/workspace/strip.ts +273 -0
  243. package/src/components/editor/workspace/tabs.ts +106 -0
  244. package/src/components/error/index.ts +1 -1
  245. package/src/components/error/scss/index.scss +19 -19
  246. package/src/components/error/scss/variables.scss +2 -2
  247. package/src/components/filter/index.ts +7 -2
  248. package/src/components/filter/scss/index.scss +1 -1
  249. package/src/components/filter/scss/variables.scss +11 -10
  250. package/src/components/frame/scss/index.scss +12 -12
  251. package/src/components/frame/scss/variables.scss +8 -8
  252. package/src/components/heatmap/index.ts +3 -3
  253. package/src/components/heatmap/scss/index.scss +28 -26
  254. package/src/components/heatmap/scss/variables.scss +18 -17
  255. package/src/components/highlight/scss/index.scss +17 -13
  256. package/src/components/highlight/scss/variables.scss +8 -10
  257. package/src/components/icon/scss/index.scss +10 -0
  258. package/src/components/icon/scss/variables.scss +5 -0
  259. package/src/components/image/scss/index.scss +9 -9
  260. package/src/components/image/scss/variables.scss +7 -2
  261. package/src/components/index.ts +2 -0
  262. package/src/components/inline-edit/scss/index.scss +99 -104
  263. package/src/components/inline-edit/scss/variables.scss +40 -39
  264. package/src/components/input/scss/_field.scss +6 -20
  265. package/src/components/input/scss/_scrub.scss +10 -8
  266. package/src/components/input/scss/_tag.scss +35 -37
  267. package/src/components/input/scss/variables.scss +100 -99
  268. package/src/components/link/scss/index.scss +4 -1
  269. package/src/components/loading/scss/index.scss +1 -1
  270. package/src/components/loading/scss/variables.scss +1 -1
  271. package/src/components/marquee/scss/index.scss +9 -5
  272. package/src/components/marquee/scss/variables.scss +3 -1
  273. package/src/components/metric/scss/_flash.scss +3 -1
  274. package/src/components/metric/scss/index.scss +8 -6
  275. package/src/components/metric/scss/variables.scss +26 -20
  276. package/src/components/nav/index.ts +1 -1
  277. package/src/components/nav/scss/index.scss +12 -40
  278. package/src/components/nav/scss/variables.scss +30 -11
  279. package/src/components/nav/tree.ts +19 -62
  280. package/src/components/notification/scss/index.scss +7 -7
  281. package/src/components/notification/scss/variables.scss +7 -9
  282. package/src/components/overlay/scss/index.scss +181 -170
  283. package/src/components/overlay/scss/variables.scss +26 -57
  284. package/src/components/page/scss/index.scss +12 -11
  285. package/src/components/page/scss/variables.scss +5 -0
  286. package/src/components/pagination/arrows.ts +58 -0
  287. package/src/components/pagination/cards.ts +57 -0
  288. package/src/components/pagination/index.ts +4 -1
  289. package/src/components/pagination/scss/_arrows.scss +69 -0
  290. package/src/components/pagination/scss/_cards.scss +121 -0
  291. package/src/components/pagination/scss/_dots.scss +2 -5
  292. package/src/components/pagination/scss/index.scss +8 -6
  293. package/src/components/pagination/scss/variables.scss +87 -37
  294. package/src/components/progress/scss/_text.scss +21 -18
  295. package/src/components/progress/scss/index.scss +1 -1
  296. package/src/components/progress/scss/variables.scss +12 -12
  297. package/src/components/pull-to-refresh/scss/index.scss +2 -1
  298. package/src/components/pull-to-refresh/scss/variables.scss +11 -6
  299. package/src/components/range/index.ts +1 -1
  300. package/src/components/range/scss/_filter.scss +62 -51
  301. package/src/components/range/scss/_slider.scss +78 -75
  302. package/src/components/range/scss/_vertical.scss +6 -6
  303. package/src/components/range/scss/index.scss +3 -2
  304. package/src/components/range/scss/variables.scss +26 -23
  305. package/src/components/relative-time/scss/index.scss +27 -27
  306. package/src/components/relative-time/scss/variables.scss +10 -12
  307. package/src/components/root/scss/index.scss +71 -43
  308. package/src/components/root/scss/variables.scss +35 -31
  309. package/src/components/section/scss/index.scss +31 -0
  310. package/src/components/section/scss/variables.scss +21 -0
  311. package/src/components/select/index.ts +11 -6
  312. package/src/components/select/scss/index.scss +21 -32
  313. package/src/components/select/scss/variables.scss +25 -18
  314. package/src/components/shortcut-recorder/scss/index.scss +13 -12
  315. package/src/components/shortcut-recorder/scss/variables.scss +12 -13
  316. package/src/components/sortable/scss/index.scss +47 -44
  317. package/src/components/sortable/scss/variables.scss +4 -5
  318. package/src/components/sticky-header/index.ts +4 -4
  319. package/src/components/sticky-header/scss/index.scss +14 -13
  320. package/src/components/sticky-header/scss/variables.scss +9 -9
  321. package/src/components/story/scss/index.scss +26 -30
  322. package/src/components/story/scss/variables.scss +16 -9
  323. package/src/components/surface-field/scss/index.scss +45 -40
  324. package/src/components/surface-field/scss/variables.scss +5 -6
  325. package/src/components/tasklist/scss/index.scss +19 -19
  326. package/src/components/tasklist/scss/variables.scss +26 -29
  327. package/src/components/text/scss/index.scss +2 -1
  328. package/src/components/textarea/scss/variables.scss +1 -1
  329. package/src/{css-utilities → components}/theme/index.ts +17 -3
  330. package/src/components/theme/scss/index.scss +1 -0
  331. package/src/components/theme/scss/variables.scss +78 -0
  332. package/src/components/theme-picker/index.ts +231 -0
  333. package/src/components/theme-picker/scss/index.scss +264 -0
  334. package/src/components/toast/index.ts +28 -30
  335. package/src/components/toast/scss/index.scss +87 -87
  336. package/src/components/toast/scss/variables.scss +39 -39
  337. package/src/components/tooltip/menu.ts +4 -1
  338. package/src/components/tooltip/scss/_east.scss +10 -10
  339. package/src/components/tooltip/scss/_menu.scss +284 -269
  340. package/src/components/tooltip/scss/_north.scss +10 -10
  341. package/src/components/tooltip/scss/_shared.scss +7 -7
  342. package/src/components/tooltip/scss/_south.scss +10 -10
  343. package/src/components/tooltip/scss/_west.scss +10 -10
  344. package/src/components/tooltip/scss/index.scss +21 -20
  345. package/src/components/tooltip/scss/variables.scss +104 -96
  346. package/src/components/typewriter/scss/_retype.scss +12 -11
  347. package/src/components/typewriter/scss/_rotate.scss +2 -1
  348. package/src/components/typewriter/scss/variables.scss +41 -39
  349. package/src/components/uptime/scss/index.scss +15 -15
  350. package/src/components/uptime/scss/variables.scss +8 -8
  351. package/src/components/usage-meter/scss/index.scss +3 -1
  352. package/src/components/usage-meter/scss/variables.scss +5 -5
  353. package/src/css-utilities/absolute.scss +64 -0
  354. package/src/css-utilities/background.scss +43 -0
  355. package/src/css-utilities/border.scss +45 -0
  356. package/src/css-utilities/box-shadow.scss +29 -0
  357. package/src/css-utilities/color.scss +41 -0
  358. package/src/css-utilities/flex.scss +64 -0
  359. package/src/css-utilities/font/geist/{scss/index.scss → index.scss} +12 -4
  360. package/src/css-utilities/font/montserrat/Montserrat-Italic-Variable.woff2 +0 -0
  361. package/src/css-utilities/font/montserrat/Montserrat-Variable.woff2 +0 -0
  362. package/src/css-utilities/font/montserrat/OFL.txt +93 -0
  363. package/src/css-utilities/font/montserrat/index.scss +38 -0
  364. package/src/{shared/scss → css-utilities}/icon.scss +1 -1
  365. package/src/css-utilities/{inline/scss/index.scss → inline.scss} +1 -1
  366. package/src/css-utilities/{skeleton/scss/index.scss → skeleton.scss} +11 -11
  367. package/src/css-utilities/surface.scss +266 -0
  368. package/src/css-utilities/text.scss +191 -0
  369. package/src/modifiers/glass/index.ts +44 -0
  370. package/src/{css-utilities → modifiers}/glass/scss/index.scss +6 -6
  371. package/src/{css-utilities → modifiers}/glass/scss/variables.scss +1 -1
  372. package/src/{css-utilities → modifiers}/index.ts +0 -1
  373. package/src/{css-utilities → modifiers}/scrollbar/index.ts +92 -17
  374. package/src/{css-utilities → modifiers}/scrollbar/scss/index.scss +178 -177
  375. package/src/{css-utilities → modifiers}/scrollbar/scss/variables.scss +28 -21
  376. package/src/normalize/scss/index.scss +4 -2
  377. package/src/shared/scss/color-weights.scss +19 -0
  378. package/src/shared/scss/index.scss +1 -12
  379. package/src/tokens/scss/blur.scss +5 -0
  380. package/src/tokens/scss/color.scss +74 -50
  381. package/src/tokens/scss/index.scss +1 -2
  382. package/src/tokens/scss/size.scss +0 -2
  383. package/src/tokens/scss/state.scss +3 -2
  384. package/src/tokens/scss/transition.scss +19 -2
  385. package/storage/svg/monitor.svg +1 -0
  386. package/storage/svg/moon.svg +1 -0
  387. package/storage/svg/pin.svg +1 -0
  388. package/storage/svg/sun.svg +1 -0
  389. package/vite.config.ts +33 -8
  390. package/build/css-utilities/background/scss/index.scss +0 -2
  391. package/build/css-utilities/border/scss/index.scss +0 -2
  392. package/build/css-utilities/color/scss/index.scss +0 -2
  393. package/build/css-utilities/flex/scss/index.scss +0 -2
  394. package/build/css-utilities/font/geist/index.d.ts +0 -1
  395. package/build/css-utilities/font/geist/index.js +0 -1
  396. package/build/css-utilities/font/geist/scss/index.scss +0 -2
  397. package/build/css-utilities/font/montserrat/index.d.ts +0 -1
  398. package/build/css-utilities/font/montserrat/index.js +0 -1
  399. package/build/css-utilities/font/montserrat/scss/Montserrat-Bold.woff +0 -0
  400. package/build/css-utilities/font/montserrat/scss/Montserrat-Bold.woff2 +0 -0
  401. package/build/css-utilities/font/montserrat/scss/Montserrat-BoldItalic.woff +0 -0
  402. package/build/css-utilities/font/montserrat/scss/Montserrat-BoldItalic.woff2 +0 -0
  403. package/build/css-utilities/font/montserrat/scss/Montserrat-Italic.woff +0 -0
  404. package/build/css-utilities/font/montserrat/scss/Montserrat-Italic.woff2 +0 -0
  405. package/build/css-utilities/font/montserrat/scss/Montserrat-Medium.woff +0 -0
  406. package/build/css-utilities/font/montserrat/scss/Montserrat-Medium.woff2 +0 -0
  407. package/build/css-utilities/font/montserrat/scss/Montserrat-MediumItalic.woff +0 -0
  408. package/build/css-utilities/font/montserrat/scss/Montserrat-MediumItalic.woff2 +0 -0
  409. package/build/css-utilities/font/montserrat/scss/Montserrat-Regular.woff +0 -0
  410. package/build/css-utilities/font/montserrat/scss/Montserrat-Regular.woff2 +0 -0
  411. package/build/css-utilities/font/montserrat/scss/Montserrat-SemiBold.woff +0 -0
  412. package/build/css-utilities/font/montserrat/scss/Montserrat-SemiBold.woff2 +0 -0
  413. package/build/css-utilities/font/montserrat/scss/Montserrat-SemiBoldItalic.woff +0 -0
  414. package/build/css-utilities/font/montserrat/scss/Montserrat-SemiBoldItalic.woff2 +0 -0
  415. package/build/css-utilities/font/montserrat/scss/index.scss +0 -2
  416. package/build/css-utilities/glass/index.js +0 -26
  417. package/build/css-utilities/glass/scss/index.scss +0 -2
  418. package/build/css-utilities/index.scss +0 -2
  419. package/build/css-utilities/inline/scss/index.scss +0 -2
  420. package/build/css-utilities/scrollbar/index.d.ts +0 -42
  421. package/build/css-utilities/scrollbar/scss/index.scss +0 -2
  422. package/build/css-utilities/skeleton/scss/index.scss +0 -2
  423. package/build/css-utilities/text/scss/index.scss +0 -2
  424. package/build/themes/dark/index.d.ts +0 -3
  425. package/build/themes/dark/index.js +0 -3
  426. package/build/themes/dark/input.d.ts +0 -3
  427. package/build/themes/dark/input.js +0 -12
  428. package/build/themes/dark/select.d.ts +0 -3
  429. package/build/themes/dark/select.js +0 -23
  430. package/build/themes/dark/textarea.d.ts +0 -2186
  431. package/build/themes/dark/textarea.js +0 -11
  432. package/src/css-utilities/background/scss/index.scss +0 -1
  433. package/src/css-utilities/background/scss/variables.scss +0 -18
  434. package/src/css-utilities/border/scss/index.scss +0 -1
  435. package/src/css-utilities/border/scss/variables.scss +0 -23
  436. package/src/css-utilities/color/scss/index.scss +0 -1
  437. package/src/css-utilities/color/scss/variables.scss +0 -17
  438. package/src/css-utilities/flex/scss/index.scss +0 -57
  439. package/src/css-utilities/flex/scss/variables.scss +0 -16
  440. package/src/css-utilities/font/geist/index.ts +0 -1
  441. package/src/css-utilities/font/montserrat/index.ts +0 -1
  442. package/src/css-utilities/font/montserrat/scss/Montserrat-Bold.woff +0 -0
  443. package/src/css-utilities/font/montserrat/scss/Montserrat-Bold.woff2 +0 -0
  444. package/src/css-utilities/font/montserrat/scss/Montserrat-BoldItalic.woff +0 -0
  445. package/src/css-utilities/font/montserrat/scss/Montserrat-BoldItalic.woff2 +0 -0
  446. package/src/css-utilities/font/montserrat/scss/Montserrat-Italic.woff +0 -0
  447. package/src/css-utilities/font/montserrat/scss/Montserrat-Italic.woff2 +0 -0
  448. package/src/css-utilities/font/montserrat/scss/Montserrat-Medium.woff +0 -0
  449. package/src/css-utilities/font/montserrat/scss/Montserrat-Medium.woff2 +0 -0
  450. package/src/css-utilities/font/montserrat/scss/Montserrat-MediumItalic.woff +0 -0
  451. package/src/css-utilities/font/montserrat/scss/Montserrat-MediumItalic.woff2 +0 -0
  452. package/src/css-utilities/font/montserrat/scss/Montserrat-Regular.woff +0 -0
  453. package/src/css-utilities/font/montserrat/scss/Montserrat-Regular.woff2 +0 -0
  454. package/src/css-utilities/font/montserrat/scss/Montserrat-SemiBold.woff +0 -0
  455. package/src/css-utilities/font/montserrat/scss/Montserrat-SemiBold.woff2 +0 -0
  456. package/src/css-utilities/font/montserrat/scss/Montserrat-SemiBoldItalic.woff +0 -0
  457. package/src/css-utilities/font/montserrat/scss/Montserrat-SemiBoldItalic.woff2 +0 -0
  458. package/src/css-utilities/font/montserrat/scss/index.scss +0 -94
  459. package/src/css-utilities/glass/index.ts +0 -42
  460. package/src/css-utilities/index.scss +0 -13
  461. package/src/css-utilities/skeleton/scss/variables.scss +0 -3
  462. package/src/css-utilities/text/scss/index.scss +0 -152
  463. package/src/css-utilities/text/scss/variables.scss +0 -22
  464. package/src/shared/scss/absolute.scss +0 -28
  465. package/src/shared/scss/background.scss +0 -21
  466. package/src/shared/scss/border.scss +0 -21
  467. package/src/shared/scss/color.scss +0 -21
  468. package/src/shared/scss/position.scss +0 -55
  469. package/src/shared/scss/text.scss +0 -31
  470. package/src/themes/dark/index.ts +0 -3
  471. package/src/themes/dark/input.ts +0 -16
  472. package/src/themes/dark/select.ts +0 -28
  473. package/src/themes/dark/textarea.ts +0 -13
  474. package/src/tokens/scss/box-shadow.scss +0 -23
  475. package/src/tokens/scss/font-family.scss +0 -5
  476. package/storage/code.md +0 -180
  477. package/storage/editor-features.md +0 -227
  478. package/build/css-utilities/font/geist/{scss/Geist-Italic-Variable.woff2 → Geist-Italic-Variable.woff2} +0 -0
  479. package/build/css-utilities/font/geist/{scss/Geist-Variable.woff2 → Geist-Variable.woff2} +0 -0
  480. package/build/css-utilities/font/geist/{scss/GeistMono-Italic-Variable.woff2 → GeistMono-Italic-Variable.woff2} +0 -0
  481. package/build/css-utilities/font/geist/{scss/GeistMono-Variable.woff2 → GeistMono-Variable.woff2} +0 -0
  482. package/src/{shared/scss → css-utilities}/anchor.scss +6 -6
  483. package/src/{shared/scss → css-utilities}/drag.scss +0 -0
  484. package/src/css-utilities/font/geist/{scss/Geist-Italic-Variable.woff2 → Geist-Italic-Variable.woff2} +0 -0
  485. package/src/css-utilities/font/geist/{scss/Geist-Variable.woff2 → Geist-Variable.woff2} +0 -0
  486. package/src/css-utilities/font/geist/{scss/GeistMono-Italic-Variable.woff2 → GeistMono-Italic-Variable.woff2} +0 -0
  487. package/src/css-utilities/font/geist/{scss/GeistMono-Variable.woff2 → GeistMono-Variable.woff2} +0 -0
  488. package/src/{shared/scss → css-utilities}/hidden.scss +11 -11
  489. /package/src/{shared/scss → css-utilities}/layer.scss +0 -0
  490. /package/src/{shared/scss → css-utilities}/reset.scss +0 -0
@@ -0,0 +1,255 @@
1
+ import { flush, peek, reactive, read, signal, untrack, write } from '@esportsplus/reactivity';
2
+ import { html, type Renderable } from '@esportsplus/template';
3
+ import icon from '~/components/icon';
4
+ import status from '~/components/inline-edit/status';
5
+ import tooltip from '~/components/tooltip';
6
+ import type { Controller as MenuController, Item } from '~/components/tooltip/menu';
7
+ import type { Controller as CodeController, Language, Options } from '../code';
8
+ import type { WorkspaceEditorController } from '.';
9
+ import type { EditorWorkspaceModel, WorkspaceTab } from './model';
10
+ import {
11
+ AUTO_SAVE_MODES,
12
+ AutoSave,
13
+ INDENT_SIZES,
14
+ indentation,
15
+ indentLabel,
16
+ LANGUAGES,
17
+ lineEndings,
18
+ type AutoSaveMode,
19
+ type Indentation
20
+ } from './status';
21
+ import alert from '@esportsplus/ui/svg/circle-alert.svg';
22
+ import check from '@esportsplus/ui/svg/check.svg';
23
+ import warning from '@esportsplus/ui/svg/warning.svg';
24
+ import '~/components/inline-edit/scss/index.scss';
25
+ import './scss/status.scss';
26
+
27
+
28
+ type Choice = 'autoSave' | 'indent' | 'language';
29
+
30
+
31
+ const CHOICES: Record<Choice, string> = {
32
+ autoSave: 'Auto save',
33
+ indent: 'Indentation',
34
+ language: 'Language'
35
+ };
36
+
37
+
38
+ function isCode(controller: WorkspaceEditorController): controller is CodeController {
39
+ return 'nextProblem' in controller && 'state' in controller;
40
+ }
41
+
42
+ function mark(selected: () => boolean) {
43
+ return () => html`${() => selected() && icon({ 'aria-hidden': 'true', class: 'code-workspace-choice-icon' }, check)}`;
44
+ }
45
+
46
+
47
+ // The status bar's editor items, the auto save status that takes the save button's place, and the menu their small
48
+ // choices open in.
49
+ const statusbar = (model: EditorWorkspaceModel, nextProblem: () => Promise<boolean>) => {
50
+ let autosave = new AutoSave(model),
51
+ choice = signal<Choice>('language'),
52
+ editor = signal<CodeController | undefined>(undefined),
53
+ menu: MenuController | undefined,
54
+ // Language and indentation picked for a tab, over the workspace's editor options.
55
+ overrides = new WeakMap<WorkspaceTab, Options>(),
56
+ revision = signal(0),
57
+ view = reactive({ autoSave: 'off' as AutoSaveMode });
58
+
59
+ function choose(next: Choice, element: HTMLElement, below = false) {
60
+ let bounds = element.getBoundingClientRect();
61
+
62
+ write(choice, next);
63
+ // Items hide by the choice; the menu focuses its first visible one as it opens.
64
+ flush();
65
+ menu?.open({ x: bounds.left, y: below ? bounds.bottom : bounds.top });
66
+ }
67
+
68
+ function code(render: (controller: CodeController) => Renderable<unknown>) {
69
+ return () => {
70
+ let controller = read(editor);
71
+
72
+ return controller && render(controller);
73
+ };
74
+ }
75
+
76
+ function item(kind: string, label: () => string, onclick: (event: MouseEvent) => void, title: string | (() => string) = label) {
77
+ return html`
78
+ <button
79
+ class='button code-workspace-status-item code-workspace-status-item--${kind}'
80
+ type='button'
81
+ ${{ 'aria-label': title, onclick, title }}
82
+ >
83
+ ${label}
84
+ </button>
85
+ `;
86
+ }
87
+
88
+ function override(next: Options) {
89
+ let tab = model.state.active;
90
+
91
+ if (!tab) {
92
+ return;
93
+ }
94
+
95
+ overrides.set(tab, { ...overrides.get(tab), ...next });
96
+ write(revision, peek(revision) + 1);
97
+ peek(editor)?.focus();
98
+ }
99
+
100
+ let indents: Indentation[] = [false, true].flatMap((tabs) => INDENT_SIZES.map((size) => ({ size, tabs }))),
101
+ items: Item[] = [
102
+ ...(Object.keys(LANGUAGES) as Language[]).map((language): Item => ({
103
+ hidden: () => read(choice) !== 'language',
104
+ icon: mark(() => read(editor)?.state.language === language),
105
+ label: LANGUAGES[language],
106
+ onselect: () => override({ language })
107
+ })),
108
+ ...indents.map((indent): Item => ({
109
+ hidden: () => read(choice) !== 'indent',
110
+ icon: mark(() => {
111
+ let current = read(editor)?.state.indent;
112
+
113
+ return current?.size === indent.size && current.tabs === indent.tabs;
114
+ }),
115
+ label: indent.tabs ? `Indent using tabs, size ${indent.size}` : `Indent using ${indent.size} spaces`,
116
+ onselect: () => override(indentation(indent))
117
+ })),
118
+ ...(['off', 'delay', 'focus'] as const).map((mode): Item => ({
119
+ hidden: () => read(choice) !== 'autoSave',
120
+ icon: mark(() => view.autoSave === mode),
121
+ label: AUTO_SAVE_MODES[mode],
122
+ onselect: () => model.setPreferences({ autoSave: mode })
123
+ }))
124
+ ];
125
+
126
+ return {
127
+ attach: (controller: WorkspaceEditorController | undefined) => {
128
+ write(editor, controller && isCode(controller) ? controller : undefined);
129
+ },
130
+ connect: (element: HTMLElement) => {
131
+ let listening = new AbortController(),
132
+ update = () => {
133
+ view.autoSave = model.state.preferences.autoSave;
134
+ },
135
+ disconnect = autosave.connect(),
136
+ unsubscribe = model.subscribe(update);
137
+
138
+ update();
139
+ element.ownerDocument.defaultView?.addEventListener('blur', () => autosave.blur(true), { signal: listening.signal });
140
+ element.addEventListener('focusout', (event) => {
141
+ let panel = (event.target as Element).closest('.code-workspace-editor');
142
+
143
+ if (panel && !panel.contains(event.relatedTarget as Node | null)) {
144
+ autosave.blur();
145
+ }
146
+ }, { signal: listening.signal });
147
+
148
+ return () => {
149
+ listening.abort();
150
+ unsubscribe();
151
+ disconnect();
152
+ write(editor, undefined);
153
+ };
154
+ },
155
+ items: () => html`
156
+ <div class='code-workspace-status-items'>
157
+ ${code((controller) => {
158
+ let state = controller.state,
159
+ problems = () => `${state.problems.errors} errors, ${state.problems.warnings} warnings: go to the next problem`;
160
+
161
+ return html`
162
+ ${() => state.selections > 1 && html`<span class='code-workspace-status-item code-workspace-status-item--selections'>${state.selections} selections</span>`}
163
+ <button
164
+ class='button code-workspace-status-item code-workspace-status-item--problems'
165
+ type='button'
166
+ ${{
167
+ 'aria-label': problems,
168
+ disabled: () => !state.problems.errors && !state.problems.warnings,
169
+ onclick: () => {
170
+ void nextProblem().then((moved) => {
171
+ if (moved) {
172
+ peek(editor)?.focus();
173
+ }
174
+ });
175
+ },
176
+ title: problems
177
+ }}
178
+ >
179
+ ${icon({ 'aria-hidden': 'true', class: 'code-workspace-status-icon' }, alert)}
180
+ ${() => state.problems.errors}
181
+ ${icon({ 'aria-hidden': 'true', class: 'code-workspace-status-icon' }, warning)}
182
+ ${() => state.problems.warnings}
183
+ </button>
184
+ ${item(
185
+ 'language',
186
+ () => LANGUAGES[state.language],
187
+ (event) => choose('language', event.currentTarget as HTMLElement),
188
+ 'Select language'
189
+ )}
190
+ ${item(
191
+ 'indent',
192
+ () => indentLabel(state.indent),
193
+ (event) => choose('indent', event.currentTarget as HTMLElement),
194
+ 'Select indentation'
195
+ )}
196
+ ${item(
197
+ 'eol',
198
+ () => (state.lineEnding === 'crlf' ? 'CRLF' : 'LF'),
199
+ () => {
200
+ lineEndings(controller.document, state.lineEnding === 'crlf' ? 'lf' : 'crlf');
201
+ },
202
+ () => (state.lineEnding === 'crlf' ? 'Convert line endings to LF' : 'Convert line endings to CRLF')
203
+ )}
204
+ <span class='code-workspace-status-item code-workspace-status-item--encoding' title='Encoding'>UTF-8</span>
205
+ `;
206
+ })}
207
+ ${item(
208
+ 'autosave',
209
+ () => `Auto Save: ${AUTO_SAVE_MODES[view.autoSave]}`,
210
+ (event) => choose('autoSave', event.currentTarget as HTMLElement),
211
+ 'Select auto save'
212
+ )}
213
+ </div>
214
+ `,
215
+ menu: () => tooltip.context(
216
+ {
217
+ class: 'code-workspace-menu',
218
+ controller: (value: MenuController) => {
219
+ menu = value;
220
+ },
221
+ items,
222
+ [tooltip.context.panel]: { 'aria-label': () => CHOICES[read(choice)], class: 'code-workspace-choices code-workspace-menu-panel' }
223
+ },
224
+ ''
225
+ ),
226
+ options: (tab: WorkspaceTab) => {
227
+ read(revision);
228
+
229
+ return overrides.get(tab);
230
+ },
231
+ // While auto save is on, its status stands where the save button was.
232
+ save: (button: () => Renderable<unknown>) => () => {
233
+ if (view.autoSave === 'off') {
234
+ return button();
235
+ }
236
+
237
+ return html`
238
+ <button
239
+ class='button code-workspace-autosave'
240
+ type='button'
241
+ ${{
242
+ 'aria-label': () => `Auto save: ${AUTO_SAVE_MODES[view.autoSave]}`,
243
+ onclick: (event: MouseEvent) => choose('autoSave', event.currentTarget as HTMLElement, true),
244
+ title: () => `Auto save: ${AUTO_SAVE_MODES[view.autoSave]}`
245
+ }}
246
+ >
247
+ ${untrack(() => status.render(autosave.status))}
248
+ </button>
249
+ `;
250
+ }
251
+ };
252
+ };
253
+
254
+
255
+ export default statusbar;
@@ -0,0 +1,273 @@
1
+ import { flush, reactive } from '@esportsplus/reactivity';
2
+ import { html } from '@esportsplus/template';
3
+ import icon from '~/components/icon';
4
+ import tooltip from '~/components/tooltip';
5
+ import type { Controller as MenuController, Item } from '~/components/tooltip/menu';
6
+ import { mac } from '~/shared/platform';
7
+ import diffs from '../diffs';
8
+ import type { WorkspaceEditor } from './index';
9
+ import type { EditorWorkspaceModel, WorkspaceTab } from './model';
10
+ import { sides, type MergeSides } from './tabs';
11
+ import pin from '@esportsplus/ui/svg/pin.svg';
12
+ import './scss/tabs.scss';
13
+
14
+
15
+ type Options = {
16
+ isFile: (path: string) => boolean;
17
+ model: EditorWorkspaceModel;
18
+ // Puts the active tab in the pane again, so a merge starting or ending on it takes effect.
19
+ remount: VoidFunction;
20
+ reveal: (path: string) => void;
21
+ };
22
+
23
+
24
+ function name(path: string) {
25
+ return path.slice(path.lastIndexOf('/') + 1);
26
+ }
27
+
28
+
29
+ /** Pinned and preview tabs, the tab context menu, merging a conflicted tab and comparing two files. */
30
+ const strip = ({ isFile, model, remount, reveal }: Options) => {
31
+ let chosen = '',
32
+ controller: MenuController | undefined,
33
+ merging = new WeakMap<WorkspaceTab, MergeSides>(),
34
+ subject = reactive({ compare: false, conflicted: false, path: '', pinned: false });
35
+
36
+ function compare(tab: WorkspaceTab): WorkspaceEditor {
37
+ let { modified, original, paths } = tab.compare!;
38
+
39
+ return () => diffs({
40
+ class: 'code-workspace-document code-workspace-compare',
41
+ filename: `${paths[0]} ↔ ${paths[1]}`,
42
+ modified,
43
+ original
44
+ });
45
+ }
46
+
47
+ function merge(tab: WorkspaceTab, found: MergeSides): WorkspaceEditor {
48
+ return () => html`
49
+ <div class='code-workspace-document code-workspace-merge'>
50
+ <div class='code-workspace-merge-bar'>
51
+ <span class='code-workspace-merge-title'>Merging ${tab.path}</span>
52
+ <button
53
+ class='button code-workspace-merge-cancel'
54
+ type='button'
55
+ ${{
56
+ onclick: () => {
57
+ merging.delete(tab);
58
+ remount();
59
+ }
60
+ }}
61
+ >
62
+ Cancel merge
63
+ </button>
64
+ </div>
65
+ ${diffs.merge({
66
+ base: found.base,
67
+ class: 'code-workspace-merge-editor',
68
+ current: found.current,
69
+ filename: tab.path,
70
+ incoming: found.incoming,
71
+ onresolve: (result) => {
72
+ merging.delete(tab);
73
+ tab.document.setValue(result);
74
+ remount();
75
+ void model.save(tab);
76
+ }
77
+ })}
78
+ </div>
79
+ `;
80
+ }
81
+
82
+ let items: Item[] = [
83
+ {
84
+ hidden: () => subject.compare || subject.pinned,
85
+ label: 'Pin',
86
+ onselect: () => model.pin(subject.path)
87
+ },
88
+ {
89
+ hidden: () => !subject.pinned,
90
+ label: 'Unpin',
91
+ onselect: () => model.unpin(subject.path)
92
+ },
93
+ {
94
+ hidden: () => !subject.conflicted,
95
+ label: 'Merge Conflicts',
96
+ onselect: () => {
97
+ void api.merge(subject.path);
98
+ }
99
+ },
100
+ {
101
+ hint: mac() ? '⌘W' : 'Ctrl+W',
102
+ label: 'Close',
103
+ onselect: () => {
104
+ void model.close(subject.path);
105
+ }
106
+ },
107
+ {
108
+ label: 'Close Others',
109
+ onselect: () => {
110
+ let path = subject.path;
111
+
112
+ void model.closeOthers(path).then((closed) => closed && model.activate(path));
113
+ }
114
+ },
115
+ {
116
+ label: 'Close to the Right',
117
+ onselect: () => {
118
+ let path = subject.path;
119
+
120
+ void model.closeRight(path).then((closed) => closed && model.activate(path));
121
+ }
122
+ },
123
+ {
124
+ label: 'Close Saved',
125
+ onselect: () => {
126
+ void model.closeSaved();
127
+ }
128
+ },
129
+ {
130
+ hidden: () => subject.compare,
131
+ label: 'Copy Path',
132
+ onselect: () => {
133
+ void model.copyPath(subject.path);
134
+ }
135
+ },
136
+ {
137
+ hidden: () => subject.compare,
138
+ label: 'Reveal in Explorer',
139
+ onselect: () => reveal(subject.path)
140
+ }
141
+ ];
142
+
143
+ let api = {
144
+ // Spread on a tab: its preview and pinned looks, its context menu, and a double click that keeps a preview.
145
+ attributes(tab: WorkspaceTab) {
146
+ let modifiers = [tab.pinned && 'code-workspace-tab--pinned', tab.preview && 'code-workspace-tab--preview'].filter(Boolean);
147
+
148
+ return {
149
+ ...(modifiers.length ? { class: modifiers.join(' ') } : {}),
150
+ oncontextmenu: (event: MouseEvent) => api.open(tab, event),
151
+ ondblclick: () => {
152
+ if (tab.preview) {
153
+ void model.open(tab.path);
154
+ }
155
+ }
156
+ };
157
+ },
158
+
159
+ // The view a tab shows in place of its editor: a compare tab's diff, or the merge started on it.
160
+ editor(tab: WorkspaceTab): WorkspaceEditor | undefined {
161
+ if (tab.compare) {
162
+ return compare(tab);
163
+ }
164
+
165
+ let found = merging.get(tab);
166
+
167
+ return found && merge(tab, found);
168
+ },
169
+
170
+ // Tree context menu entries, against the paths the menu opened on.
171
+ items(paths: () => string[]): Item[] {
172
+ let files = () => paths().filter(isFile);
173
+
174
+ return [
175
+ {
176
+ hidden: () => paths().length !== 1 || files().length !== 1,
177
+ label: 'Select for Compare',
178
+ onselect: () => {
179
+ chosen = paths()[0];
180
+ model.status(`Selected ${chosen} for compare`);
181
+ }
182
+ },
183
+ {
184
+ hidden: () => {
185
+ let list = files();
186
+
187
+ return list.length !== paths().length || !(list.length === 2 || (list.length === 1 && !!chosen && chosen !== list[0]));
188
+ },
189
+ label: 'Compare with Selected',
190
+ onselect: () => {
191
+ let list = files();
192
+
193
+ void (list.length === 2 ? model.compare(list[0], list[1]) : model.compare(chosen, list[0]));
194
+ }
195
+ },
196
+ {
197
+ hidden: () => paths().length !== 1 || files().length !== 1,
198
+ label: 'Merge Conflicts',
199
+ onselect: () => {
200
+ void api.merge(paths()[0]);
201
+ }
202
+ }
203
+ ];
204
+ },
205
+
206
+ label(tab: WorkspaceTab) {
207
+ return tab.compare ? `${name(tab.compare.paths[0])} ↔ ${name(tab.compare.paths[1])}` : name(tab.path);
208
+ },
209
+
210
+ // Shows the merge editor in place of the file's editor, with the versions its conflict markers hold.
211
+ async merge(target: WorkspaceTab | string) {
212
+ let tab = typeof target === 'string' ? await model.open(target) : target;
213
+
214
+ if (!tab || tab.compare) {
215
+ return;
216
+ }
217
+
218
+ let found = sides(tab.document.value);
219
+
220
+ if (!found) {
221
+ model.status(`${tab.path} has no conflict markers`);
222
+ return;
223
+ }
224
+
225
+ merging.set(tab, found);
226
+ model.activate(tab);
227
+ remount();
228
+ },
229
+
230
+ menu: () => tooltip.context(
231
+ {
232
+ class: 'code-workspace-menu',
233
+ controller: (value: MenuController) => {
234
+ controller = value;
235
+ },
236
+ items,
237
+ [tooltip.context.panel]: { 'aria-label': 'Tab actions', class: 'code-workspace-menu-panel' }
238
+ },
239
+ ''
240
+ ),
241
+
242
+ open(tab: WorkspaceTab, event: MouseEvent) {
243
+ if (!controller) {
244
+ return;
245
+ }
246
+
247
+ event.preventDefault();
248
+
249
+ // A context menu key reports no pointer, so the menu opens under the tab instead.
250
+ let box = event.button === 2 ? undefined : (event.currentTarget as HTMLElement).getBoundingClientRect();
251
+
252
+ subject.compare = !!tab.compare;
253
+ subject.conflicted = !tab.compare && !!sides(tab.document.value);
254
+ subject.path = tab.path;
255
+ subject.pinned = tab.pinned;
256
+ flush();
257
+ controller.open(box ? { x: box.left, y: box.bottom } : { x: event.clientX, y: event.clientY });
258
+ },
259
+
260
+ pin(tab: WorkspaceTab) {
261
+ return tab.pinned && icon({ 'aria-label': 'Pinned', class: 'code-workspace-tab-pin', role: 'img' }, pin);
262
+ },
263
+
264
+ title(tab: WorkspaceTab) {
265
+ return tab.compare ? `${tab.compare.paths[0]} ↔ ${tab.compare.paths[1]}` : tab.path;
266
+ }
267
+ };
268
+
269
+ return api;
270
+ };
271
+
272
+
273
+ export default strip;
@@ -0,0 +1,106 @@
1
+ import { EditorDocument } from '../code/document';
2
+ import { conflictMarkers, resolveMarker } from '../diffs/diff3';
3
+ import type { WorkspaceCompare, WorkspaceTab } from './model';
4
+
5
+
6
+ type Closable = 'others' | 'right' | 'saved';
7
+
8
+ // A conflicted file split back into the versions its markers hold, as the merge editor takes them.
9
+ type MergeSides = { base: string | null; current: string; incoming: string };
10
+
11
+
12
+ // No workspace path holds a NUL, so a compare tab's key never matches a file's path, nor lies inside a folder.
13
+ const SEPARATOR = '\u0000';
14
+
15
+ const TRAILING_EOL = /(?:\r\n|\r|\n)$/;
16
+
17
+
18
+ // Bulk closes leave pinned tabs and the tab they were asked from; 'saved' also keeps drafts of files gone from disk.
19
+ const closable = (tabs: readonly WorkspaceTab[], kind: Closable, path?: string) => {
20
+ let at = tabs.findIndex((tab) => tab.path === path);
21
+
22
+ return tabs.filter((tab, i) => {
23
+ if (tab.pinned || tab.path === path) {
24
+ return false;
25
+ }
26
+
27
+ if (kind === 'right') {
28
+ return at !== -1 && i > at;
29
+ }
30
+
31
+ return kind === 'others' || (!tab.missing && tab.document.value === tab.saved);
32
+ });
33
+ };
34
+
35
+ const compareKey = (original: string, modified: string) => `${SEPARATOR}${original}${SEPARATOR}${modified}`;
36
+
37
+ // A compare tab's document stays empty and saved, so nothing that reads tabs ever finds it dirty.
38
+ const compareTab = (id: number, compare: WorkspaceCompare): WorkspaceTab => ({
39
+ compare,
40
+ document: new EditorDocument(''),
41
+ id,
42
+ missing: false,
43
+ path: compareKey(compare.paths[0], compare.paths[1]),
44
+ pinned: false,
45
+ preview: false,
46
+ saved: '',
47
+ scroll: { left: 0, top: 0 }
48
+ });
49
+
50
+ // Pinned tabs lead; a stable sort keeps every other tab where it was among its group.
51
+ const order = (tabs: WorkspaceTab[]) => {
52
+ tabs.sort((a, b) => Number(b.pinned) - Number(a.pinned));
53
+ };
54
+
55
+ // A preview tab takes the place of the last one, which the caller then removes.
56
+ const place = (tabs: WorkspaceTab[], tab: WorkspaceTab) => {
57
+ let at = tab.preview ? tabs.findIndex((item) => item.preview) : -1;
58
+
59
+ if (at === -1) {
60
+ tabs.push(tab);
61
+ return;
62
+ }
63
+
64
+ let replaced = tabs[at];
65
+
66
+ tabs.splice(at, 0, tab);
67
+
68
+ return replaced;
69
+ };
70
+
71
+ const sides = (text: string): MergeSides | null => {
72
+ let markers = conflictMarkers(text);
73
+
74
+ if (!markers.length) {
75
+ return null;
76
+ }
77
+
78
+ let at = 0,
79
+ base: string | null = '',
80
+ current = '',
81
+ incoming = '';
82
+
83
+ for (let i = 0, n = markers.length; i < n; i++) {
84
+ let marker = markers[i],
85
+ between = text.slice(at, marker.from);
86
+
87
+ if (base !== null && marker.base !== null) {
88
+ base += between + (marker.to === text.length && !TRAILING_EOL.test(text) ? marker.base.replace(TRAILING_EOL, '') : marker.base);
89
+ }
90
+ else {
91
+ base = null;
92
+ }
93
+
94
+ current += between + resolveMarker(text, marker, 'current');
95
+ incoming += between + resolveMarker(text, marker, 'incoming');
96
+ at = marker.to;
97
+ }
98
+
99
+ let rest = text.slice(at);
100
+
101
+ return { base: base === null ? null : base + rest, current: current + rest, incoming: incoming + rest };
102
+ };
103
+
104
+
105
+ export { closable, compareKey, compareTab, order, place, sides };
106
+ export type { Closable, MergeSides };
@@ -24,7 +24,7 @@ type Direction = 'e' | 'en' | 'es' | 'n' | 'ne' | 'nw' | 's' | 'se' | 'sw' | 'w'
24
24
 
25
25
 
26
26
  // The morph tooltip's '--morph-close-duration', plus a frame: a new message reopens once the old one has landed.
27
- const CLOSE = 180;
27
+ const CLOSE = 210;
28
28
 
29
29
 
30
30
  // Wraps one control, so it works on any element that keeps its error in 'state.error': the control shakes and its