@k2b/ui 0.27.0 → 0.29.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 (323) hide show
  1. package/README.md +1 -1
  2. package/dist/base.css +147 -2
  3. package/dist/browser/actions/ContextMenu.js +35 -4
  4. package/dist/browser/actions/ContextMenu.js.map +1 -1
  5. package/dist/browser/actions/DragAndDrop.js +89 -0
  6. package/dist/browser/actions/DragAndDrop.js.map +1 -0
  7. package/dist/browser/actions/Dropdown.js +184 -158
  8. package/dist/browser/actions/Dropdown.js.map +1 -1
  9. package/dist/browser/actions/GestureMenu.js +95 -139
  10. package/dist/browser/actions/GestureMenu.js.map +1 -1
  11. package/dist/browser/actions/Toolbar.js +379 -48
  12. package/dist/browser/actions/Toolbar.js.map +1 -1
  13. package/dist/browser/actions/drag-and-drop-messages.js +75 -0
  14. package/dist/browser/actions/drag-and-drop-messages.js.map +1 -0
  15. package/dist/browser/actions/drag-and-drop.js +692 -0
  16. package/dist/browser/actions/drag-and-drop.js.map +1 -0
  17. package/dist/browser/actions/index.js +1 -0
  18. package/dist/browser/actions/index.js.map +1 -1
  19. package/dist/browser/actions/menu-rows.js +15 -0
  20. package/dist/browser/actions/menu-rows.js.map +1 -0
  21. package/dist/browser/actions/menu-sheet.js +154 -0
  22. package/dist/browser/actions/menu-sheet.js.map +1 -0
  23. package/dist/browser/actions/toolbar-messages.js +20 -0
  24. package/dist/browser/actions/toolbar-messages.js.map +1 -0
  25. package/dist/browser/chart-inspection.js +3 -0
  26. package/dist/browser/chart-inspection.js.map +1 -0
  27. package/dist/browser/chat/ChatComposer.js +714 -410
  28. package/dist/browser/chat/ChatComposer.js.map +1 -1
  29. package/dist/browser/chat/ChatDecision.js +778 -0
  30. package/dist/browser/chat/ChatDecision.js.map +1 -0
  31. package/dist/browser/chat/ChatPrimitives.js +34 -28
  32. package/dist/browser/chat/ChatPrimitives.js.map +1 -1
  33. package/dist/browser/chat/ChatTimeline.js.map +1 -1
  34. package/dist/browser/chat/chat-messages.js +25 -1
  35. package/dist/browser/chat/chat-messages.js.map +1 -1
  36. package/dist/browser/chat/command-search.js +13 -3
  37. package/dist/browser/chat/command-search.js.map +1 -1
  38. package/dist/browser/chat/index.js +8 -1
  39. package/dist/browser/chat/index.js.map +1 -1
  40. package/dist/browser/chat/reaction-people.js +15 -0
  41. package/dist/browser/chat/reaction-people.js.map +1 -0
  42. package/dist/browser/chat/types.js.map +1 -1
  43. package/dist/browser/content/Calendar.js +3 -3
  44. package/dist/browser/content/Calendar.js.map +1 -1
  45. package/dist/browser/content/Chart.js +60 -86
  46. package/dist/browser/content/Chart.js.map +1 -1
  47. package/dist/browser/content/ChartSnapshotView.js +7 -10
  48. package/dist/browser/content/ChartSnapshotView.js.map +1 -1
  49. package/dist/browser/content/FileBrowser.js +2 -2
  50. package/dist/browser/content/FileBrowser.js.map +1 -1
  51. package/dist/browser/content/FileTree.js +42 -36
  52. package/dist/browser/content/FileTree.js.map +1 -1
  53. package/dist/browser/content/FileTypeIcon.js +72 -0
  54. package/dist/browser/content/FileTypeIcon.js.map +1 -0
  55. package/dist/browser/content/FileView.js +2 -2
  56. package/dist/browser/content/FileView.js.map +1 -1
  57. package/dist/browser/content/MessageRow.js +330 -448
  58. package/dist/browser/content/MessageRow.js.map +1 -1
  59. package/dist/browser/content/ReactionBar.js +419 -0
  60. package/dist/browser/content/ReactionBar.js.map +1 -0
  61. package/dist/browser/content/ReferenceChip.js +162 -0
  62. package/dist/browser/content/ReferenceChip.js.map +1 -0
  63. package/dist/browser/content/calendar-pointer.js +9 -0
  64. package/dist/browser/content/calendar-pointer.js.map +1 -1
  65. package/dist/browser/content/calendar-time-view.js +6 -3
  66. package/dist/browser/content/calendar-time-view.js.map +1 -1
  67. package/dist/browser/content/chart-inspection-core.js +557 -0
  68. package/dist/browser/content/chart-inspection-core.js.map +1 -0
  69. package/dist/browser/content/chart-inspection.js +10 -445
  70. package/dist/browser/content/chart-inspection.js.map +1 -1
  71. package/dist/browser/content/chart-line-gaps.js +1 -1
  72. package/dist/browser/content/chart-line-gaps.js.map +1 -1
  73. package/dist/browser/content/chart-snapshot.js +1 -1
  74. package/dist/browser/content/chart-snapshot.js.map +1 -1
  75. package/dist/browser/content/index.js +3 -0
  76. package/dist/browser/content/index.js.map +1 -1
  77. package/dist/browser/feedback/dialog-core.js +135 -23
  78. package/dist/browser/feedback/dialog-core.js.map +1 -1
  79. package/dist/browser/index.js +1 -0
  80. package/dist/browser/index.js.map +1 -1
  81. package/dist/browser/input-mode.js +40 -0
  82. package/dist/browser/input-mode.js.map +1 -0
  83. package/dist/browser/inputs/FileDropTarget.js +24 -9
  84. package/dist/browser/inputs/FileDropTarget.js.map +1 -1
  85. package/dist/browser/inputs/FileInputs.js +2 -2
  86. package/dist/browser/inputs/FileInputs.js.map +1 -1
  87. package/dist/browser/inputs/SelectChip.js +9 -0
  88. package/dist/browser/inputs/SelectChip.js.map +1 -1
  89. package/dist/browser/inputs/emoji/EmojiPicker.js +13 -0
  90. package/dist/browser/inputs/emoji/EmojiPicker.js.map +1 -1
  91. package/dist/browser/inputs/file-drop.js.map +1 -1
  92. package/dist/browser/layout/AppOverview.js +1 -1
  93. package/dist/browser/layout/AppOverview.js.map +1 -1
  94. package/dist/browser/layout/AppWorkspace.js +644 -445
  95. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  96. package/dist/browser/layout/DetailPanel.js +283 -197
  97. package/dist/browser/layout/DetailPanel.js.map +1 -1
  98. package/dist/browser/layout/Discussion.js +233 -185
  99. package/dist/browser/layout/Discussion.js.map +1 -1
  100. package/dist/browser/layout/PanelDialog.js +88 -86
  101. package/dist/browser/layout/PanelDialog.js.map +1 -1
  102. package/dist/browser/layout/ResizeSeparator.js +81 -0
  103. package/dist/browser/layout/ResizeSeparator.js.map +1 -0
  104. package/dist/browser/layout/SidebarSwitcher.js +9 -2
  105. package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
  106. package/dist/browser/layout/TabBar.js +15 -12
  107. package/dist/browser/layout/TabBar.js.map +1 -1
  108. package/dist/browser/layout/TableOfContents.js +10 -2
  109. package/dist/browser/layout/TableOfContents.js.map +1 -1
  110. package/dist/browser/layout/app-workspace-controller.js +130 -17
  111. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  112. package/dist/browser/layout/detail-panel-messages.js +35 -0
  113. package/dist/browser/layout/detail-panel-messages.js.map +1 -0
  114. package/dist/browser/layout/index.js +3 -1
  115. package/dist/browser/layout/index.js.map +1 -1
  116. package/dist/browser/layout/resize-separator.js +90 -0
  117. package/dist/browser/layout/resize-separator.js.map +1 -0
  118. package/dist/browser/layout/workspace-messages.js +12 -2
  119. package/dist/browser/layout/workspace-messages.js.map +1 -1
  120. package/dist/browser/surfaces/Avatar.js +50 -20
  121. package/dist/browser/surfaces/Avatar.js.map +1 -1
  122. package/dist/browser/surfaces/AvatarStack.js +406 -0
  123. package/dist/browser/surfaces/AvatarStack.js.map +1 -0
  124. package/dist/browser/surfaces/LinkCard.js +1 -1
  125. package/dist/browser/surfaces/LinkCard.js.map +1 -1
  126. package/dist/browser/surfaces/Placeholder.js +14 -3
  127. package/dist/browser/surfaces/Placeholder.js.map +1 -1
  128. package/dist/browser/surfaces/StatCell.js +23 -0
  129. package/dist/browser/surfaces/StatCell.js.map +1 -1
  130. package/dist/browser/surfaces/avatar-messages.js +8 -2
  131. package/dist/browser/surfaces/avatar-messages.js.map +1 -1
  132. package/dist/browser/surfaces/index.js +1 -0
  133. package/dist/browser/surfaces/index.js.map +1 -1
  134. package/dist/browser/widgets/Widget.js +1 -1
  135. package/dist/browser/widgets/Widget.js.map +1 -1
  136. package/dist/ssr/actions/ContextMenu.js +26 -3
  137. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  138. package/dist/ssr/actions/DragAndDrop.js +63 -0
  139. package/dist/ssr/actions/DragAndDrop.js.map +1 -0
  140. package/dist/ssr/actions/Dropdown.js +140 -72
  141. package/dist/ssr/actions/Dropdown.js.map +1 -1
  142. package/dist/ssr/actions/GestureMenu.js +76 -107
  143. package/dist/ssr/actions/GestureMenu.js.map +1 -1
  144. package/dist/ssr/actions/Toolbar.js +294 -14
  145. package/dist/ssr/actions/Toolbar.js.map +1 -1
  146. package/dist/ssr/actions/drag-and-drop-messages.js +75 -0
  147. package/dist/ssr/actions/drag-and-drop-messages.js.map +1 -0
  148. package/dist/ssr/actions/drag-and-drop.js +692 -0
  149. package/dist/ssr/actions/drag-and-drop.js.map +1 -0
  150. package/dist/ssr/actions/index.js +1 -0
  151. package/dist/ssr/actions/index.js.map +1 -1
  152. package/dist/ssr/actions/menu-rows.js +15 -0
  153. package/dist/ssr/actions/menu-rows.js.map +1 -0
  154. package/dist/ssr/actions/menu-sheet.js +138 -0
  155. package/dist/ssr/actions/menu-sheet.js.map +1 -0
  156. package/dist/ssr/actions/toolbar-messages.js +20 -0
  157. package/dist/ssr/actions/toolbar-messages.js.map +1 -0
  158. package/dist/ssr/chart-inspection.js +3 -0
  159. package/dist/ssr/chart-inspection.js.map +1 -0
  160. package/dist/ssr/chat/ChatComposer.js +393 -102
  161. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  162. package/dist/ssr/chat/ChatDecision.js +465 -0
  163. package/dist/ssr/chat/ChatDecision.js.map +1 -0
  164. package/dist/ssr/chat/ChatPrimitives.js +2 -2
  165. package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
  166. package/dist/ssr/chat/ChatTimeline.js.map +1 -1
  167. package/dist/ssr/chat/chat-messages.js +25 -1
  168. package/dist/ssr/chat/chat-messages.js.map +1 -1
  169. package/dist/ssr/chat/command-search.js +13 -3
  170. package/dist/ssr/chat/command-search.js.map +1 -1
  171. package/dist/ssr/chat/index.js +8 -1
  172. package/dist/ssr/chat/index.js.map +1 -1
  173. package/dist/ssr/chat/reaction-people.js +15 -0
  174. package/dist/ssr/chat/reaction-people.js.map +1 -0
  175. package/dist/ssr/chat/types.js.map +1 -1
  176. package/dist/ssr/content/Calendar.js +3 -3
  177. package/dist/ssr/content/Calendar.js.map +1 -1
  178. package/dist/ssr/content/Chart.js +25 -38
  179. package/dist/ssr/content/Chart.js.map +1 -1
  180. package/dist/ssr/content/ChartSnapshotView.js +7 -10
  181. package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
  182. package/dist/ssr/content/FileBrowser.js +2 -2
  183. package/dist/ssr/content/FileBrowser.js.map +1 -1
  184. package/dist/ssr/content/FileTree.js +21 -14
  185. package/dist/ssr/content/FileTree.js.map +1 -1
  186. package/dist/ssr/content/FileTypeIcon.js +50 -0
  187. package/dist/ssr/content/FileTypeIcon.js.map +1 -0
  188. package/dist/ssr/content/FileView.js +2 -2
  189. package/dist/ssr/content/FileView.js.map +1 -1
  190. package/dist/ssr/content/MessageRow.js +98 -152
  191. package/dist/ssr/content/MessageRow.js.map +1 -1
  192. package/dist/ssr/content/ReactionBar.js +304 -0
  193. package/dist/ssr/content/ReactionBar.js.map +1 -0
  194. package/dist/ssr/content/ReferenceChip.js +121 -0
  195. package/dist/ssr/content/ReferenceChip.js.map +1 -0
  196. package/dist/ssr/content/calendar-pointer.js +9 -0
  197. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  198. package/dist/ssr/content/calendar-time-view.js +6 -3
  199. package/dist/ssr/content/calendar-time-view.js.map +1 -1
  200. package/dist/ssr/content/chart-inspection-core.js +557 -0
  201. package/dist/ssr/content/chart-inspection-core.js.map +1 -0
  202. package/dist/ssr/content/chart-inspection.js +10 -445
  203. package/dist/ssr/content/chart-inspection.js.map +1 -1
  204. package/dist/ssr/content/chart-line-gaps.js +1 -1
  205. package/dist/ssr/content/chart-line-gaps.js.map +1 -1
  206. package/dist/ssr/content/chart-snapshot.js +1 -1
  207. package/dist/ssr/content/chart-snapshot.js.map +1 -1
  208. package/dist/ssr/content/index.js +3 -0
  209. package/dist/ssr/content/index.js.map +1 -1
  210. package/dist/ssr/feedback/dialog-core.js +135 -23
  211. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  212. package/dist/ssr/index.js +1 -0
  213. package/dist/ssr/index.js.map +1 -1
  214. package/dist/ssr/input-mode.js +40 -0
  215. package/dist/ssr/input-mode.js.map +1 -0
  216. package/dist/ssr/inputs/FileDropTarget.js +17 -5
  217. package/dist/ssr/inputs/FileDropTarget.js.map +1 -1
  218. package/dist/ssr/inputs/FileInputs.js +2 -2
  219. package/dist/ssr/inputs/FileInputs.js.map +1 -1
  220. package/dist/ssr/inputs/SelectChip.js +9 -0
  221. package/dist/ssr/inputs/SelectChip.js.map +1 -1
  222. package/dist/ssr/inputs/emoji/EmojiPicker.js +12 -0
  223. package/dist/ssr/inputs/emoji/EmojiPicker.js.map +1 -1
  224. package/dist/ssr/inputs/file-drop.js.map +1 -1
  225. package/dist/ssr/layout/AppOverview.js +1 -1
  226. package/dist/ssr/layout/AppOverview.js.map +1 -1
  227. package/dist/ssr/layout/AppWorkspace.js +272 -95
  228. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  229. package/dist/ssr/layout/DetailPanel.js +112 -58
  230. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  231. package/dist/ssr/layout/Discussion.js +63 -36
  232. package/dist/ssr/layout/Discussion.js.map +1 -1
  233. package/dist/ssr/layout/PanelDialog.js +7 -6
  234. package/dist/ssr/layout/PanelDialog.js.map +1 -1
  235. package/dist/ssr/layout/ResizeSeparator.js +45 -0
  236. package/dist/ssr/layout/ResizeSeparator.js.map +1 -0
  237. package/dist/ssr/layout/SidebarSwitcher.js +9 -2
  238. package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
  239. package/dist/ssr/layout/TabBar.js +1 -1
  240. package/dist/ssr/layout/TabBar.js.map +1 -1
  241. package/dist/ssr/layout/TableOfContents.js +10 -2
  242. package/dist/ssr/layout/TableOfContents.js.map +1 -1
  243. package/dist/ssr/layout/app-workspace-controller.js +130 -17
  244. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  245. package/dist/ssr/layout/detail-panel-messages.js +35 -0
  246. package/dist/ssr/layout/detail-panel-messages.js.map +1 -0
  247. package/dist/ssr/layout/index.js +3 -1
  248. package/dist/ssr/layout/index.js.map +1 -1
  249. package/dist/ssr/layout/resize-separator.js +90 -0
  250. package/dist/ssr/layout/resize-separator.js.map +1 -0
  251. package/dist/ssr/layout/workspace-messages.js +12 -2
  252. package/dist/ssr/layout/workspace-messages.js.map +1 -1
  253. package/dist/ssr/surfaces/Avatar.js +20 -2
  254. package/dist/ssr/surfaces/Avatar.js.map +1 -1
  255. package/dist/ssr/surfaces/AvatarStack.js +286 -0
  256. package/dist/ssr/surfaces/AvatarStack.js.map +1 -0
  257. package/dist/ssr/surfaces/LinkCard.js +1 -1
  258. package/dist/ssr/surfaces/LinkCard.js.map +1 -1
  259. package/dist/ssr/surfaces/Placeholder.js +4 -2
  260. package/dist/ssr/surfaces/Placeholder.js.map +1 -1
  261. package/dist/ssr/surfaces/StatCell.js +23 -0
  262. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  263. package/dist/ssr/surfaces/avatar-messages.js +8 -2
  264. package/dist/ssr/surfaces/avatar-messages.js.map +1 -1
  265. package/dist/ssr/surfaces/index.js +1 -0
  266. package/dist/ssr/surfaces/index.js.map +1 -1
  267. package/dist/ssr/widgets/Widget.js +1 -1
  268. package/dist/ssr/widgets/Widget.js.map +1 -1
  269. package/dist/styles.css +1 -1
  270. package/dist/types/actions/ContextMenu.d.ts +9 -0
  271. package/dist/types/actions/DragAndDrop.d.ts +29 -0
  272. package/dist/types/actions/Dropdown.d.ts +12 -5
  273. package/dist/types/actions/GestureMenu.d.ts +6 -4
  274. package/dist/types/actions/Toolbar.d.ts +20 -0
  275. package/dist/types/actions/drag-and-drop-messages.d.ts +35 -0
  276. package/dist/types/actions/drag-and-drop.d.ts +36 -0
  277. package/dist/types/actions/index.d.ts +3 -1
  278. package/dist/types/actions/menu-rows.d.ts +5 -0
  279. package/dist/types/actions/menu-sheet.d.ts +22 -0
  280. package/dist/types/actions/toolbar-messages.d.ts +8 -0
  281. package/dist/types/chart-inspection.d.ts +2 -0
  282. package/dist/types/chat/ChatComposer.d.ts +26 -1
  283. package/dist/types/chat/ChatDecision.d.ts +133 -0
  284. package/dist/types/chat/ChatPrimitives.d.ts +4 -1
  285. package/dist/types/chat/ChatTimeline.d.ts +2 -1
  286. package/dist/types/chat/chat-messages.d.ts +13 -2
  287. package/dist/types/chat/command-search.d.ts +5 -0
  288. package/dist/types/chat/index.d.ts +25 -1
  289. package/dist/types/chat/reaction-people.d.ts +9 -0
  290. package/dist/types/chat/types.d.ts +54 -1
  291. package/dist/types/content/Chart.d.ts +11 -5
  292. package/dist/types/content/FileTypeIcon.d.ts +27 -0
  293. package/dist/types/content/MessageRow.d.ts +3 -10
  294. package/dist/types/content/ReactionBar.d.ts +32 -0
  295. package/dist/types/content/ReferenceChip.d.ts +49 -0
  296. package/dist/types/content/calendar-pointer.d.ts +6 -0
  297. package/dist/types/content/chart-inspection-core.d.ts +61 -0
  298. package/dist/types/content/chart-inspection.d.ts +4 -20
  299. package/dist/types/content/chart-snapshot.d.ts +1 -1
  300. package/dist/types/content/index.d.ts +5 -1
  301. package/dist/types/feedback/dialog-core.d.ts +16 -1
  302. package/dist/types/index.d.ts +1 -0
  303. package/dist/types/input-mode.d.ts +7 -0
  304. package/dist/types/inputs/FileDropTarget.d.ts +6 -3
  305. package/dist/types/inputs/SelectChip.d.ts +2 -0
  306. package/dist/types/inputs/file-drop.d.ts +2 -0
  307. package/dist/types/layout/AppWorkspace.d.ts +5 -3
  308. package/dist/types/layout/DetailPanel.d.ts +11 -0
  309. package/dist/types/layout/Discussion.d.ts +8 -0
  310. package/dist/types/layout/ResizeSeparator.d.ts +9 -0
  311. package/dist/types/layout/TabBar.d.ts +7 -0
  312. package/dist/types/layout/TableOfContents.d.ts +2 -0
  313. package/dist/types/layout/app-workspace-controller.d.ts +2 -0
  314. package/dist/types/layout/detail-panel-messages.d.ts +15 -0
  315. package/dist/types/layout/index.d.ts +3 -1
  316. package/dist/types/layout/resize-separator.d.ts +18 -0
  317. package/dist/types/layout/workspace-messages.d.ts +5 -0
  318. package/dist/types/surfaces/Avatar.d.ts +12 -0
  319. package/dist/types/surfaces/AvatarStack.d.ts +41 -0
  320. package/dist/types/surfaces/StatCell.d.ts +6 -0
  321. package/dist/types/surfaces/avatar-messages.d.ts +3 -0
  322. package/dist/types/surfaces/index.d.ts +3 -1
  323. package/package.json +7 -2
