@kispace-io/core 0.7.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 (272) hide show
  1. package/dist/api/base-classes.d.ts +7 -0
  2. package/dist/api/base-classes.d.ts.map +1 -0
  3. package/dist/api/constants.d.ts +2 -0
  4. package/dist/api/constants.d.ts.map +1 -0
  5. package/dist/api/index.d.ts +6 -0
  6. package/dist/api/index.d.ts.map +1 -0
  7. package/dist/api/index.js +80 -0
  8. package/dist/api/index.js.map +1 -0
  9. package/dist/api/services.d.ts +27 -0
  10. package/dist/api/services.d.ts.map +1 -0
  11. package/dist/api/types.d.ts +11 -0
  12. package/dist/api/types.d.ts.map +1 -0
  13. package/dist/commands/files.d.ts +2 -0
  14. package/dist/commands/files.d.ts.map +1 -0
  15. package/dist/commands/global.d.ts +1 -0
  16. package/dist/commands/global.d.ts.map +1 -0
  17. package/dist/commands/index.d.ts +1 -0
  18. package/dist/commands/index.d.ts.map +1 -0
  19. package/dist/commands/version-info.d.ts +2 -0
  20. package/dist/commands/version-info.d.ts.map +1 -0
  21. package/dist/components/index.d.ts +1 -0
  22. package/dist/components/index.d.ts.map +1 -0
  23. package/dist/components/k-app-selector.d.ts +17 -0
  24. package/dist/components/k-app-selector.d.ts.map +1 -0
  25. package/dist/components/k-app-switcher.d.ts +13 -0
  26. package/dist/components/k-app-switcher.d.ts.map +1 -0
  27. package/dist/components/k-command.d.ts +31 -0
  28. package/dist/components/k-command.d.ts.map +1 -0
  29. package/dist/components/k-extensions.d.ts +32 -0
  30. package/dist/components/k-extensions.d.ts.map +1 -0
  31. package/dist/components/k-fastviews.d.ts +34 -0
  32. package/dist/components/k-fastviews.d.ts.map +1 -0
  33. package/dist/components/k-filebrowser.d.ts +40 -0
  34. package/dist/components/k-filebrowser.d.ts.map +1 -0
  35. package/dist/components/k-language-selector.d.ts +12 -0
  36. package/dist/components/k-language-selector.d.ts.map +1 -0
  37. package/dist/components/k-log-terminal.d.ts +36 -0
  38. package/dist/components/k-log-terminal.d.ts.map +1 -0
  39. package/dist/components/k-part-name.d.ts +12 -0
  40. package/dist/components/k-part-name.d.ts.map +1 -0
  41. package/dist/components/k-tasks.d.ts +13 -0
  42. package/dist/components/k-tasks.d.ts.map +1 -0
  43. package/dist/components/k-workspace-name.d.ts +14 -0
  44. package/dist/components/k-workspace-name.d.ts.map +1 -0
  45. package/dist/contributions/default-ui-contributions.d.ts +2 -0
  46. package/dist/contributions/default-ui-contributions.d.ts.map +1 -0
  47. package/dist/contributions/index.d.ts +1 -0
  48. package/dist/contributions/index.d.ts.map +1 -0
  49. package/dist/contributions/marketplace-catalog-contributions.d.ts +2 -0
  50. package/dist/contributions/marketplace-catalog-contributions.d.ts.map +1 -0
  51. package/dist/core/app-host-config.d.ts +7 -0
  52. package/dist/core/app-host-config.d.ts.map +1 -0
  53. package/dist/core/apploader.d.ts +214 -0
  54. package/dist/core/apploader.d.ts.map +1 -0
  55. package/dist/core/appstate.d.ts +12 -0
  56. package/dist/core/appstate.d.ts.map +1 -0
  57. package/dist/core/commandregistry.d.ts +79 -0
  58. package/dist/core/commandregistry.d.ts.map +1 -0
  59. package/dist/core/config.d.ts +15 -0
  60. package/dist/core/config.d.ts.map +1 -0
  61. package/dist/core/constants.d.ts +21 -0
  62. package/dist/core/constants.d.ts.map +1 -0
  63. package/dist/core/contributionregistry.d.ts +49 -0
  64. package/dist/core/contributionregistry.d.ts.map +1 -0
  65. package/dist/core/di.d.ts +18 -0
  66. package/dist/core/di.d.ts.map +1 -0
  67. package/dist/core/dialogservice.d.ts +33 -0
  68. package/dist/core/dialogservice.d.ts.map +1 -0
  69. package/dist/core/editorregistry.d.ts +73 -0
  70. package/dist/core/editorregistry.d.ts.map +1 -0
  71. package/dist/core/esmsh-service.d.ts +40 -0
  72. package/dist/core/esmsh-service.d.ts.map +1 -0
  73. package/dist/core/events.d.ts +7 -0
  74. package/dist/core/events.d.ts.map +1 -0
  75. package/dist/core/events.js +63 -0
  76. package/dist/core/events.js.map +1 -0
  77. package/dist/core/extensionregistry.d.ts +98 -0
  78. package/dist/core/extensionregistry.d.ts.map +1 -0
  79. package/dist/core/filesys.d.ts +139 -0
  80. package/dist/core/filesys.d.ts.map +1 -0
  81. package/dist/core/i18n.d.ts +50 -0
  82. package/dist/core/i18n.d.ts.map +1 -0
  83. package/dist/core/index.d.ts +1 -0
  84. package/dist/core/index.d.ts.map +1 -0
  85. package/dist/core/k-utils.d.ts +2 -0
  86. package/dist/core/k-utils.d.ts.map +1 -0
  87. package/dist/core/keybindings.d.ts +67 -0
  88. package/dist/core/keybindings.d.ts.map +1 -0
  89. package/dist/core/logger.d.ts +44 -0
  90. package/dist/core/logger.d.ts.map +1 -0
  91. package/dist/core/marketplaceregistry.d.ts +25 -0
  92. package/dist/core/marketplaceregistry.d.ts.map +1 -0
  93. package/dist/core/packageinfoservice.d.ts +16 -0
  94. package/dist/core/packageinfoservice.d.ts.map +1 -0
  95. package/dist/core/persistenceservice.d.ts +6 -0
  96. package/dist/core/persistenceservice.d.ts.map +1 -0
  97. package/dist/core/settingsservice.d.ts +19 -0
  98. package/dist/core/settingsservice.d.ts.map +1 -0
  99. package/dist/core/signals.d.ts +3 -0
  100. package/dist/core/signals.d.ts.map +1 -0
  101. package/dist/core/taskservice.d.ts +20 -0
  102. package/dist/core/taskservice.d.ts.map +1 -0
  103. package/dist/core/toast.d.ts +4 -0
  104. package/dist/core/toast.d.ts.map +1 -0
  105. package/dist/core/tree-utils.d.ts +16 -0
  106. package/dist/core/tree-utils.d.ts.map +1 -0
  107. package/dist/dialogs/confirm-dialog.d.ts +14 -0
  108. package/dist/dialogs/confirm-dialog.d.ts.map +1 -0
  109. package/dist/dialogs/index.d.ts +5 -0
  110. package/dist/dialogs/index.d.ts.map +1 -0
  111. package/dist/dialogs/info-dialog.d.ts +13 -0
  112. package/dist/dialogs/info-dialog.d.ts.map +1 -0
  113. package/dist/dialogs/navigable-info-dialog.d.ts +33 -0
  114. package/dist/dialogs/navigable-info-dialog.d.ts.map +1 -0
  115. package/dist/dialogs/prompt-dialog.d.ts +21 -0
  116. package/dist/dialogs/prompt-dialog.d.ts.map +1 -0
  117. package/dist/externals/lit.d.ts +20 -0
  118. package/dist/externals/lit.d.ts.map +1 -0
  119. package/dist/externals/lit.js +15 -0
  120. package/dist/externals/lit.js.map +1 -0
  121. package/dist/externals/third-party.d.ts +7 -0
  122. package/dist/externals/third-party.d.ts.map +1 -0
  123. package/dist/externals/third-party.js +2 -0
  124. package/dist/externals/third-party.js.map +1 -0
  125. package/dist/externals/webawesome.d.ts +1 -0
  126. package/dist/externals/webawesome.d.ts.map +1 -0
  127. package/dist/externals/webawesome.js +52 -0
  128. package/dist/externals/webawesome.js.map +1 -0
  129. package/dist/i18n/extensions.json.d.ts +42 -0
  130. package/dist/i18n/fastviews.json.d.ts +13 -0
  131. package/dist/i18n/filebrowser.json.d.ts +35 -0
  132. package/dist/i18n/index.d.ts +2 -0
  133. package/dist/i18n/index.d.ts.map +1 -0
  134. package/dist/i18n/logterminal.json.d.ts +45 -0
  135. package/dist/i18n/partname.json.d.ts +15 -0
  136. package/dist/i18n/tasks.json.d.ts +15 -0
  137. package/dist/i18n/workspace.json.d.ts +15 -0
  138. package/dist/index.d.ts +2 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +80 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/k-icon-BZC7dQV0.js +492 -0
  143. package/dist/k-icon-BZC7dQV0.js.map +1 -0
  144. package/dist/k-nocontent-Bh_yToGh.js +48 -0
  145. package/dist/k-nocontent-Bh_yToGh.js.map +1 -0
  146. package/dist/k-resizable-grid-Ch3iWZaL.js +3157 -0
  147. package/dist/k-resizable-grid-Ch3iWZaL.js.map +1 -0
  148. package/dist/k-standard-layout-CQ1VZoxa.js +5011 -0
  149. package/dist/k-standard-layout-CQ1VZoxa.js.map +1 -0
  150. package/dist/layouts/k-standard-layout.d.ts +16 -0
  151. package/dist/layouts/k-standard-layout.d.ts.map +1 -0
  152. package/dist/parts/index.d.ts +1 -0
  153. package/dist/parts/index.d.ts.map +1 -0
  154. package/dist/parts/index.js +53 -0
  155. package/dist/parts/index.js.map +1 -0
  156. package/dist/parts/k-app.d.ts +11 -0
  157. package/dist/parts/k-app.d.ts.map +1 -0
  158. package/dist/parts/k-container.d.ts +4 -0
  159. package/dist/parts/k-container.d.ts.map +1 -0
  160. package/dist/parts/k-contextmenu.d.ts +38 -0
  161. package/dist/parts/k-contextmenu.d.ts.map +1 -0
  162. package/dist/parts/k-dialog-content.d.ts +9 -0
  163. package/dist/parts/k-dialog-content.d.ts.map +1 -0
  164. package/dist/parts/k-element.d.ts +36 -0
  165. package/dist/parts/k-element.d.ts.map +1 -0
  166. package/dist/parts/k-part.d.ts +96 -0
  167. package/dist/parts/k-part.d.ts.map +1 -0
  168. package/dist/parts/k-resizable-grid.d.ts +31 -0
  169. package/dist/parts/k-resizable-grid.d.ts.map +1 -0
  170. package/dist/parts/k-tabs.d.ts +74 -0
  171. package/dist/parts/k-tabs.d.ts.map +1 -0
  172. package/dist/parts/k-toolbar.d.ts +21 -0
  173. package/dist/parts/k-toolbar.d.ts.map +1 -0
  174. package/dist/widgets/index.d.ts +1 -0
  175. package/dist/widgets/index.d.ts.map +1 -0
  176. package/dist/widgets/index.js +3 -0
  177. package/dist/widgets/index.js.map +1 -0
  178. package/dist/widgets/k-icon.d.ts +10 -0
  179. package/dist/widgets/k-icon.d.ts.map +1 -0
  180. package/dist/widgets/k-nocontent.d.ts +13 -0
  181. package/dist/widgets/k-nocontent.d.ts.map +1 -0
  182. package/dist/widgets/k-widget.d.ts +25 -0
  183. package/dist/widgets/k-widget.d.ts.map +1 -0
  184. package/package.json +81 -0
  185. package/src/api/base-classes.ts +10 -0
  186. package/src/api/constants.ts +3 -0
  187. package/src/api/index.ts +31 -0
  188. package/src/api/services.ts +52 -0
  189. package/src/api/types.ts +46 -0
  190. package/src/commands/files.ts +829 -0
  191. package/src/commands/global.ts +225 -0
  192. package/src/commands/index.ts +4 -0
  193. package/src/commands/version-info.ts +214 -0
  194. package/src/components/index.ts +10 -0
  195. package/src/components/k-app-selector.ts +233 -0
  196. package/src/components/k-app-switcher.ts +126 -0
  197. package/src/components/k-command.ts +236 -0
  198. package/src/components/k-extensions.ts +615 -0
  199. package/src/components/k-fastviews.ts +314 -0
  200. package/src/components/k-filebrowser.ts +442 -0
  201. package/src/components/k-language-selector.ts +166 -0
  202. package/src/components/k-log-terminal.ts +337 -0
  203. package/src/components/k-part-name.ts +54 -0
  204. package/src/components/k-tasks.ts +267 -0
  205. package/src/components/k-workspace-name.ts +56 -0
  206. package/src/contributions/default-ui-contributions.ts +51 -0
  207. package/src/contributions/index.ts +3 -0
  208. package/src/contributions/marketplace-catalog-contributions.ts +6 -0
  209. package/src/core/app-host-config.ts +23 -0
  210. package/src/core/apploader.ts +630 -0
  211. package/src/core/appstate.ts +15 -0
  212. package/src/core/commandregistry.ts +210 -0
  213. package/src/core/config.ts +29 -0
  214. package/src/core/constants.ts +27 -0
  215. package/src/core/contributionregistry.ts +77 -0
  216. package/src/core/di.ts +54 -0
  217. package/src/core/dialogservice.ts +266 -0
  218. package/src/core/editorregistry.ts +303 -0
  219. package/src/core/esmsh-service.ts +404 -0
  220. package/src/core/events.ts +68 -0
  221. package/src/core/extensionregistry.ts +399 -0
  222. package/src/core/filesys.ts +618 -0
  223. package/src/core/i18n.ts +221 -0
  224. package/src/core/index.ts +51 -0
  225. package/src/core/k-utils.ts +11 -0
  226. package/src/core/keybindings.ts +274 -0
  227. package/src/core/logger.ts +187 -0
  228. package/src/core/marketplaceregistry.ts +197 -0
  229. package/src/core/packageinfoservice.ts +56 -0
  230. package/src/core/persistenceservice.ts +15 -0
  231. package/src/core/settingsservice.ts +70 -0
  232. package/src/core/signals.ts +18 -0
  233. package/src/core/taskservice.ts +72 -0
  234. package/src/core/toast.ts +11 -0
  235. package/src/core/tree-utils.ts +24 -0
  236. package/src/dialogs/confirm-dialog.ts +72 -0
  237. package/src/dialogs/index.ts +4 -0
  238. package/src/dialogs/info-dialog.ts +67 -0
  239. package/src/dialogs/navigable-info-dialog.ts +256 -0
  240. package/src/dialogs/prompt-dialog.ts +123 -0
  241. package/src/externals/lit.ts +26 -0
  242. package/src/externals/third-party.ts +9 -0
  243. package/src/externals/webawesome.ts +54 -0
  244. package/src/i18n/extensions.json +39 -0
  245. package/src/i18n/fastviews.json +10 -0
  246. package/src/i18n/filebrowser.json +33 -0
  247. package/src/i18n/index.ts +25 -0
  248. package/src/i18n/logterminal.json +42 -0
  249. package/src/i18n/partname.json +12 -0
  250. package/src/i18n/tasks.json +12 -0
  251. package/src/i18n/workspace.json +12 -0
  252. package/src/icons/icons.txt +3 -0
  253. package/src/icons/js.svg +6 -0
  254. package/src/icons/jupyter.svg +18 -0
  255. package/src/icons/python.svg +15 -0
  256. package/src/index.ts +3 -0
  257. package/src/layouts/k-standard-layout.ts +174 -0
  258. package/src/parts/index.ts +6 -0
  259. package/src/parts/k-app.ts +29 -0
  260. package/src/parts/k-container.ts +4 -0
  261. package/src/parts/k-contextmenu.ts +245 -0
  262. package/src/parts/k-dialog-content.ts +31 -0
  263. package/src/parts/k-element.ts +100 -0
  264. package/src/parts/k-part.ts +158 -0
  265. package/src/parts/k-resizable-grid.ts +366 -0
  266. package/src/parts/k-tabs.ts +574 -0
  267. package/src/parts/k-toolbar.ts +158 -0
  268. package/src/vite-env.d.ts +2 -0
  269. package/src/widgets/index.ts +2 -0
  270. package/src/widgets/k-icon.ts +39 -0
  271. package/src/widgets/k-nocontent.ts +40 -0
  272. package/src/widgets/k-widget.ts +90 -0