@@ -10,7 +10,7 @@ var _tmpl$ = ["<ul class=\"", "\"", " role=\"tree\"", ">", "</ul>"],
10
10
  _tmpl$4 = ["<span class=\"k2b-content-file-tree__badge\">", "</span>"],
11
11
  _tmpl$5 = "<i class=\"ti ti-dots\" aria-hidden=\"true\"></i>",
12
12
  _tmpl$6 = ["<span class=\"k2b-sr-only\">Actions for ", "</span>"],
13
- _tmpl$7 = ["<div", " class=\"k2b-content-file-tree__row\"><button type=\"button\" tabindex=\"-1\" class=\"k2b-content-file-tree__select\" style=\"", "\"", "><i class=\"", "\" aria-hidden=\"true\"></i><span class=\"k2b-content-file-tree__name\">", "</span>", "</button>", "</div>"];
13
+ _tmpl$7 = ["<div", " class=\"k2b-content-file-tree__row\"><button type=\"button\" tabindex=\"-1\" class=\"k2b-content-file-tree__select\" style=\"", "\"", ">", "<span class=\"k2b-content-file-tree__name\">", "</span>", "</button>", "</div>"];
14
14
  /**
15
15
  * FileTree — path-first tree over a flat entry list (folders derived from
16
16
  * paths, explicit folder entries allowed for empty dirs). Capabilities are
@@ -18,19 +18,13 @@ var _tmpl$ = ["<ul class=\"", "\"", " role=\"tree\"", ">", "</ul>"],
18
18
  * pure read-only browser. Context menus render through the platform
19
19
  * ContextMenu. Minimal look: text rows, bevel on selection, no hover motion.
20
20
  */
21
- import { fileIcons } from "@k2b/stdlib";
22
21
  import { createEffect, createMemo, createSignal, For, Show } from "solid-js";
23
22
  import ContextMenu from "../actions/ContextMenu";
24
23
  import Dropdown from "../actions/Dropdown";
25
24
  import { useUiMessages } from "../intl/messages";
25
+ import { FileTypeIcon } from "./FileTypeIcon";
26
26
  import { useFileBrowserMessages } from "./file-browser-messages";
27
27
  import { allFolderPaths, buildTree, flattenVisible, parentOf } from "./file-tree";
28
- /**
29
- * `fileIcons` (and app-supplied entry icons) may carry Tailwind colour classes.
30
- * @k2b/ui ships no Tailwind utilities, so only the `ti-*` glyph is kept — the
31
- * row owns the icon colour.
32
- */
33
- const glyphOnly = icon => icon.split(/\s+/).filter(token => token.startsWith("ti-")).join(" ");
34
28
 
35
29
  /** Presence of a callback enables the matching UI affordance. */
36
30
 
@@ -239,18 +233,31 @@ export default function FileTree(props) {
239
233
  };
240
234
  const isSelected = () => props.selectedPath === currentNode().entry.path;
241
235
  const isDropTarget = () => currentNode().isFolder && dropTarget() === currentNode().entry.path;
242
- const icon = () => currentNode().isFolder ? expanded().has(currentNode().entry.path) ? "ti-folder-open" : "ti-folder" : glyphOnly(currentNode().entry.icon ?? fileIcons.getFileIcon({
243
- name: currentNode().name,
244
- type: "file",
245
- mimeType: currentNode().entry.mediaType ?? "text/plain"
246
- }));
247
236
  const hasItems = () => menuItems(node).length > 0;