@@ -0,0 +1,225 @@
1
+ import { registerAll } from "../core/commandregistry";
2
+ import { CommandContribution } from "../core/contributionregistry";
3
+ import { TOOLBAR_MAIN_RIGHT } from "../core/constants";
4
+ import { EditorInput, editorRegistry } from "../core/editorregistry";
5
+ import { html } from "lit";
6
+ import { toastError, toastInfo } from "../core/toast";
7
+ import { activeEditorSignal, activePartSignal } from "../core/appstate";
8
+ import { appSettings } from "../core/settingsservice";
9
+ import { extensionRegistry } from "../core/extensionregistry";
10
+ import type { Extension } from "../core/extensionregistry";
11
+ import { marketplaceRegistry } from "../core/marketplaceregistry";
12
+ import "./files";
13
+ import "./version-info";
14
+
15
+ registerAll({
16
+ command: {
17
+ "id": "js",
18
+ "name": "Run JavaScript file",
19
+ "description": "Executes a JavaScript file given its path",
20
+ "parameters": [
21
+ {
22
+ "name": "script",
23
+ "description": "the path to a JavaScript file to run",
24
+ "required": false
25
+ }
26
+ ]
27
+ }
28
+ })
29
+
30
+ registerAll({
31
+ command: {
32
+ "id": "save",
33
+ "name": "Save editor",
34
+ "description": "Saves the active/focused editor",
35
+ "keyBinding": "CTRL+S",
36
+ "parameters": []
37
+ },
38
+ handler: {
39
+ execute: async _context => {
40
+ const part = activeEditorSignal.get() || activePartSignal.get()
41
+ if (part && part.isDirty()) {
42
+ part.save()
43
+ }
44
+ }
45
+ },
46
+ contribution: {
47
+ target: "toolbar:.system.editors",
48
+ icon: "floppy-disk",
49
+ label: "Save active editor",
50
+ slot: "start",
51
+ disabled: () => {
52
+ const part = activePartSignal.get()
53
+ return !part || !part.isDirty()
54
+ }
55
+ } as CommandContribution
56
+ })
57
+
58
+ registerAll({
59
+ command: {
60
+ "id": "run_python",
61
+ "name": "Run Python Cell",
62
+ "description": "Runs active Python code in a supporting context (e.g. notebook, terminal, etc.)",
63
+ "keyBinding": "CTRL+R",
64
+ "parameters": []
65
+ }
66
+ })
67
+
68
+ const THEME_SETTINGS_KEY = "theme"
69
+
70
+ async function applyTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {
71
+ const root = document.documentElement
72
+ root.classList.remove('wa-dark', 'wa-light')
73
+ root.classList.add(themeClass)
74
+ }
75
+
76
+ async function loadTheme(): Promise<void> {
77
+ const theme = await appSettings.get(THEME_SETTINGS_KEY)
78
+ await applyTheme(theme || 'wa-dark')
79
+ }
80
+
81
+ async function saveTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {
82
+ await appSettings.set(THEME_SETTINGS_KEY, themeClass)
83
+ }
84
+
85
+ registerAll({
86
+ command: {
87
+ "id": "switch_theme",
88
+ "name": "Switch theme",
89
+ "description": "Switches between dark and light theme",
90
+ "parameters": []
91
+ },
92
+ handler: {
93
+ execute: async _context => {
94
+ const isDark = document.documentElement.classList.contains("wa-dark")
95
+ const newTheme = isDark ? 'wa-light' : 'wa-dark'
96
+ await applyTheme(newTheme)
97
+ await saveTheme(newTheme)
98
+ }
99
+ },
100
+ contribution: {
101
+ target: TOOLBAR_MAIN_RIGHT,
102
+ icon: "circle-half-stroke",
103
+ label: "Theme Switcher",
104
+ }
105
+ })
106
+
107
+ // Load theme on module initialization
108
+ loadTheme().catch(err => {
109
+ console.error('Failed to load theme preference:', err)
110
+ })
111
+
112
+ registerAll({
113
+ command: {
114
+ "id": "fullscreen",
115
+ "name": "Toggle fullscreen",
116
+ "description": "Toggles fullscreen mode",
117
+ "parameters": []
118
+ },
119
+ handler: {
120
+ execute: async _context => {
121
+ if (document.fullscreenElement === document.body) {
122
+ await document.exitFullscreen()
123
+ } else {
124
+ await document.body.requestFullscreen()
125
+ }
126
+ }
127
+ },
128
+ contribution: {
129
+ target: TOOLBAR_MAIN_RIGHT,
130
+ icon: "expand",
131
+ label: "Fullscreen",
132
+ }
133
+ })
134
+
135
+ registerAll({
136
+ command: {
137
+ "id": "open_extensions",
138
+ "name": "Open Extensions",
139
+ "description": "Opens the extensions registry",
140
+ "parameters": []
141
+ },
142
+ handler: {
143
+ execute: _context => {
144
+ const editorInput = {
145
+ title: "Extensions",
146
+ data: {},
147
+ key: "system.extensions",
148
+ editorId: "extensions-editor",
149
+ icon: "puzzle-piece",
150
+ state: {},
151
+ noOverflow: true,
152
+ } as EditorInput
153
+ editorInput.widgetFactory = () => html`
154
+ <k-extensions></k-extensions>`
155
+ editorRegistry.loadEditor(editorInput).then()
156
+ }
157
+ },
158
+ contribution: {
159
+ target: TOOLBAR_MAIN_RIGHT,
160
+ icon: "puzzle-piece",
161
+ label: "Open Extensions",
162
+ }
163
+ })
164
+
165
+ registerAll({
166
+ command: {
167
+ "id": "list_extensions",
168
+ "name": "List extensions",
169
+ "description": "Lists all available extensions with their status (enabled/disabled)",
170
+ "parameters": [],
171
+ "output": [
172
+ {
173
+ "name": "extensions",
174
+ "description": "array of extension objects with id, name, description, experimental flag, and enabled status"
175
+ }
176
+ ]
177
+ },
178
+ handler: {
179
+ execute: async (_context: any) => {
180
+ const extensions = extensionRegistry.getExtensions().map((e: Extension) => {
181
+ return {
182
+ id: e.id,
183
+ name: e.name,
184
+ description: e.description,
185
+ experimental: e.experimental,
186
+ enabled: extensionRegistry.isEnabled(e.id)
187
+ }
188
+ });
189
+ return extensions;
190
+ }
191
+ }
192
+ })
193
+
194
+ registerAll({
195
+ command: {
196
+ "id": "toast_message",
197
+ "name": "Toast message to user",
198
+ "description": "Shows a toast message",
199
+ "parameters": [
200
+ {
201
+ "name": "message",
202
+ "description": "the message to toast",
203
+ "required": true
204
+ },
205
+ {
206
+ "name": "type",
207
+ "description": "the toast type: info (default), or error",
208
+ "required": false
209
+ }
210
+ ]
211
+ },
212
+ handler: {
213
+ execute: ({ params: { message, type } }: any) => {
214
+ if (!message) {
215
+ return
216
+ }
217
+ if (type === "error") {
218
+ toastError(message)
219
+ } else {
220
+ toastInfo(message)
221
+ }
222
+ }
223
+ }
224
+ })
225
+
@@ -0,0 +1,4 @@
1
+ import "./files";
2
+ import "./global";
3
+ import "./version-info";
4
+
@@ -0,0 +1,214 @@
1
+ import { registerAll } from "../core/commandregistry";
2
+ import { html, render } from "lit";
3
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
4
+ import { marked } from "marked";
5
+ import { toastError } from "../core/toast";
6
+ import { appLoaderService, type ReleaseEntry } from "../core/apploader";
7
+ import { packageInfoService } from "../core/packageinfoservice";
8
+
9
+ registerAll({
10
+ command: {
11
+ "id": "show_version_info",
12
+ "name": "Show Version Info",
13
+ "description": "Shows application version information",
14
+ "parameters": []
15
+ },
16
+ handler: {
17
+ execute: async _context => {
18
+ const app = appLoaderService.getCurrentApp();
19
+ if (!app) {
20
+ toastError("No app loaded");
21
+ return;
22
+ }
23
+
24
+ const hasPackages = packageInfoService.hasPackages();
25
+ const packagesTree = packageInfoService.renderTree();
26
+
27
+ let dialogContainer: HTMLElement | null = null;
28
+ const getDialogContainer = (): HTMLElement => {
29
+ if (!dialogContainer) {
30
+ dialogContainer = document.getElementById('global-dialog-container') || document.createElement('div');
31
+ if (!dialogContainer.id) {
32
+ dialogContainer.id = 'global-dialog-container';
33
+ document.body.appendChild(dialogContainer);
34
+ }
35
+ }
36
+ return dialogContainer;
37
+ };
38
+
39
+ const cleanup = () => {
40
+ if (dialogContainer) {
41
+ render(html``, dialogContainer);
42
+ }
43
+ };
44
+
45
+ const renderReleaseContent = (releaseContent: string) => {
46
+ const htmlContent = marked.parse(releaseContent, { async: false }) as string;
47
+ return html`${unsafeHTML(htmlContent)}`;
48
+ };
49
+
50
+ let releases: ReleaseEntry[] = [];
51
+ if (app.releaseHistory) {
52
+ if (typeof app.releaseHistory === 'function') {
53
+ try {
54
+ releases = await app.releaseHistory();
55
+ } catch (error) {
56
+ console.error('Failed to load release history from app:', error);
57
+ releases = [];
58
+ }
59
+ } else {
60
+ releases = app.releaseHistory;
61
+ }
62
+ }
63
+
64
+ const isDev = app.version === '0.0.0';
65
+ const currentIndex = releases.length > 0 ? releases.findIndex(r => r.tag_name === app.version) : -1;
66
+ const startIndex = currentIndex >= 0 ? currentIndex : 0;
67
+ let currentReleaseIndex = startIndex;
68
+
69
+ const buildReleaseContent = (index: number) => {
70
+ if (releases.length === 0) {
71
+ return "";
72
+ }
73
+
74
+ const release = releases[index];
75
+ const isCurrentVersion = release.tag_name === app.version;
76
+
77
+ let message = `**Version:** ${release.tag_name}`;
78
+ if (isCurrentVersion) {
79
+ message += ` (Current)`;
80
+ }
81
+ message += `\n\n`;
82
+
83
+ const publishDate = new Date(release.published_at).toLocaleDateString();
84
+ message += `**Released:** ${publishDate}\n\n`;
85
+
86
+ if (!isCurrentVersion) {
87
+ const cleanCurrent = app.version.replace(/^v/, '');
88
+ const cleanRelease = release.tag_name.replace(/^v/, '');
89
+ const currentParts = cleanCurrent.split('.').map(Number);
90
+ const releaseParts = cleanRelease.split('.').map(Number);
91
+ let isNewer = false;
92
+ for (let i = 0; i < Math.max(currentParts.length, releaseParts.length); i++) {
93
+ const current = currentParts[i] || 0;
94
+ const releasePart = releaseParts[i] || 0;
95
+ if (releasePart > current) {
96
+ isNewer = true;
97
+ break;
98
+ }
99
+ if (releasePart < current) {
100
+ break;
101
+ }
102
+ }
103
+ if (isNewer) {
104
+ message += `⚠️ **Update available - reload page to update**\n\n`;
105
+ }
106
+ }
107
+
108
+ if (release.body) {
109
+ message += `---\n\n${release.body}`;
110
+ }
111
+
112
+ return message;
113
+ };
114
+
115
+ const handleClose = () => {
116
+ cleanup();
117
+ };
118
+
119
+ const handleAfterHide = () => {
120
+ cleanup();
121
+ };
122
+
123
+ const updateDialog = (index: number) => {
124
+ const releaseContent = buildReleaseContent(index);
125
+ const hasNavigation = releases.length > 0;
126
+
127
+ const template = html`
128
+ <wa-dialog
129
+ label="About ${app.name} - ${app.version}"
130
+ open
131
+ light-dismiss
132
+ style="--width: 600px;"
133
+ @wa-request-close=${handleClose}
134
+ @wa-after-hide=${handleAfterHide}
135
+ >
136
+ <style>
137
+ .dialog-content {
138
+ height: 600px;
139
+ }
140
+
141
+ wa-tree-item > span small {
142
+ color: var(--wa-color-neutral-60);
143
+ font-size: 0.875em;
144
+ margin-left: 0.5rem;
145
+ }
146
+ </style>
147
+ <small>${app.description}</small>
148
+ <div class="dialog-content">
149
+ <wa-tab-group>
150
+ ${releases.length > 0 ? html`
151
+ <wa-tab slot="nav" panel="release">Release History</wa-tab>
152
+ <wa-tab-panel name="release">
153
+ ${renderReleaseContent(releaseContent)}
154
+ </wa-tab-panel>
155
+ ` : ''}
156
+
157
+ ${hasPackages ? html`
158
+ <wa-tab slot="nav" panel="packages">NPM Packages</wa-tab>
159
+ <wa-tab-panel name="packages">
160
+ ${packagesTree}
161
+ </wa-tab-panel>
162
+ ` : ''}
163
+ </wa-tab-group>
164
+ </div>
165
+ <div slot="footer">
166
+ ${hasNavigation ? html`
167
+ <wa-button
168
+ variant="default"
169
+ ?disabled=${index === releases.length - 1}
170
+ @click=${() => {
171
+ if (index < releases.length - 1) {
172
+ currentReleaseIndex = index + 1;
173
+ updateDialog(currentReleaseIndex);
174
+ }
175
+ }}
176
+ >
177
+ ← Previous
178
+ </wa-button>
179
+ <wa-button
180
+ variant="default"
181
+ ?disabled=${index === 0}
182
+ @click=${() => {
183
+ if (index > 0) {
184
+ currentReleaseIndex = index - 1;
185
+ updateDialog(currentReleaseIndex);
186
+ }
187
+ }}
188
+ >
189
+ Next →
190
+ </wa-button>
191
+ ` : ''}
192
+ <wa-button variant="primary" data-dialog="close">Close</wa-button>
193
+ </div>
194
+ </wa-dialog>
195
+ `;
196
+ render(template, getDialogContainer());
197
+ };
198
+
199
+ updateDialog(startIndex);
200
+
201
+ return new Promise<void>((resolve) => {
202
+ const checkClosed = () => {
203
+ if (!dialogContainer?.querySelector('wa-dialog[open]')) {
204
+ resolve();
205
+ } else {
206
+ setTimeout(checkClosed, 100);
207
+ }
208
+ };
209
+ checkClosed();
210
+ });
211
+ }
212
+ }
213
+ })
214
+
@@ -0,0 +1,10 @@
1
+ import "./k-filebrowser"
2
+ import "./k-tasks"
3
+ import "./k-workspace-name"
4
+ import "./k-part-name"
5
+ import "./k-extensions"
6
+ import "./k-log-terminal"
7
+ import "./k-command"
8
+ import "./k-fastviews"
9
+ import "./k-language-selector"
10
+ import "./k-app-switcher"
@@ -0,0 +1,233 @@
1
+ import { html, css } from "lit";
2
+ import { customElement, state } from "lit/decorators.js";
3
+ import { KElement } from "../parts/k-element";
4
+ import { appLoaderService, type AppDefinition } from "../core/apploader";
5
+
6
+ @customElement('k-app-selector')
7
+ export class KAppSelector extends KElement {
8
+ @state()
9
+ private apps: AppDefinition[] = [];
10
+
11
+ @state()
12
+ private loading = true;
13
+
14
+ @state()
15
+ private error: string | null = null;
16
+
17
+ protected async doBeforeUI() {
18
+ await this.loadApps();
19
+ }
20
+
21
+ private async loadApps() {
22
+ try {
23
+ this.loading = true;
24
+ this.apps = appLoaderService.getRegisteredApps();
25
+ this.loading = false;
26
+ } catch (err) {
27
+ this.error = err instanceof Error ? err.message : 'Failed to load apps';
28
+ this.loading = false;
29
+ }
30
+ }
31
+
32
+ private async selectApp(app: AppDefinition) {
33
+ try {
34
+ await appLoaderService.setPreferredAppId(app.id);
35
+ await appLoaderService.loadApp(app.id, document.body);
36
+ } catch (err) {
37
+ this.error = err instanceof Error ? err.message : 'Failed to load app';
38
+ }
39
+ }
40
+
41
+ protected render() {
42
+ if (this.loading) {
43
+ return html`
44
+ <div class="selector-container">
45
+ <wa-spinner></wa-spinner>
46
+ <p>Loading available apps...</p>
47
+ </div>
48
+ `;
49
+ }
50
+
51
+ if (this.error) {
52
+ return html`
53
+ <div class="selector-container">
54
+ <wa-icon name="triangle-exclamation" class="error-icon"></wa-icon>
55
+ <p class="error-message">${this.error}</p>
56
+ <wa-button @click=${() => this.loadApps()}>Retry</wa-button>
57
+ </div>
58
+ `;
59
+ }
60
+
61
+ if (this.apps.length === 0) {
62
+ return html`
63
+ <div class="selector-container">
64
+ <wa-icon name="folder-open" class="empty-icon"></wa-icon>
65
+ <h2>No Apps Available</h2>
66
+ <p>No applications are currently registered.</p>
67
+ </div>
68
+ `;
69
+ }
70
+
71
+ return html`
72
+ <div class="selector-container">
73
+ <div class="header">
74
+ <h1>Select an Application</h1>
75
+ <p>Choose an application to load</p>
76
+ </div>
77
+
78
+ <div class="app-list">
79
+ ${this.apps.map(app => html`
80
+ <div
81
+ class="app-card"
82
+ @click=${() => this.selectApp(app)}
83
+ @keydown=${(e: KeyboardEvent) => {
84
+ if (e.key === 'Enter' || e.key === ' ') {
85
+ e.preventDefault();
86
+ this.selectApp(app);
87
+ }
88
+ }}
89
+ tabindex="0"
90
+ role="button">
91
+ <div class="app-header">
92
+ <h3 class="app-name">${app.name}</h3>
93
+ ${app.version ? html`<span class="app-version">v${app.version}</span>` : ''}
94
+ </div>
95
+ ${app.description ? html`<p class="app-description">${app.description}</p>` : ''}
96
+ <div class="app-id">ID: ${app.id}</div>
97
+ </div>
98
+ `)}
99
+ </div>
100
+ </div>
101
+ `;
102
+ }
103
+
104
+ static styles = css`
105
+ :host {
106
+ display: flex;
107
+ flex-direction: column;
108
+ width: 100%;
109
+ height: 100vh;
110
+ align-items: center;
111
+ justify-content: center;
112
+ background: var(--wa-color-neutral-background-base);
113
+ }
114
+
115
+ .selector-container {
116
+ display: flex;
117
+ flex-direction: column;
118
+ align-items: center;
119
+ justify-content: center;
120
+ max-width: 800px;
121
+ width: 100%;
122
+ padding: 2rem;
123
+ box-sizing: border-box;
124
+ }
125
+
126
+ .header {
127
+ text-align: center;
128
+ margin-bottom: 2rem;
129
+ }
130
+
131
+ .header h1 {
132
+ margin: 0 0 0.5rem 0;
133
+ font-size: 2rem;
134
+ font-weight: 600;
135
+ color: var(--wa-color-neutral-foreground-loud);
136
+ }
137
+
138
+ .header p {
139
+ margin: 0;
140
+ color: var(--wa-color-neutral-foreground-quiet);
141
+ }
142
+
143
+ .app-list {
144
+ display: grid;
145
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
146
+ gap: 1rem;
147
+ width: 100%;
148
+ }
149
+
150
+ .app-card {
151
+ display: flex;
152
+ flex-direction: column;
153
+ padding: 1.5rem;
154
+ border: 1px solid var(--wa-color-neutral-border-loud);
155
+ border-radius: var(--wa-border-radius-medium);
156
+ background: var(--wa-color-neutral-background-base);
157
+ cursor: pointer;
158
+ transition: all 0.2s ease;
159
+ box-sizing: border-box;
160
+ }
161
+
162
+ .app-card:hover {
163
+ border-color: var(--wa-color-brand-border-loud);
164
+ background: var(--wa-color-brand-fill-quiet);
165
+ transform: translateY(-2px);
166
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
167
+ }
168
+
169
+ .app-card:focus {
170
+ outline: 2px solid var(--wa-color-brand-border-loud);
171
+ outline-offset: 2px;
172
+ }
173
+
174
+ .app-header {
175
+ display: flex;
176
+ justify-content: space-between;
177
+ align-items: flex-start;
178
+ margin-bottom: 0.75rem;
179
+ }
180
+
181
+ .app-name {
182
+ margin: 0;
183
+ font-size: 1.25rem;
184
+ font-weight: 600;
185
+ color: var(--wa-color-neutral-foreground-loud);
186
+ flex: 1;
187
+ }
188
+
189
+ .app-version {
190
+ font-size: 0.875rem;
191
+ color: var(--wa-color-neutral-foreground-quiet);
192
+ padding: 0.25rem 0.5rem;
193
+ background: var(--wa-color-neutral-fill-quiet);
194
+ border-radius: var(--wa-border-radius-small);
195
+ }
196
+
197
+ .app-description {
198
+ margin: 0 0 0.75rem 0;
199
+ color: var(--wa-color-neutral-foreground-base);
200
+ line-height: 1.5;
201
+ }
202
+
203
+ .app-id {
204
+ font-size: 0.75rem;
205
+ color: var(--wa-color-neutral-foreground-quiet);
206
+ font-family: monospace;
207
+ margin-top: auto;
208
+ }
209
+
210
+ .empty-icon,
211
+ .error-icon {
212
+ font-size: 4rem;
213
+ color: var(--wa-color-neutral-foreground-quiet);
214
+ margin-bottom: 1rem;
215
+ }
216
+
217
+ .error-message {
218
+ color: var(--wa-color-danger-foreground-loud);
219
+ margin-bottom: 1rem;
220
+ }
221
+
222
+ wa-spinner {
223
+ margin-bottom: 1rem;
224
+ }
225
+ `;
226
+ }
227
+
228
+ declare global {
229
+ interface HTMLElementTagNameMap {
230
+ 'k-app-selector': KAppSelector;
231
+ }
232
+ }
233
+