248
237
  return _$ssr(_tmpl$3, _$ssrAttribute("tabindex", renamingPath() === node.entry.path ? -1 : focusedPath() === node.entry.path ? 0 : -1, false) + _$ssrAttribute("aria-label", _$escape(currentNode().entry.displayName ?? currentNode().name, true), false) + _$ssrAttribute("aria-level", _$escape(currentNode().depth, true) + 1, false) + _$ssrAttribute("aria-selected", _$escape(isSelected(), true), false) + _$ssrAttribute("aria-expanded", currentNode().isFolder ? _$escape(expanded().has(currentNode().entry.path), true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-haspopup", hasItems() ? "menu" : _$escape(undefined, true), false) + _$ssrAttribute("data-context-open", contextMenuOpen() && contextPath() === node.entry.path ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
249
238
  get when() {
250
239
  return renamingPath() === node.entry.path;
251
240
  },
252
241
  get fallback() {
253
- return _$ssr(_tmpl$7, _$ssrAttribute("data-state", isSelected() ? "selected" : isDropTarget() ? "drop-target" : "idle", false), _$ssrStyleProperty("padding-left:", `${6 + _$escape(currentNode().depth, true) * 14}px`), _$ssrAttribute("title", _$escape(currentNode().entry.path, true), false) + _$ssrAttribute("draggable", _$escape(Boolean(props.actions?.move), true), false), `ti ${_$escape(icon(), true)} k2b-content-file-tree__icon`, _$escape(currentNode().entry.displayName ?? currentNode().name), _$escape(_$createComponent(Show, {
242
+ return _$ssr(_tmpl$7, _$ssrAttribute("data-state", isSelected() ? "selected" : isDropTarget() ? "drop-target" : "idle", false), _$ssrStyleProperty("padding-left:", `${6 + _$escape(currentNode().depth, true) * 14}px`), _$ssrAttribute("title", _$escape(currentNode().entry.path, true), false) + _$ssrAttribute("draggable", _$escape(Boolean(props.actions?.move), true), false), _$escape(_$createComponent(FileTypeIcon, {
243
+ size: "sm",
244
+ "class": "k2b-content-file-tree__icon",
245
+ get name() {
246
+ return currentNode().name;
247
+ },
248
+ get folder() {
249
+ return currentNode().isFolder;
250
+ },
251
+ get open() {
252
+ return _$memo(() => !!currentNode().isFolder)() && expanded().has(currentNode().entry.path);
253
+ },
254
+ get icon() {
255
+ return _$memo(() => !!currentNode().isFolder)() ? undefined : currentNode().entry.icon;
256
+ },
257
+ get mediaType() {
258
+ return currentNode().entry.mediaType ?? "text/plain";
259
+ }
260
+ })), _$escape(currentNode().entry.displayName ?? currentNode().name), _$escape(_$createComponent(Show, {
254
261
  get when() {
255
262
  return currentNode().entry.badge;
256
263
  },
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["content/FileTree.tsx"],"sourcesContent":["/**\n * FileTree — path-first tree over a flat entry list (folders derived from\n * paths, explicit folder entries allowed for empty dirs). Capabilities are\n * enabled by the presence of action callbacks; without them the tree is a\n * pure read-only browser. Context menus render through the platform\n * ContextMenu. Minimal look: text rows, bevel on selection, no hover motion.\n */\nimport { fileIcons } from \"@k2b/stdlib\";\nimport { createEffect, createMemo, createSignal, For, Show } from \"solid-js\";\nimport ContextMenu from \"../actions/ContextMenu\";\nimport Dropdown, { type DropdownItem } from \"../actions/Dropdown\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useFileBrowserMessages } from \"./file-browser-messages\";\nimport { allFolderPaths, buildTree, type FileTreeEntry, flattenVisible, parentOf, type TreeNode } from \"./file-tree\";\n\nexport type { FileTreeEntry } from \"./file-tree\";\n\n/**\n * `fileIcons` (and app-supplied entry icons) may carry Tailwind colour classes.\n * @k2b/ui ships no Tailwind utilities, so only the `ti-*` glyph is kept — the\n * row owns the icon colour.\n */\nconst glyphOnly = (icon: string): string =>\n icon\n .split(/\\s+/)\n .filter((token) => token.startsWith(\"ti-\"))\n .join(\" \");\n\n/** Presence of a callback enables the matching UI affordance. */\nexport type FileTreeActions = {\n rename?: (path: string, nextName: string) => void | Promise<void>;\n remove?: (path: string) => void | Promise<void>;\n createFile?: (dirPath: string) => void | Promise<void>;\n createFolder?: (dirPath: string) => void | Promise<void>;\n /** Enables drag & drop of files and folders onto folders (and the tree root). */\n move?: (path: string, targetDir: string) => void | Promise<void>;\n /** Download menu entry — folders arrive as \"Download as ZIP\". */\n download?: (path: string, isFolder: boolean) => void | Promise<void>;\n};\n\nexport type FileTreeProps = {\n entries: FileTreeEntry[];\n selectedPath?: string | null;\n onSelect?: (entry: FileTreeEntry) => void;\n /** Controlled expansion; omit for internal state (folders start expanded). */\n expandedPaths?: Set<string>;\n onExpandedChange?: (expanded: Set<string>) => void;\n /** Extra context-menu items per entry, merged above the built-in actions. */\n contextMenu?: (entry: FileTreeEntry) => DropdownItem[];\n actions?: FileTreeActions;\n /** Accessible name for the tree. */\n label?: string;\n class?: string;\n};\n\nexport default function FileTree(props: FileTreeProps) {\n const messages = useUiMessages();\n const fileBrowserMessages = useFileBrowserMessages();\n let previousTree: TreeNode[] = [];\n const tree = createMemo(() => (previousTree = buildTree(props.entries, previousTree)));\n\n const [internalExpanded, setInternalExpanded] = createSignal<Set<string>>(new Set(allFolderPaths(tree())), { equals: false });\n // Newly appearing folders start expanded in uncontrolled mode.\n createEffect((previous: Set<string>) => {\n const current = new Set(allFolderPaths(tree()));\n const added = [...current].filter((path) => !previous.has(path));\n if (added.length > 0 && !props.expandedPaths) setInternalExpanded((expanded) => new Set([...expanded, ...added]));\n return current;\n }, new Set<string>());\n\n const expanded = () => props.expandedPaths ?? internalExpanded();\n const setExpanded = (next: Set<string>) => {\n if (props.onExpandedChange) props.onExpandedChange(next);\n if (!props.expandedPaths) setInternalExpanded(next);\n };\n const toggleFolder = (path: string) => {\n const next = new Set(expanded());\n if (next.has(path)) next.delete(path);\n else next.add(path);\n setExpanded(next);\n };\n\n const visible = createMemo(() => flattenVisible(tree(), expanded()));\n const [renamingPath, setRenamingPath] = createSignal<string | null>(null);\n const [renameDraft, setRenameDraft] = createSignal(\"\");\n const [focusedPath, setFocusedPath] = createSignal(props.selectedPath ?? \"\");\n const [pendingFocusPath, setPendingFocusPath] = createSignal<string | null>(null);\n const [contextPath, setContextPath] = createSignal<string | null>(props.selectedPath ?? null);\n const [contextMenuOpen, setContextMenuOpen] = createSignal(false);\n const rowRefs = new Map<string, HTMLLIElement>();\n /** Folder currently hovered by a drag (\"/\" = tree root). */\n const [dropTarget, setDropTarget] = createSignal<string | null>(null);\n\n const focusRow = (path: string, restoreDomFocus = true) => {\n setFocusedPath(path);\n if (!restoreDomFocus) return;\n const row = rowRefs.get(path);\n if (row?.isConnected) row.focus();\n else queueMicrotask(() => rowRefs.get(path)?.focus());\n };\n\n createEffect(() => {\n const rows = visible();\n const paths = new Set(rows.map((node) => node.entry.path));\n for (const path of rowRefs.keys()) if (!paths.has(path)) rowRefs.delete(path);\n const pending = pendingFocusPath();\n if (pending && rows.some((node) => node.entry.path === pending)) {\n setPendingFocusPath(null);\n focusRow(pending);\n return;\n }\n if (rows.some((node) => node.entry.path === focusedPath())) return;\n const selected = rows.find((node) => node.entry.path === props.selectedPath);\n setFocusedPath(selected?.entry.path ?? rows[0]?.entry.path ?? \"\");\n });\n\n const DRAG_MIME = \"application/x-filetree-path\";\n const canDrop = (event: DragEvent) => props.actions?.move && event.dataTransfer?.types.includes(DRAG_MIME);\n const handleDrop = (event: DragEvent, targetDir: string) => {\n event.preventDefault();\n event.stopPropagation();\n setDropTarget(null);\n const path = event.dataTransfer?.getData(DRAG_MIME);\n if (!path || parentOf(path) === targetDir || path === targetDir || targetDir.startsWith(`${path}/`)) return;\n void props.actions?.move?.(path, targetDir);\n };\n\n const select = (node: TreeNode) => {\n if (node.isFolder) toggleFolder(node.entry.path);\n else props.onSelect?.(node.entry);\n };\n\n const commitRename = async (node: TreeNode, value: string) => {\n if (renamingPath() !== node.entry.path) return;\n setRenamingPath(null);\n const nextName = value.trim();\n focusRow(node.entry.path);\n if (!nextName || nextName === node.name || nextName.includes(\"/\")) return;\n const parent = parentOf(node.entry.path);\n setPendingFocusPath(`${parent === \"/\" ? \"\" : parent}/${nextName}`);\n await props.actions?.rename?.(node.entry.path, nextName);\n };\n\n const cancelRename = (node: TreeNode) => {\n setRenamingPath(null);\n focusRow(node.entry.path);\n };\n\n const beginRename = (node: TreeNode) => {\n setRenameDraft(node.name);\n setRenamingPath(node.entry.path);\n };\n\n const menuItems = (node: TreeNode): DropdownItem[] => {\n tree();\n const items: DropdownItem[] = [...(props.contextMenu?.(node.entry) ?? [])];\n if (node.isFolder && props.actions?.createFile) {\n items.push({\n icon: \"ti ti-file-plus\",\n label: fileBrowserMessages().newFile,\n action: () => void props.actions?.createFile?.(node.entry.path),\n });\n }\n if (node.isFolder && props.actions?.createFolder) {\n items.push({\n icon: \"ti ti-folder-plus\",\n label: fileBrowserMessages().newFolder,\n action: () => void props.actions?.createFolder?.(node.entry.path),\n });\n }\n if (props.actions?.download) {\n items.push({\n icon: node.isFolder ? \"ti ti-file-zip\" : \"ti ti-download\",\n label: node.isFolder ? fileBrowserMessages().downloadAsZip : messages().download,\n action: () => void props.actions?.download?.(node.entry.path, node.isFolder),\n });\n }\n if (!node.isFolder && props.actions?.rename) {\n items.push({ icon: \"ti ti-cursor-text\", label: fileBrowserMessages().rename, action: () => beginRename(node) });\n }\n if (props.actions?.remove) {\n items.push({\n icon: \"ti ti-trash\",\n label: messages().delete,\n variant: \"danger\",\n action: () => void props.actions?.remove?.(node.entry.path),\n });\n }\n return items;\n };\n\n const contextNode = createMemo(() => visible().find((node) => node.entry.path === contextPath()));\n const contextItems = createMemo(() => {\n const node = contextNode();\n return node ? menuItems(node) : [];\n });\n\n const onKeyDown = (event: KeyboardEvent, node: TreeNode) => {\n if (renamingPath()) return;\n const target = event.target;\n if (target instanceof Element && target !== rowRefs.get(node.entry.path)) return;\n const rows = visible();\n const index = rows.findIndex((row) => row.entry.path === node.entry.path);\n const focus = (next: TreeNode | undefined) => {\n if (!next) return;\n focusRow(next.entry.path);\n };\n if (event.key === \"ContextMenu\" || (event.shiftKey && event.key === \"F10\")) {\n setContextPath(node.entry.path);\n return;\n }\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n focus(rows[Math.min(index + 1, rows.length - 1)] ?? rows[0]);\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n focus(rows[Math.max(index - 1, 0)] ?? rows[0]);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focus(rows[event.key === \"Home\" ? 0 : rows.length - 1]);\n } else if (event.key === \"ArrowRight\" && node.isFolder) {\n event.preventDefault();\n if (!expanded().has(node.entry.path)) toggleFolder(node.entry.path);\n else focus(rows[index + 1]?.depth === node.depth + 1 ? rows[index + 1] : undefined);\n } else if (event.key === \"ArrowLeft\" && node.isFolder && expanded().has(node.entry.path)) {\n event.preventDefault();\n toggleFolder(node.entry.path);\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n const parent = parentOf(node.entry.path);\n focus(rows.find((row) => row.entry.path === parent));\n } else if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n select(node);\n } else if (event.key === \"F2\" && !node.isFolder && props.actions?.rename) {\n event.preventDefault();\n beginRename(node);\n }\n };\n\n return (\n <ContextMenu\n class=\"k2b-content-file-tree__context-host\"\n tabIndex={-1}\n label={contextNode() ? fileBrowserMessages().actionsFor({ name: contextNode()!.name }) : fileBrowserMessages().fileActions}\n items={contextItems()}\n disabled={contextItems().length === 0}\n onOpen={() => setContextMenuOpen(true)}\n onClose={() => {\n setContextMenuOpen(false);\n const path = contextPath();\n if (path) focusRow(path);\n }}\n >\n <ul\n class={`k2b-content-file-tree ${props.class ?? \"\"}`}\n data-drop-root={dropTarget() === \"/\" ? \"true\" : undefined}\n role=\"tree\"\n aria-label={props.label ?? fileBrowserMessages().files}\n onDragOver={(event) => {\n if (!canDrop(event)) return;\n event.preventDefault();\n if (dropTarget() === null) setDropTarget(\"/\");\n }}\n onDragLeave={(event) => {\n if (event.currentTarget === event.target) setDropTarget(null);\n }}\n onDrop={(event) => handleDrop(event, \"/\")}\n >\n <For each={visible()}>\n {(node) => {\n const currentNode = () => {\n tree();\n return node;\n };\n const isSelected = () => props.selectedPath === currentNode().entry.path;\n const isDropTarget = () => currentNode().isFolder && dropTarget() === currentNode().entry.path;\n const icon = () =>\n currentNode().isFolder\n ? expanded().has(currentNode().entry.path)\n ? \"ti-folder-open\"\n : \"ti-folder\"\n : glyphOnly(\n currentNode().entry.icon ??\n fileIcons.getFileIcon({\n name: currentNode().name,\n type: \"file\",\n mimeType: currentNode().entry.mediaType ?? \"text/plain\",\n }),\n );\n const hasItems = () => menuItems(node).length > 0;\n return (\n <li\n ref={(element) => {\n rowRefs.set(node.entry.path, element);\n }}\n class=\"k2b-content-file-tree__item\"\n role=\"treeitem\"\n tabIndex={renamingPath() === node.entry.path ? -1 : focusedPath() === node.entry.path ? 0 : -1}\n aria-label={currentNode().entry.displayName ?? currentNode().name}\n aria-level={currentNode().depth + 1}\n aria-selected={isSelected()}\n aria-expanded={currentNode().isFolder ? expanded().has(currentNode().entry.path) : undefined}\n aria-haspopup={hasItems() ? \"menu\" : undefined}\n data-context-open={contextMenuOpen() && contextPath() === node.entry.path ? \"true\" : undefined}\n onFocus={() => {\n setFocusedPath(node.entry.path);\n setContextPath(node.entry.path);\n }}\n onKeyDown={(event) => onKeyDown(event, node)}\n onContextMenu={() => setContextPath(node.entry.path)}\n >\n <Show\n when={renamingPath() === node.entry.path}\n fallback={\n <div\n data-state={isSelected() ? \"selected\" : isDropTarget() ? \"drop-target\" : \"idle\"}\n class=\"k2b-content-file-tree__row\"\n >\n <button\n type=\"button\"\n tabIndex={-1}\n class=\"k2b-content-file-tree__select\"\n style={{ \"padding-left\": `${6 + currentNode().depth * 14}px` }}\n title={currentNode().entry.path}\n draggable={Boolean(props.actions?.move)}\n onDragStart={(event) => event.dataTransfer?.setData(DRAG_MIME, node.entry.path)}\n onDragOver={(event) => {\n if (!node.isFolder || !canDrop(event)) return;\n event.preventDefault();\n event.stopPropagation();\n setDropTarget(node.entry.path);\n }}\n onDragLeave={() => {\n if (isDropTarget()) setDropTarget(null);\n }}\n onDrop={(event) => node.isFolder && handleDrop(event, node.entry.path)}\n onClick={(event) => {\n event.currentTarget.closest<HTMLElement>('[role=\"treeitem\"]')?.focus();\n select(node);\n }}\n >\n <i class={`ti ${icon()} k2b-content-file-tree__icon`} aria-hidden=\"true\" />\n <span class=\"k2b-content-file-tree__name\">{currentNode().entry.displayName ?? currentNode().name}</span>\n <Show when={currentNode().entry.badge}>\n <span class=\"k2b-content-file-tree__badge\">{currentNode().entry.badge}</span>\n </Show>\n </button>\n <Show when={hasItems()}>\n <Dropdown.Root position=\"bottom-left\" items={menuItems(node)} label={`Actions for ${currentNode().name}`}>\n <Dropdown.Trigger\n appearance=\"plain\"\n tabIndex={-1}\n class=\"k2b-content-file-tree__actions\"\n label={`Actions for ${currentNode().name}`}\n tooltip={messages().actions}\n >\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n <span class=\"k2b-sr-only\">Actions for {currentNode().name}</span>\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n }\n >\n <input\n class=\"k2b-content-file-tree__rename\"\n style={{\n \"margin-left\": `${6 + currentNode().depth * 14}px`,\n width: `calc(100% - ${6 + currentNode().depth * 14}px)`,\n }}\n value={renameDraft()}\n ref={(element) =>\n requestAnimationFrame(() => {\n element.focus();\n element.select();\n })\n }\n onInput={(event) => setRenameDraft(event.currentTarget.value)}\n onKeyDown={(event) => {\n event.stopPropagation();\n if (event.key === \"Enter\") void commitRename(node, event.currentTarget.value);\n if (event.key === \"Escape\") cancelRename(node);\n }}\n onBlur={(event) => void commitRename(node, event.currentTarget.value)}\n />\n </Show>\n </li>\n );\n }}\n </For>\n </ul>\n </ContextMenu>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,QAAQ,aAAa;AACvC,SAAS,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,QAAQ,UAAU;AAC5E,OAAO,WAAW,MAAM,wBAAwB;AAChD,OAAO,QAAQ,MAA6B,qBAAqB;AACjE,SAAS,aAAa,QAAQ,kBAAkB;AAChD,SAAS,sBAAsB,QAAQ,yBAAyB;AAChE,SAAS,cAAc,EAAE,SAAS,EAAsB,cAAc,EAAE,QAAQ,QAAuB,aAAa;AAIpH;AACA;AACA;AACA;AACA;AACA,MAAM,SAAS,GAAI,IAAY,IAC7B,IAAI,CACD,KAAK,CAAC,KAAK,CAAC,CACZ,MAAM,CAAE,KAAK,IAAK,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAC1C,IAAI,CAAC,GAAG,CAAC;;AAEd;;AA2BA,eAAe,SAAS,QAAQ,CAAC,KAAoB,EAAE;EACrD,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,CAAC;EACpD,IAAI,YAAwB,GAAG,EAAE;EACjC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAO,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,YAAY,CAAE,CAAC;EAEtF,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,YAAY,CAAc,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;IAAE,MAAM,EAAE;EAAM,CAAC,CAAC;EAC7H;EACA,YAAY,CAAE,QAAqB,IAAK;IACtC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAE,IAAI,IAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,mBAAmB,CAAE,QAAQ,IAAK,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IACjH,OAAO,OAAO;EAChB,CAAC,EAAE,IAAI,GAAG,CAAS,CAAC,CAAC;EAErB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,IAAI,gBAAgB,CAAC,CAAC;EAChE,MAAM,WAAW,GAAI,IAAiB,IAAK;IACzC,IAAI,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC;IACxD,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,mBAAmB,CAAC,IAAI,CAAC;EACrD,CAAC;EACD,MAAM,YAAY,GAAI,IAAY,IAAK;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KACjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACnB,WAAW,CAAC,IAAI,CAAC;EACnB,CAAC;EAED,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;EACpE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,YAAY,CAAgB,IAAI,CAAC;EACzE,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC;EACtD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;EAC5E,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,YAAY,CAAgB,IAAI,CAAC;EACjF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,YAAY,CAAgB,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC;EAC7F,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC;EACjE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAwB,CAAC;EAChD;EACA,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,YAAY,CAAgB,IAAI,CAAC;EAErE,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,eAAe,GAAG,IAAI,KAAK;IACzD,cAAc,CAAC,IAAI,CAAC;IACpB,IAAI,CAAC,eAAe,EAAE;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B,IAAI,GAAG,EAAE,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAC7B,cAAc,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;EACvD,CAAC;EAED,YAAY,CAAC,MAAM;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAE,IAAI,IAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;IAC7E,MAAM,OAAO,GAAG,gBAAgB,CAAC,CAAC;IAClC,IAAI,OAAO,IAAI,IAAI,CAAC,IAAI,CAAE,IAAI,IAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE;MAC/D,mBAAmB,CAAC,IAAI,CAAC;MACzB,QAAQ,CAAC,OAAO,CAAC;MACjB;IACF;IACA,IAAI,IAAI,CAAC,IAAI,CAAE,IAAI,IAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAE,IAAI,IAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,YAAY,CAAC;IAC5E,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;EACnE,CAAC,CAAC;EAEF,MAAM,SAAS,GAAG,6BAA6B;EAC/C,MAAM,OAAO,GAAI,KAAgB,IAAK,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;EAC1G,MAAM,UAAU,GAAG,CAAC,KAAgB,EAAE,SAAiB,KAAK;IAC1D,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,KAAK,CAAC,eAAe,CAAC,CAAC;IACvB,aAAa,CAAC,IAAI,CAAC;IACnB,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC;IACnD,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE;IACrG,KAAK,KAAK,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,EAAE,SAAS,CAAC;EAC7C,CAAC;EAED,MAAM,MAAM,GAAI,IAAc,IAAK;IACjC,IAAI,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAC5C,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;EACnC,CAAC;EAED,MAAM,YAAY,GAAG,OAAO,IAAc,EAAE,KAAa,KAAK;IAC5D,IAAI,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;IACxC,eAAe,CAAC,IAAI,CAAC;IACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;IACnE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACxC,mBAAmB,CAAC,GAAG,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;IAClE,MAAM,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC;EAC1D,CAAC;EAED,MAAM,YAAY,GAAI,IAAc,IAAK;IACvC,eAAe,CAAC,IAAI,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;EAC3B,CAAC;EAED,MAAM,WAAW,GAAI,IAAc,IAAK;IACtC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;IACzB,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;EAClC,CAAC;EAED,MAAM,SAAS,GAAI,IAAc,IAAqB;IACpD,IAAI,CAAC,CAAC;IACN,MAAM,KAAqB,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE;MAC9C,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO;QACpC,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI;MAChE,CAAC,CAAC;IACJ;IACA,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE;MAChD,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,SAAS;QACtC,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI;MAClE,CAAC,CAAC;IACJ;IACA,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;MAC3B,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,gBAAgB,GAAG,gBAAgB;QACzD,KAAK,EAAE,IAAI,CAAC,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ;QAChF,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ;MAC7E,CAAC,CAAC;IACJ;IACA,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE;MAC3C,KAAK,CAAC,IAAI,CAAC;QAAE,IAAI,EAAE,mBAAmB;QAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,MAAM;QAAE,MAAM,EAAE,MAAM,WAAW,CAAC,IAAI;MAAE,CAAC,CAAC;IACjH;IACA,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE;MACzB,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM;QACxB,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI;MAC5D,CAAC,CAAC;IACJ;IACA,OAAO,KAAK;EACd,CAAC;EAED,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAE,IAAI,IAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;EACjG,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM;IACpC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC;IAC1B,OAAO,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE;EACpC,CAAC,CAAC;EAEF,MAAM,SAAS,GAAG,CAAC,KAAoB,EAAE,IAAc,KAAK;IAC1D,IAAI,YAAY,CAAC,CAAC,EAAE;IACpB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;IAC3B,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;IAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzE,MAAM,KAAK,GAAI,IAA0B,IAAK;MAC5C,IAAI,CAAC,IAAI,EAAE;MACX,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3B,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,KAAK,aAAa,IAAK,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,KAAM,EAAE;MAC1E,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;MAC/B;IACF;IACA,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE;MAC7B,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE;MAClC,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE;MACtD,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,YAAY,IAAI,IAAI,CAAC,QAAQ,EAAE;MACtD,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAC/D,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IACrF,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;MACxF,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC/B,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE;MACpC,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;MACxC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACtD,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE;MACrD,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,MAAM,CAAC,IAAI,CAAC;IACd,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE;MACxE,KAAK,CAAC,cAAc,CAAC,CAAC;MACtB,WAAW,CAAC,IAAI,CAAC;IACnB;EACF,CAAC;EAED,yBACG,WAAW;IAAA;IAEV,QAAQ,EAAE,CAAC,CAAC;IAAA,IACZ,KAAK;MAAA,OAAE,0BAAW,CAAC,CAAC,MAAG,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAE;MAAK,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,WAAW;IAAA;IAAA,IAC1H,KAAK;MAAA,OAAE,YAAY,CAAC,CAAC;IAAA;IAAA,IACrB,QAAQ;MAAA,OAAE,YAAY,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;IAAA;IACrC,MAAM,EAAE,MAAM,kBAAkB,CAAC,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM;MACb,kBAAkB,CAAC,KAAK,CAAC;MACzB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC;MAC1B,IAAI,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAC1B,CAAC;IAAA;MAAA,qBAGQ,kCAAyB,KAAK,CAAC,KAAK,IAAI,EAAE,SAAE,mCACnC,UAAU,CAAC,CAAC,KAAK,GAAG,GAAG,MAAM,YAAG,SAAS,uDAE7C,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC,KAAK,4CAWrD,GAAG;QAAA,IAAC,IAAI;UAAA,OAAE,OAAO,CAAC,CAAC;QAAA;QAAA,UAChB,IAAI,IAAK;UACT,MAAM,WAAW,GAAG,MAAM;YACxB,IAAI,CAAC,CAAC;YACN,OAAO,IAAI;UACb,CAAC;UACD,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;UACxE,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;UAC9F,MAAM,IAAI,GAAG,MACX,WAAW,CAAC,CAAC,CAAC,QAAQ,GAClB,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GACtC,gBAAgB,GAChB,WAAW,GACb,SAAS,CACP,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IACtB,SAAS,CAAC,WAAW,CAAC;YACpB,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI;YACxB,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI;UAC7C,CAAC,CACL,CAAC;UACP,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;UACjD,iDAOc,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,iDAClF,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,+CACrD,oBAAW,CAAC,CAAC,CAAC,KAAK,UAAG,CAAC,oDACpB,UAAU,CAAC,CAAC,kDACZ,WAAW,CAAC,CAAC,CAAC,QAAQ,YAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAG,SAAS,kDAC7E,QAAQ,CAAC,CAAC,GAAG,MAAM,YAAG,SAAS,sDAC3B,eAAe,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,YAAG,SAAS,4CAQ7F,IAAI;YAAA,IACH,IAAI;cAAA,OAAE,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI;YAAA;YAAA,IACxC,QAAQ;cAAA,mDAEQ,UAAU,CAAC,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC,CAAC,GAAG,aAAa,GAAG,MAAM,8CAOpD,GAAG,CAAC,GAAG,oBAAW,CAAC,CAAC,CAAC,KAAK,UAAG,EAAE,IAAI,oCACrD,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,uDACpB,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,iBAiB7B,eAAM,IAAI,CAAC,CAAC,qCAA8B,WACT,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,8BAC/F,IAAI;gBAAA,IAAC,IAAI;kBAAA,OAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;gBAAA;gBAAA;kBAAA,+BACS,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;gBAAA;cAAA,gCAGxE,IAAI;gBAAA,IAAC,IAAI;kBAAA,OAAE,QAAQ,CAAC,CAAC;gBAAA;gBAAA;kBAAA,yBACnB,QAAQ,CAAC,IAAI;oBAAC,QAAQ;oBAAA,IAAe,KAAK;sBAAA,OAAE,SAAS,CAAC,IAAI,CAAC;oBAAA;oBAAA,IAAE,KAAK;sBAAA,OAAE,eAAe,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE;oBAAA;oBAAA;sBAAA,yBACrG,QAAQ,CAAC,OAAO;wBACf,UAAU;wBACV,QAAQ,EAAE,CAAC,CAAC;wBAAA;wBAAA,IAEZ,KAAK;0BAAA,OAAE,eAAe,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE;wBAAA;wBAAA,IAC1C,OAAO;0BAAA,OAAE,QAAQ,CAAC,CAAC,CAAC,OAAO;wBAAA;wBAAA;0BAAA,gDAGY,WAAW,CAAC,CAAC,CAAC,IAAI;wBAAA;sBAAA;oBAAA;kBAAA;gBAAA;cAAA;YAAA;YAAA;cAAA,yDAUhD,GAAG,CAAC,GAAG,oBAAW,CAAC,CAAC,CAAC,KAAK,UAAG,EAAE,IAAI,kCAC3C,eAAe,CAAC,GAAG,oBAAW,CAAC,CAAC,CAAC,KAAK,UAAG,EAAE,KAAK,oCAElD,WAAW,CAAC,CAAC;YAAA;UAAA;QAkB9B;MAAC;IAAA;EAAA;AAKX","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["content/FileTree.tsx"],"sourcesContent":["/**\n * FileTree — path-first tree over a flat entry list (folders derived from\n * paths, explicit folder entries allowed for empty dirs). Capabilities are\n * enabled by the presence of action callbacks; without them the tree is a\n * pure read-only browser. Context menus render through the platform\n * ContextMenu. Minimal look: text rows, bevel on selection, no hover motion.\n */\nimport { createEffect, createMemo, createSignal, For, Show } from \"solid-js\";\nimport ContextMenu from \"../actions/ContextMenu\";\nimport Dropdown, { type DropdownItem } from \"../actions/Dropdown\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { FileTypeIcon } from \"./FileTypeIcon\";\nimport { useFileBrowserMessages } from \"./file-browser-messages\";\nimport { allFolderPaths, buildTree, type FileTreeEntry, flattenVisible, parentOf, type TreeNode } from \"./file-tree\";\n\nexport type { FileTreeEntry } from \"./file-tree\";\n\n/** Presence of a callback enables the matching UI affordance. */\nexport type FileTreeActions = {\n rename?: (path: string, nextName: string) => void | Promise<void>;\n remove?: (path: string) => void | Promise<void>;\n createFile?: (dirPath: string) => void | Promise<void>;\n createFolder?: (dirPath: string) => void | Promise<void>;\n /** Enables drag & drop of files and folders onto folders (and the tree root). */\n move?: (path: string, targetDir: string) => void | Promise<void>;\n /** Download menu entry — folders arrive as \"Download as ZIP\". */\n download?: (path: string, isFolder: boolean) => void | Promise<void>;\n};\n\nexport type FileTreeProps = {\n entries: FileTreeEntry[];\n selectedPath?: string | null;\n onSelect?: (entry: FileTreeEntry) => void;\n /** Controlled expansion; omit for internal state (folders start expanded). */\n expandedPaths?: Set<string>;\n onExpandedChange?: (expanded: Set<string>) => void;\n /** Extra context-menu items per entry, merged above the built-in actions. */\n contextMenu?: (entry: FileTreeEntry) => DropdownItem[];\n actions?: FileTreeActions;\n /** Accessible name for the tree. */\n label?: string;\n class?: string;\n};\n\nexport default function FileTree(props: FileTreeProps) {\n const messages = useUiMessages();\n const fileBrowserMessages = useFileBrowserMessages();\n let previousTree: TreeNode[] = [];\n const tree = createMemo(() => (previousTree = buildTree(props.entries, previousTree)));\n\n const [internalExpanded, setInternalExpanded] = createSignal<Set<string>>(new Set(allFolderPaths(tree())), { equals: false });\n // Newly appearing folders start expanded in uncontrolled mode.\n createEffect((previous: Set<string>) => {\n const current = new Set(allFolderPaths(tree()));\n const added = [...current].filter((path) => !previous.has(path));\n if (added.length > 0 && !props.expandedPaths) setInternalExpanded((expanded) => new Set([...expanded, ...added]));\n return current;\n }, new Set<string>());\n\n const expanded = () => props.expandedPaths ?? internalExpanded();\n const setExpanded = (next: Set<string>) => {\n if (props.onExpandedChange) props.onExpandedChange(next);\n if (!props.expandedPaths) setInternalExpanded(next);\n };\n const toggleFolder = (path: string) => {\n const next = new Set(expanded());\n if (next.has(path)) next.delete(path);\n else next.add(path);\n setExpanded(next);\n };\n\n const visible = createMemo(() => flattenVisible(tree(), expanded()));\n const [renamingPath, setRenamingPath] = createSignal<string | null>(null);\n const [renameDraft, setRenameDraft] = createSignal(\"\");\n const [focusedPath, setFocusedPath] = createSignal(props.selectedPath ?? \"\");\n const [pendingFocusPath, setPendingFocusPath] = createSignal<string | null>(null);\n const [contextPath, setContextPath] = createSignal<string | null>(props.selectedPath ?? null);\n const [contextMenuOpen, setContextMenuOpen] = createSignal(false);\n const rowRefs = new Map<string, HTMLLIElement>();\n /** Folder currently hovered by a drag (\"/\" = tree root). */\n const [dropTarget, setDropTarget] = createSignal<string | null>(null);\n\n const focusRow = (path: string, restoreDomFocus = true) => {\n setFocusedPath(path);\n if (!restoreDomFocus) return;\n const row = rowRefs.get(path);\n if (row?.isConnected) row.focus();\n else queueMicrotask(() => rowRefs.get(path)?.focus());\n };\n\n createEffect(() => {\n const rows = visible();\n const paths = new Set(rows.map((node) => node.entry.path));\n for (const path of rowRefs.keys()) if (!paths.has(path)) rowRefs.delete(path);\n const pending = pendingFocusPath();\n if (pending && rows.some((node) => node.entry.path === pending)) {\n setPendingFocusPath(null);\n focusRow(pending);\n return;\n }\n if (rows.some((node) => node.entry.path === focusedPath())) return;\n const selected = rows.find((node) => node.entry.path === props.selectedPath);\n setFocusedPath(selected?.entry.path ?? rows[0]?.entry.path ?? \"\");\n });\n\n const DRAG_MIME = \"application/x-filetree-path\";\n const canDrop = (event: DragEvent) => props.actions?.move && event.dataTransfer?.types.includes(DRAG_MIME);\n const handleDrop = (event: DragEvent, targetDir: string) => {\n event.preventDefault();\n event.stopPropagation();\n setDropTarget(null);\n const path = event.dataTransfer?.getData(DRAG_MIME);\n if (!path || parentOf(path) === targetDir || path === targetDir || targetDir.startsWith(`${path}/`)) return;\n void props.actions?.move?.(path, targetDir);\n };\n\n const select = (node: TreeNode) => {\n if (node.isFolder) toggleFolder(node.entry.path);\n else props.onSelect?.(node.entry);\n };\n\n const commitRename = async (node: TreeNode, value: string) => {\n if (renamingPath() !== node.entry.path) return;\n setRenamingPath(null);\n const nextName = value.trim();\n focusRow(node.entry.path);\n if (!nextName || nextName === node.name || nextName.includes(\"/\")) return;\n const parent = parentOf(node.entry.path);\n setPendingFocusPath(`${parent === \"/\" ? \"\" : parent}/${nextName}`);\n await props.actions?.rename?.(node.entry.path, nextName);\n };\n\n const cancelRename = (node: TreeNode) => {\n setRenamingPath(null);\n focusRow(node.entry.path);\n };\n\n const beginRename = (node: TreeNode) => {\n setRenameDraft(node.name);\n setRenamingPath(node.entry.path);\n };\n\n const menuItems = (node: TreeNode): DropdownItem[] => {\n tree();\n const items: DropdownItem[] = [...(props.contextMenu?.(node.entry) ?? [])];\n if (node.isFolder && props.actions?.createFile) {\n items.push({\n icon: \"ti ti-file-plus\",\n label: fileBrowserMessages().newFile,\n action: () => void props.actions?.createFile?.(node.entry.path),\n });\n }\n if (node.isFolder && props.actions?.createFolder) {\n items.push({\n icon: \"ti ti-folder-plus\",\n label: fileBrowserMessages().newFolder,\n action: () => void props.actions?.createFolder?.(node.entry.path),\n });\n }\n if (props.actions?.download) {\n items.push({\n icon: node.isFolder ? \"ti ti-file-zip\" : \"ti ti-download\",\n label: node.isFolder ? fileBrowserMessages().downloadAsZip : messages().download,\n action: () => void props.actions?.download?.(node.entry.path, node.isFolder),\n });\n }\n if (!node.isFolder && props.actions?.rename) {\n items.push({ icon: \"ti ti-cursor-text\", label: fileBrowserMessages().rename, action: () => beginRename(node) });\n }\n if (props.actions?.remove) {\n items.push({\n icon: \"ti ti-trash\",\n label: messages().delete,\n variant: \"danger\",\n action: () => void props.actions?.remove?.(node.entry.path),\n });\n }\n return items;\n };\n\n const contextNode = createMemo(() => visible().find((node) => node.entry.path === contextPath()));\n const contextItems = createMemo(() => {\n const node = contextNode();\n return node ? menuItems(node) : [];\n });\n\n const onKeyDown = (event: KeyboardEvent, node: TreeNode) => {\n if (renamingPath()) return;\n const target = event.target;\n if (target instanceof Element && target !== rowRefs.get(node.entry.path)) return;\n const rows = visible();\n const index = rows.findIndex((row) => row.entry.path === node.entry.path);\n const focus = (next: TreeNode | undefined) => {\n if (!next) return;\n focusRow(next.entry.path);\n };\n if (event.key === \"ContextMenu\" || (event.shiftKey && event.key === \"F10\")) {\n setContextPath(node.entry.path);\n return;\n }\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n focus(rows[Math.min(index + 1, rows.length - 1)] ?? rows[0]);\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n focus(rows[Math.max(index - 1, 0)] ?? rows[0]);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focus(rows[event.key === \"Home\" ? 0 : rows.length - 1]);\n } else if (event.key === \"ArrowRight\" && node.isFolder) {\n event.preventDefault();\n if (!expanded().has(node.entry.path)) toggleFolder(node.entry.path);\n else focus(rows[index + 1]?.depth === node.depth + 1 ? rows[index + 1] : undefined);\n } else if (event.key === \"ArrowLeft\" && node.isFolder && expanded().has(node.entry.path)) {\n event.preventDefault();\n toggleFolder(node.entry.path);\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n const parent = parentOf(node.entry.path);\n focus(rows.find((row) => row.entry.path === parent));\n } else if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n select(node);\n } else if (event.key === \"F2\" && !node.isFolder && props.actions?.rename) {\n event.preventDefault();\n beginRename(node);\n }\n };\n\n return (\n <ContextMenu\n class=\"k2b-content-file-tree__context-host\"\n tabIndex={-1}\n label={contextNode() ? fileBrowserMessages().actionsFor({ name: contextNode()!.name }) : fileBrowserMessages().fileActions}\n items={contextItems()}\n disabled={contextItems().length === 0}\n onOpen={() => setContextMenuOpen(true)}\n onClose={() => {\n setContextMenuOpen(false);\n const path = contextPath();\n if (path) focusRow(path);\n }}\n >\n <ul\n class={`k2b-content-file-tree ${props.class ?? \"\"}`}\n data-drop-root={dropTarget() === \"/\" ? \"true\" : undefined}\n role=\"tree\"\n aria-label={props.label ?? fileBrowserMessages().files}\n onDragOver={(event) => {\n if (!canDrop(event)) return;\n event.preventDefault();\n if (dropTarget() === null) setDropTarget(\"/\");\n }}\n onDragLeave={(event) => {\n if (event.currentTarget === event.target) setDropTarget(null);\n }}\n onDrop={(event) => handleDrop(event, \"/\")}\n >\n <For each={visible()}>\n {(node) => {\n const currentNode = () => {\n tree();\n return node;\n };\n const isSelected = () => props.selectedPath === currentNode().entry.path;\n const isDropTarget = () => currentNode().isFolder && dropTarget() === currentNode().entry.path;\n const hasItems = () => menuItems(node).length > 0;\n return (\n <li\n ref={(element) => {\n rowRefs.set(node.entry.path, element);\n }}\n class=\"k2b-content-file-tree__item\"\n role=\"treeitem\"\n tabIndex={renamingPath() === node.entry.path ? -1 : focusedPath() === node.entry.path ? 0 : -1}\n aria-label={currentNode().entry.displayName ?? currentNode().name}\n aria-level={currentNode().depth + 1}\n aria-selected={isSelected()}\n aria-expanded={currentNode().isFolder ? expanded().has(currentNode().entry.path) : undefined}\n aria-haspopup={hasItems() ? \"menu\" : undefined}\n data-context-open={contextMenuOpen() && contextPath() === node.entry.path ? \"true\" : undefined}\n onFocus={() => {\n setFocusedPath(node.entry.path);\n setContextPath(node.entry.path);\n }}\n onKeyDown={(event) => onKeyDown(event, node)}\n onContextMenu={() => setContextPath(node.entry.path)}\n >\n <Show\n when={renamingPath() === node.entry.path}\n fallback={\n <div\n data-state={isSelected() ? \"selected\" : isDropTarget() ? \"drop-target\" : \"idle\"}\n class=\"k2b-content-file-tree__row\"\n >\n <button\n type=\"button\"\n tabIndex={-1}\n class=\"k2b-content-file-tree__select\"\n style={{ \"padding-left\": `${6 + currentNode().depth * 14}px` }}\n title={currentNode().entry.path}\n draggable={Boolean(props.actions?.move)}\n onDragStart={(event) => event.dataTransfer?.setData(DRAG_MIME, node.entry.path)}\n onDragOver={(event) => {\n if (!node.isFolder || !canDrop(event)) return;\n event.preventDefault();\n event.stopPropagation();\n setDropTarget(node.entry.path);\n }}\n onDragLeave={() => {\n if (isDropTarget()) setDropTarget(null);\n }}\n onDrop={(event) => node.isFolder && handleDrop(event, node.entry.path)}\n onClick={(event) => {\n event.currentTarget.closest<HTMLElement>('[role=\"treeitem\"]')?.focus();\n select(node);\n }}\n >\n <FileTypeIcon\n size=\"sm\"\n class=\"k2b-content-file-tree__icon\"\n name={currentNode().name}\n folder={currentNode().isFolder}\n open={currentNode().isFolder && expanded().has(currentNode().entry.path)}\n icon={currentNode().isFolder ? undefined : currentNode().entry.icon}\n mediaType={currentNode().entry.mediaType ?? \"text/plain\"}\n />\n <span class=\"k2b-content-file-tree__name\">{currentNode().entry.displayName ?? currentNode().name}</span>\n <Show when={currentNode().entry.badge}>\n <span class=\"k2b-content-file-tree__badge\">{currentNode().entry.badge}</span>\n </Show>\n </button>\n <Show when={hasItems()}>\n <Dropdown.Root position=\"bottom-left\" items={menuItems(node)} label={`Actions for ${currentNode().name}`}>\n <Dropdown.Trigger\n appearance=\"plain\"\n tabIndex={-1}\n class=\"k2b-content-file-tree__actions\"\n label={`Actions for ${currentNode().name}`}\n tooltip={messages().actions}\n >\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n <span class=\"k2b-sr-only\">Actions for {currentNode().name}</span>\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n }\n >\n <input\n class=\"k2b-content-file-tree__rename\"\n style={{\n \"margin-left\": `${6 + currentNode().depth * 14}px`,\n width: `calc(100% - ${6 + currentNode().depth * 14}px)`,\n }}\n value={renameDraft()}\n ref={(element) =>\n requestAnimationFrame(() => {\n element.focus();\n element.select();\n })\n }\n onInput={(event) => setRenameDraft(event.currentTarget.value)}\n onKeyDown={(event) => {\n event.stopPropagation();\n if (event.key === \"Enter\") void commitRename(node, event.currentTarget.value);\n if (event.key === \"Escape\") cancelRename(node);\n }}\n onBlur={(event) => void commitRename(node, event.currentTarget.value)}\n />\n </Show>\n </li>\n );\n }}\n </For>\n </ul>\n </ContextMenu>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,50 @@
1
+ import { ssr as _$ssr } from "solid-js/web";
2
+ import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
3
+ import { escape as _$escape } from "solid-js/web";
4
+ var _tmpl$ = ["<span class=\"", "\"", " aria-hidden=\"true\"><i class=\"", "\"></i></span>"];
5
+ import { fileIcons } from "@k2b/stdlib";
6
+
7
+ /** The colour family a file's icon tile uses. `other` covers code, text, and unknown files. */
8
+
9
+ // Known extensions decide first: a generic media type such as `text/plain` or `text/csv` must not hide a sheet,
10
+ // a slide deck, a document, or an archive behind the neutral family.
11
+ const BY_EXTENSION = new Map([["sheet", ["xls", "xlsx", "ods", "csv"]], ["slides", ["ppt", "pptx", "odp"]], ["document", ["doc", "docx", "odt", "rtf"]], ["archive", ["zip", "tar", "gz", "tgz", "bz2", "xz", "7z", "rar"]]].flatMap(([type, extensions]) => extensions.map(extension => [extension, type])));
12
+
13
+ /** Resolve the colour family for a file or folder from its name and media type. */
14
+ export const fileTypeOf = file => {
15
+ if (file.folder) return "folder";
16
+ const known = BY_EXTENSION.get(file.name.split(".").pop()?.toLowerCase() ?? "");
17
+ if (known) return known;
18
+ const category = fileIcons.getFileCategory({
19
+ name: file.name,
20
+ type: "file",
21
+ mimeType: file.mediaType
22
+ });
23
+ return category === "pdf" || category === "image" || category === "video" || category === "audio" || category === "archive" ? category : "other";
24
+ };
25
+
26
+ /** `fileIcons` adds Tailwind colour utilities that @k2b/ui does not ship; only the `ti-*` glyph is kept. */
27
+ const glyph = props => {
28
+ // `fileIcons` looks names up in plain objects, so a name such as `constructor` returns an inherited member
29
+ // instead of a class string; such names fall back to the generic glyph.
30
+ const found = props.icon ?? fileIcons.getFileIcon({
31
+ name: props.name,
32
+ type: props.folder ? "directory" : "file",
33
+ mimeType: props.mediaType
34
+ });
35
+ const icon = (typeof found === "string" ? found : "").split(/\s+/).filter(token => token.startsWith("ti-")).join(" ") || (props.folder ? "ti-folder" : "ti-file");
36
+ return props.folder && props.open ? icon.replace(/\bti-folder$/, "ti-folder-open") : icon;
37
+ };
38
+
39
+ /**
40
+ * A file or folder glyph in a soft chip of its type colour. Folders take the app accent hook
41
+ * `--k2b-app-workspace-active`; code, text, and unknown files a neutral ink. The box size is fixed per `size`.
42
+ */
43
+ export function FileTypeIcon(props) {
44
+ return _$ssr(_tmpl$, `k2b-icon-tile k2b-file-type-icon ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-file-type", _$escape(fileTypeOf({
45
+ name: props.name,
46
+ mediaType: props.mediaType,
47
+ folder: props.folder
48
+ }), true), false) + _$ssrAttribute("data-size", _$escape(props.size ?? "md", true), false), `ti ${_$escape(glyph(props), true)}`);
49
+ }
50
+ //# sourceMappingURL=FileTypeIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["content/FileTypeIcon.tsx"],"sourcesContent":["import { fileIcons } from \"@k2b/stdlib\";\nimport type { JSX } from \"solid-js\";\n\n/** The colour family a file's icon tile uses. `other` covers code, text, and unknown files. */\nexport type FileType = \"folder\" | \"pdf\" | \"image\" | \"sheet\" | \"document\" | \"slides\" | \"video\" | \"audio\" | \"archive\" | \"other\";\n\nexport type FileTypeIconProps = {\n /** The file or folder name; its extension picks the glyph and the type colour. */\n name: string;\n mediaType?: string;\n folder?: boolean;\n /** Shows an open folder, for example the folder a list is showing. */\n open?: boolean;\n /** A Tabler icon class that replaces the glyph the name picks; the type colour still follows the name. */\n icon?: string;\n /** `sm` for tree rows, `md` for list rows, `lg` for grid previews. Defaults to `md`. */\n size?: \"sm\" | \"md\" | \"lg\";\n class?: string;\n};\n\n// Known extensions decide first: a generic media type such as `text/plain` or `text/csv` must not hide a sheet,\n// a slide deck, a document, or an archive behind the neutral family.\nconst BY_EXTENSION = new Map<string, FileType>(\n (\n [\n [\"sheet\", [\"xls\", \"xlsx\", \"ods\", \"csv\"]],\n [\"slides\", [\"ppt\", \"pptx\", \"odp\"]],\n [\"document\", [\"doc\", \"docx\", \"odt\", \"rtf\"]],\n [\"archive\", [\"zip\", \"tar\", \"gz\", \"tgz\", \"bz2\", \"xz\", \"7z\", \"rar\"]],\n ] as const\n ).flatMap(([type, extensions]) => extensions.map((extension) => [extension, type] as const)),\n);\n\n/** Resolve the colour family for a file or folder from its name and media type. */\nexport const fileTypeOf = (file: { name: string; mediaType?: string; folder?: boolean }): FileType => {\n if (file.folder) return \"folder\";\n const known = BY_EXTENSION.get(file.name.split(\".\").pop()?.toLowerCase() ?? \"\");\n if (known) return known;\n const category = fileIcons.getFileCategory({ name: file.name, type: \"file\", mimeType: file.mediaType });\n return category === \"pdf\" || category === \"image\" || category === \"video\" || category === \"audio\" || category === \"archive\"\n ? category\n : \"other\";\n};\n\n/** `fileIcons` adds Tailwind colour utilities that @k2b/ui does not ship; only the `ti-*` glyph is kept. */\nconst glyph = (props: FileTypeIconProps): string => {\n // `fileIcons` looks names up in plain objects, so a name such as `constructor` returns an inherited member\n // instead of a class string; such names fall back to the generic glyph.\n const found: unknown =\n props.icon ?? fileIcons.getFileIcon({ name: props.name, type: props.folder ? \"directory\" : \"file\", mimeType: props.mediaType });\n const icon =\n (typeof found === \"string\" ? found : \"\")\n .split(/\\s+/)\n .filter((token) => token.startsWith(\"ti-\"))\n .join(\" \") || (props.folder ? \"ti-folder\" : \"ti-file\");\n return props.folder && props.open ? icon.replace(/\\bti-folder$/, \"ti-folder-open\") : icon;\n};\n\n/**\n * A file or folder glyph in a soft chip of its type colour. Folders take the app accent hook\n * `--k2b-app-workspace-active`; code, text, and unknown files a neutral ink. The box size is fixed per `size`.\n */\nexport function FileTypeIcon(props: FileTypeIconProps): JSX.Element {\n return (\n <span\n class={`k2b-icon-tile k2b-file-type-icon ${props.class ?? \"\"}`}\n data-file-type={fileTypeOf({ name: props.name, mediaType: props.mediaType, folder: props.folder })}\n data-size={props.size ?? \"md\"}\n aria-hidden=\"true\"\n >\n <i class={`ti ${glyph(props)}`} />\n </span>\n );\n}\n"],"mappings":";;;;AAAA,SAAS,SAAS,QAAQ,aAAa;;AAGvC;;AAiBA;AACA;AACA,MAAM,YAAY,GAAG,IAAI,GAAG,CAExB,CACE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,EACxC,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,EAClC,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,EAC3C,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CACnE,CACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,UAAU,CAAC,GAAG,CAAE,SAAS,IAAK,CAAC,SAAS,EAAE,IAAI,CAAU,CAAC,CAC7F,CAAC;;AAED;AACA,OAAO,MAAM,UAAU,GAAI,IAA4D,IAAe;EACpG,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,QAAQ;EAChC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;EAC/E,IAAI,KAAK,EAAE,OAAO,KAAK;EACvB,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC,IAAI;IAAE,IAAI,EAAE,MAAM;IAAE,QAAQ,EAAE,IAAI,CAAC;EAAU,CAAC,CAAC;EACvG,OAAO,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,SAAS,GACvH,QAAQ,GACR,OAAO;AACb,CAAC;;AAED;AACA,MAAM,KAAK,GAAI,KAAwB,IAAa;EAClD;EACA;EACA,MAAM,KAAc,GAClB,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC,WAAW,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC,IAAI;IAAE,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,GAAG,MAAM;IAAE,QAAQ,EAAE,KAAK,CAAC;EAAU,CAAC,CAAC;EACjI,MAAM,IAAI,GACR,CAAC,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,EAAE,EACpC,KAAK,CAAC,KAAK,CAAC,CACZ,MAAM,CAAE,KAAK,IAAK,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAC1C,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;EAC1D,OAAO,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,gBAAgB,CAAC,GAAG,IAAI;AAC3F,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,SAAS,YAAY,CAAC,KAAwB,EAAe;EAClE,qBAEW,6CAAoC,KAAK,CAAC,KAAK,IAAI,EAAE,SAAE,4CAC9C,UAAU,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC,IAAI;IAAE,SAAS,EAAE,KAAK,CAAC,SAAS;IAAE,MAAM,EAAE,KAAK,CAAC;EAAO,CAAC,CAAC,uDACvF,KAAK,CAAC,IAAI,IAAI,IAAI,iBAGnB,eAAM,KAAK,CAAC,KAAK,CAAC,SAAE;AAGpC","ignoreList":[]}
@@ -1026,7 +1026,7 @@ export default function FileView(props) {
1026
1026
  },
1027
1027
  get children() {
1028
1028
  return _$createComponent(Placeholder, {
1029
- icon: "ti ti-loader-2",
1029
+ state: "loading",
1030
1030
  get title() {
1031
1031
  return messages().loading;
1032
1032
  }
@@ -1038,7 +1038,7 @@ export default function FileView(props) {
1038
1038
  },
1039
1039
  get children() {
1040
1040
  return _$createComponent(Placeholder, {
1041
- icon: "ti ti-alert-circle",
1041
+ state: "error",
1042
1042
  get title() {
1043
1043
  return fileViewMessages().failedLoadFile;
1044
1044
  },