@monkey-mini-app/dsh-mini-app 0.1.0 → 0.1.4

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 (317) hide show
  1. package/README.md +59 -0
  2. package/assets/apps-list.png +0 -0
  3. package/assets/complex-demo-app.png +0 -0
  4. package/assets/demo-app.png +0 -0
  5. package/assets/home.png +0 -0
  6. package/assets/sidebar-mode.png +0 -0
  7. package/lib/client.js +2024 -783
  8. package/lib/index.d.ts +5 -2
  9. package/lib/index.js +29 -16
  10. package/package.json +12 -10
  11. package/skills/monkey-mini-app/SKILL.md +182 -106
  12. package/skills/monkey-mini-app/references/catalog.md +236 -99
  13. package/skills/monkey-mini-app/references/contracts/accordion.md +30 -0
  14. package/skills/monkey-mini-app/references/contracts/activity-feed.md +12 -2
  15. package/skills/monkey-mini-app/references/contracts/alert-dialog.md +38 -0
  16. package/skills/monkey-mini-app/references/contracts/alert.md +38 -0
  17. package/skills/monkey-mini-app/references/contracts/app-shell.md +2 -2
  18. package/skills/monkey-mini-app/references/contracts/aspect-ratio.md +25 -0
  19. package/skills/monkey-mini-app/references/contracts/attachment-gallery.md +12 -2
  20. package/skills/monkey-mini-app/references/contracts/attachment.md +35 -0
  21. package/skills/monkey-mini-app/references/contracts/autocomplete.md +12 -2
  22. package/skills/monkey-mini-app/references/contracts/avatar.md +24 -0
  23. package/skills/monkey-mini-app/references/contracts/badge.md +26 -0
  24. package/skills/monkey-mini-app/references/contracts/breadcrumb.md +33 -0
  25. package/skills/monkey-mini-app/references/contracts/bubble.md +30 -0
  26. package/skills/monkey-mini-app/references/contracts/button-group.md +36 -0
  27. package/skills/monkey-mini-app/references/contracts/button.md +26 -0
  28. package/skills/monkey-mini-app/references/contracts/calendar.md +20 -0
  29. package/skills/monkey-mini-app/references/contracts/card.md +41 -0
  30. package/skills/monkey-mini-app/references/contracts/cascader.md +12 -2
  31. package/skills/monkey-mini-app/references/contracts/chart.md +32 -0
  32. package/skills/monkey-mini-app/references/contracts/checkbox.md +19 -0
  33. package/skills/monkey-mini-app/references/contracts/code-block.md +20 -2
  34. package/skills/monkey-mini-app/references/contracts/code-editor.md +30 -4
  35. package/skills/monkey-mini-app/references/contracts/collapsible.md +21 -0
  36. package/skills/monkey-mini-app/references/contracts/color-picker.md +12 -2
  37. package/skills/monkey-mini-app/references/contracts/combobox.md +34 -0
  38. package/skills/monkey-mini-app/references/contracts/command.md +41 -0
  39. package/skills/monkey-mini-app/references/contracts/comment-thread.md +12 -2
  40. package/skills/monkey-mini-app/references/contracts/commit-graph.md +50 -0
  41. package/skills/monkey-mini-app/references/contracts/confirm-dialog.md +20 -2
  42. package/skills/monkey-mini-app/references/contracts/context-menu.md +41 -0
  43. package/skills/monkey-mini-app/references/contracts/copyable.md +12 -2
  44. package/skills/monkey-mini-app/references/contracts/currency-input.md +12 -2
  45. package/skills/monkey-mini-app/references/contracts/dashboard-shell.md +41 -0
  46. package/skills/monkey-mini-app/references/contracts/data-grid.md +13 -6
  47. package/skills/monkey-mini-app/references/contracts/date-picker.md +20 -2
  48. package/skills/monkey-mini-app/references/contracts/date-range-picker.md +10 -2
  49. package/skills/monkey-mini-app/references/contracts/date-time-picker.md +20 -2
  50. package/skills/monkey-mini-app/references/contracts/date-time-range-picker.md +20 -2
  51. package/skills/monkey-mini-app/references/contracts/description-list.md +12 -2
  52. package/skills/monkey-mini-app/references/contracts/detail-panel.md +10 -2
  53. package/skills/monkey-mini-app/references/contracts/dialog.md +44 -0
  54. package/skills/monkey-mini-app/references/contracts/diff-viewer.md +21 -2
  55. package/skills/monkey-mini-app/references/contracts/donut-chart.md +14 -2
  56. package/skills/monkey-mini-app/references/contracts/drawer.md +29 -0
  57. package/skills/monkey-mini-app/references/contracts/dropdown-menu.md +49 -0
  58. package/skills/monkey-mini-app/references/contracts/duration-input.md +20 -2
  59. package/skills/monkey-mini-app/references/contracts/empty.md +40 -0
  60. package/skills/monkey-mini-app/references/contracts/env-badge.md +12 -2
  61. package/skills/monkey-mini-app/references/contracts/env-table.md +46 -0
  62. package/skills/monkey-mini-app/references/contracts/event-calendar.md +28 -20
  63. package/skills/monkey-mini-app/references/contracts/field.md +34 -0
  64. package/skills/monkey-mini-app/references/contracts/file-dropzone.md +20 -2
  65. package/skills/monkey-mini-app/references/contracts/file-tree.md +12 -2
  66. package/skills/monkey-mini-app/references/contracts/filter-bar.md +2 -2
  67. package/skills/monkey-mini-app/references/contracts/form-sheet.md +51 -0
  68. package/skills/monkey-mini-app/references/contracts/gantt.md +20 -2
  69. package/skills/monkey-mini-app/references/contracts/gauge.md +14 -2
  70. package/skills/monkey-mini-app/references/contracts/hover-card.md +21 -0
  71. package/skills/monkey-mini-app/references/contracts/input-group.md +24 -0
  72. package/skills/monkey-mini-app/references/contracts/input.md +33 -0
  73. package/skills/monkey-mini-app/references/contracts/item.md +36 -0
  74. package/skills/monkey-mini-app/references/contracts/jira-wiki.md +3 -4
  75. package/skills/monkey-mini-app/references/contracts/jql-input.md +15 -8
  76. package/skills/monkey-mini-app/references/contracts/json-viewer.md +20 -2
  77. package/skills/monkey-mini-app/references/contracts/kanban-issue-panel.md +12 -2
  78. package/skills/monkey-mini-app/references/contracts/kanban.md +10 -2
  79. package/skills/monkey-mini-app/references/contracts/kbd.md +20 -0
  80. package/skills/monkey-mini-app/references/contracts/label.md +33 -0
  81. package/skills/monkey-mini-app/references/contracts/list-detail.md +46 -0
  82. package/skills/monkey-mini-app/references/contracts/log-viewer.md +45 -4
  83. package/skills/monkey-mini-app/references/contracts/markdown-editor.md +20 -2
  84. package/skills/monkey-mini-app/references/contracts/markdown.md +12 -2
  85. package/skills/monkey-mini-app/references/contracts/marker.md +30 -0
  86. package/skills/monkey-mini-app/references/contracts/menubar.md +34 -0
  87. package/skills/monkey-mini-app/references/contracts/message-scroller.md +24 -0
  88. package/skills/monkey-mini-app/references/contracts/message.md +24 -0
  89. package/skills/monkey-mini-app/references/contracts/mini-calendar.md +20 -2
  90. package/skills/monkey-mini-app/references/contracts/native-select.md +21 -0
  91. package/skills/monkey-mini-app/references/contracts/navigation-menu.md +27 -0
  92. package/skills/monkey-mini-app/references/contracts/notification-center.md +12 -2
  93. package/skills/monkey-mini-app/references/contracts/number-field.md +20 -2
  94. package/skills/monkey-mini-app/references/contracts/page-header.md +2 -2
  95. package/skills/monkey-mini-app/references/contracts/pagination.md +33 -0
  96. package/skills/monkey-mini-app/references/contracts/password-field.md +12 -2
  97. package/skills/monkey-mini-app/references/contracts/phone-input.md +12 -2
  98. package/skills/monkey-mini-app/references/contracts/popover.md +32 -0
  99. package/skills/monkey-mini-app/references/contracts/progress-ring.md +14 -2
  100. package/skills/monkey-mini-app/references/contracts/progress.md +39 -0
  101. package/skills/monkey-mini-app/references/contracts/questionnaire.md +33 -0
  102. package/skills/monkey-mini-app/references/contracts/radar-chart.md +14 -2
  103. package/skills/monkey-mini-app/references/contracts/radio-group.md +20 -0
  104. package/skills/monkey-mini-app/references/contracts/rating.md +12 -2
  105. package/skills/monkey-mini-app/references/contracts/relative-date-picker.md +20 -2
  106. package/skills/monkey-mini-app/references/contracts/request-inspector.md +12 -2
  107. package/skills/monkey-mini-app/references/contracts/resizable.md +29 -0
  108. package/skills/monkey-mini-app/references/contracts/reveal.md +31 -0
  109. package/skills/monkey-mini-app/references/contracts/rich-text-editor.md +14 -2
  110. package/skills/monkey-mini-app/references/contracts/run-timeline.md +20 -2
  111. package/skills/monkey-mini-app/references/contracts/scroll-area.md +20 -0
  112. package/skills/monkey-mini-app/references/contracts/scrollspy.md +20 -2
  113. package/skills/monkey-mini-app/references/contracts/search-input.md +12 -2
  114. package/skills/monkey-mini-app/references/contracts/select.md +36 -0
  115. package/skills/monkey-mini-app/references/contracts/separator.md +27 -0
  116. package/skills/monkey-mini-app/references/contracts/settings-split.md +53 -0
  117. package/skills/monkey-mini-app/references/contracts/severity-chip.md +12 -2
  118. package/skills/monkey-mini-app/references/contracts/sheet.md +34 -0
  119. package/skills/monkey-mini-app/references/contracts/sidebar.md +42 -0
  120. package/skills/monkey-mini-app/references/contracts/skeleton.md +33 -0
  121. package/skills/monkey-mini-app/references/contracts/slider-range.md +12 -2
  122. package/skills/monkey-mini-app/references/contracts/slider.md +25 -0
  123. package/skills/monkey-mini-app/references/contracts/sortable-list.md +20 -2
  124. package/skills/monkey-mini-app/references/contracts/sparkline.md +13 -2
  125. package/skills/monkey-mini-app/references/contracts/spinner.md +31 -0
  126. package/skills/monkey-mini-app/references/contracts/stacked-bar-chart.md +17 -2
  127. package/skills/monkey-mini-app/references/contracts/stat-card.md +2 -2
  128. package/skills/monkey-mini-app/references/contracts/status-badge.md +2 -2
  129. package/skills/monkey-mini-app/references/contracts/stepper-item.md +39 -0
  130. package/skills/monkey-mini-app/references/contracts/stepper.md +38 -11
  131. package/skills/monkey-mini-app/references/contracts/switch.md +25 -0
  132. package/skills/monkey-mini-app/references/contracts/table-page.md +41 -0
  133. package/skills/monkey-mini-app/references/contracts/table.md +42 -0
  134. package/skills/monkey-mini-app/references/contracts/tabs.md +31 -0
  135. package/skills/monkey-mini-app/references/contracts/tag-input.md +12 -2
  136. package/skills/monkey-mini-app/references/contracts/terminal.md +13 -2
  137. package/skills/monkey-mini-app/references/contracts/test-step-list.md +12 -2
  138. package/skills/monkey-mini-app/references/contracts/textarea.md +25 -0
  139. package/skills/monkey-mini-app/references/contracts/time-picker.md +18 -2
  140. package/skills/monkey-mini-app/references/contracts/time-range-picker.md +20 -2
  141. package/skills/monkey-mini-app/references/contracts/time-wheel.md +6 -2
  142. package/skills/monkey-mini-app/references/contracts/timeline.md +20 -2
  143. package/skills/monkey-mini-app/references/contracts/timezone-select.md +20 -2
  144. package/skills/monkey-mini-app/references/contracts/toast.md +39 -0
  145. package/skills/monkey-mini-app/references/contracts/toggle-group.md +28 -0
  146. package/skills/monkey-mini-app/references/contracts/toggle.md +26 -0
  147. package/skills/monkey-mini-app/references/contracts/tooltip.md +30 -0
  148. package/skills/monkey-mini-app/references/contracts/transfer.md +12 -2
  149. package/skills/monkey-mini-app/references/contracts/tree-view.md +20 -2
  150. package/skills/monkey-mini-app/references/contracts/trend-card.md +12 -2
  151. package/skills/monkey-mini-app/references/contracts/user-picker.md +12 -2
  152. package/skills/monkey-mini-app/references/contracts/wizard-shell.md +56 -0
  153. package/skills/monkey-mini-app/references/ctx.md +123 -53
  154. package/skills/monkey-mini-app/references/eval.md +115 -0
  155. package/skills/monkey-mini-app/references/examples/alert/alert-01.tsx +17 -0
  156. package/skills/monkey-mini-app/references/examples/aspect-ratio/aspect-ratio-01.tsx +16 -0
  157. package/skills/monkey-mini-app/references/examples/attachment/attachment-01.tsx +19 -0
  158. package/skills/monkey-mini-app/references/examples/breadcrumb/breadcrumb-01.tsx +31 -0
  159. package/skills/monkey-mini-app/references/examples/bubble/bubble-01.tsx +16 -0
  160. package/skills/monkey-mini-app/references/examples/button-group/button-group-01.tsx +23 -0
  161. package/skills/monkey-mini-app/references/examples/card/card-01.tsx +19 -0
  162. package/skills/monkey-mini-app/references/examples/charts-blocks.md +15 -0
  163. package/skills/monkey-mini-app/references/examples/code-block/code-block-01.tsx +14 -0
  164. package/skills/monkey-mini-app/references/examples/code-editor/code-editor-01.tsx +15 -0
  165. package/skills/monkey-mini-app/references/examples/command/command-01.tsx +30 -0
  166. package/skills/monkey-mini-app/references/examples/confirm-dialog/confirm-dialog-01.tsx +33 -0
  167. package/skills/monkey-mini-app/references/examples/context-menu/context-menu-01.tsx +29 -0
  168. package/skills/monkey-mini-app/references/examples/dashboard-shell/dashboard-shell-01.tsx +78 -0
  169. package/skills/monkey-mini-app/references/examples/data-grid/data-grid-01.tsx +34 -0
  170. package/skills/monkey-mini-app/references/examples/data-grid/data-grid-02.tsx +88 -0
  171. package/skills/monkey-mini-app/references/examples/date-picker/date-picker-01.tsx +14 -0
  172. package/skills/monkey-mini-app/references/examples/date-range-picker/date-range-picker-01.tsx +14 -0
  173. package/skills/monkey-mini-app/references/examples/date-time-picker/date-time-picker-01.tsx +16 -0
  174. package/skills/monkey-mini-app/references/examples/date-time-range-picker/date-time-range-picker-01.tsx +15 -0
  175. package/skills/monkey-mini-app/references/examples/detail-panel/detail-panel-01.tsx +21 -0
  176. package/skills/monkey-mini-app/references/examples/dialog/dialog-01.tsx +30 -0
  177. package/skills/monkey-mini-app/references/examples/diff-viewer/diff-viewer-01.tsx +10 -0
  178. package/skills/monkey-mini-app/references/examples/dropdown-menu/dropdown-menu-01.tsx +31 -0
  179. package/skills/monkey-mini-app/references/examples/duration-input/duration-input-01.tsx +20 -0
  180. package/skills/monkey-mini-app/references/examples/editors.md +11 -0
  181. package/skills/monkey-mini-app/references/examples/empty/empty-01.tsx +19 -0
  182. package/skills/monkey-mini-app/references/examples/event-calendar/event-calendar-01.tsx +53 -0
  183. package/skills/monkey-mini-app/references/examples/file-dropzone/file-dropzone-01.tsx +14 -0
  184. package/skills/monkey-mini-app/references/examples/form-sheet/form-sheet-01.tsx +85 -0
  185. package/skills/monkey-mini-app/references/examples/forms.md +16 -0
  186. package/skills/monkey-mini-app/references/examples/gantt/gantt-01.tsx +29 -0
  187. package/skills/monkey-mini-app/references/examples/input/input-01.tsx +10 -0
  188. package/skills/monkey-mini-app/references/examples/item/item-01.tsx +19 -0
  189. package/skills/monkey-mini-app/references/examples/jql-input/jql-input-01.tsx +33 -0
  190. package/skills/monkey-mini-app/references/examples/json-viewer/json-viewer-01.tsx +10 -0
  191. package/skills/monkey-mini-app/references/examples/kanban/kanban-01.tsx +60 -0
  192. package/skills/monkey-mini-app/references/examples/label/label-01.tsx +10 -0
  193. package/skills/monkey-mini-app/references/examples/list-detail/list-detail-01.tsx +117 -0
  194. package/skills/monkey-mini-app/references/examples/log-viewer/log-viewer-01.tsx +20 -0
  195. package/skills/monkey-mini-app/references/examples/markdown-editor/markdown-editor-01.tsx +18 -0
  196. package/skills/monkey-mini-app/references/examples/marker/marker-01.tsx +16 -0
  197. package/skills/monkey-mini-app/references/examples/mini-calendar/mini-calendar-01.tsx +14 -0
  198. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-01.tsx +20 -0
  199. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-02.tsx +32 -0
  200. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-03.tsx +47 -0
  201. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-04.tsx +20 -0
  202. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-05.tsx +24 -0
  203. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-06.tsx +89 -0
  204. package/skills/monkey-mini-app/references/examples/misc-editors/misc-editors-01.tsx +114 -0
  205. package/skills/monkey-mini-app/references/examples/misc-editors/misc-editors-02.tsx +33 -0
  206. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-01.tsx +22 -0
  207. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-02.tsx +37 -0
  208. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-03.tsx +42 -0
  209. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-04.tsx +25 -0
  210. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-05.tsx +27 -0
  211. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-06.tsx +33 -0
  212. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-07.tsx +44 -0
  213. package/skills/monkey-mini-app/references/examples/misc-overlays/misc-overlays-01.tsx +43 -0
  214. package/skills/monkey-mini-app/references/examples/misc-overlays/misc-overlays-02.tsx +38 -0
  215. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-01.tsx +21 -0
  216. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-02.tsx +52 -0
  217. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-03.tsx +44 -0
  218. package/skills/monkey-mini-app/references/examples/number-field/number-field-01.tsx +22 -0
  219. package/skills/monkey-mini-app/references/examples/overlays.md +11 -0
  220. package/skills/monkey-mini-app/references/examples/pagination/pagination-01.tsx +51 -0
  221. package/skills/monkey-mini-app/references/examples/primitives.md +12 -0
  222. package/skills/monkey-mini-app/references/examples/progress/progress-01.tsx +10 -0
  223. package/skills/monkey-mini-app/references/examples/relative-date-picker/relative-date-picker-01.tsx +19 -0
  224. package/skills/monkey-mini-app/references/examples/rich-text-editor/rich-text-editor-01.tsx +15 -0
  225. package/skills/monkey-mini-app/references/examples/run-timeline/run-timeline-01.tsx +17 -0
  226. package/skills/monkey-mini-app/references/examples/scrollspy/scrollspy-01.tsx +29 -0
  227. package/skills/monkey-mini-app/references/examples/separator/separator-01.tsx +10 -0
  228. package/skills/monkey-mini-app/references/examples/settings-split/settings-split-01.tsx +84 -0
  229. package/skills/monkey-mini-app/references/examples/shared/jira-wiki-sample.ts +38 -0
  230. package/skills/monkey-mini-app/references/examples/skeleton/skeleton-01.tsx +10 -0
  231. package/skills/monkey-mini-app/references/examples/slider/slider-01.tsx +22 -0
  232. package/skills/monkey-mini-app/references/examples/sortable-list/sortable-list-01.tsx +18 -0
  233. package/skills/monkey-mini-app/references/examples/spinner/spinner-01.tsx +10 -0
  234. package/skills/monkey-mini-app/references/examples/stepper/stepper-01.tsx +41 -0
  235. package/skills/monkey-mini-app/references/examples/table/table-01.tsx +25 -0
  236. package/skills/monkey-mini-app/references/examples/table-page/table-page-01.tsx +103 -0
  237. package/skills/monkey-mini-app/references/examples/time-picker/time-picker-01.tsx +19 -0
  238. package/skills/monkey-mini-app/references/examples/time-range-picker/time-range-picker-01.tsx +14 -0
  239. package/skills/monkey-mini-app/references/examples/timeline/timeline-01.tsx +18 -0
  240. package/skills/monkey-mini-app/references/examples/timezone-select/timezone-select-01.tsx +15 -0
  241. package/skills/monkey-mini-app/references/examples/toggle/toggle-01.tsx +20 -0
  242. package/skills/monkey-mini-app/references/examples/toggle-group/toggle-group-01.tsx +22 -0
  243. package/skills/monkey-mini-app/references/examples/tree-view/tree-view-01.tsx +25 -0
  244. package/skills/monkey-mini-app/references/examples/wizard-shell/wizard-shell-01.tsx +58 -0
  245. package/skills/monkey-mini-app/references/history.md +23 -7
  246. package/skills/monkey-mini-app/references/icons.md +99 -69
  247. package/skills/monkey-mini-app/references/llm-json.md +39 -26
  248. package/skills/monkey-mini-app/references/loader.md +47 -20
  249. package/skills/monkey-mini-app/references/looks/aurora-bento.md +88 -0
  250. package/skills/monkey-mini-app/references/looks/desk-split.md +89 -0
  251. package/skills/monkey-mini-app/references/looks/editorial.md +78 -0
  252. package/skills/monkey-mini-app/references/looks/glass-island.md +90 -0
  253. package/skills/monkey-mini-app/references/looks/index.md +18 -0
  254. package/skills/monkey-mini-app/references/looks/signage.md +74 -0
  255. package/skills/monkey-mini-app/references/looks/tape.md +22 -0
  256. package/skills/monkey-mini-app/references/looks/terminal.md +88 -0
  257. package/skills/monkey-mini-app/references/looks/void.md +22 -0
  258. package/skills/monkey-mini-app/references/styling.md +189 -0
  259. package/skills/monkey-mini-app/references/test.md +12 -12
  260. package/skills/monkey-mini-app/references/theme.md +197 -0
  261. package/skills/monkey-mini-app/references/tools.md +12 -12
  262. package/skills/monkey-mini-app/references/troubleshoot.md +165 -12
  263. package/skills/monkey-mini-app/templates/README.md +33 -21
  264. package/skills/monkey-mini-app/templates/{jira → board}/main.api.ts +11 -11
  265. package/skills/monkey-mini-app/templates/board/manifest.json +8 -0
  266. package/skills/monkey-mini-app/templates/board/theme.css +46 -0
  267. package/skills/monkey-mini-app/templates/board/ui.tsx +546 -0
  268. package/skills/monkey-mini-app/templates/chores/main.api.ts +35 -0
  269. package/skills/monkey-mini-app/templates/chores/manifest.json +8 -0
  270. package/skills/monkey-mini-app/templates/chores/theme.css +46 -0
  271. package/skills/monkey-mini-app/templates/chores/ui.tsx +117 -0
  272. package/skills/monkey-mini-app/templates/minimal/main.api.ts +5 -5
  273. package/skills/monkey-mini-app/templates/minimal/manifest.json +1 -2
  274. package/skills/monkey-mini-app/templates/minimal/ui.tsx +17 -8
  275. package/skills/monkey-mini-app/templates/radar/api/scan.ts +79 -0
  276. package/skills/monkey-mini-app/templates/radar/main.api.ts +29 -0
  277. package/skills/monkey-mini-app/templates/radar/manifest.json +8 -0
  278. package/skills/monkey-mini-app/templates/radar/shared/events.ts +25 -0
  279. package/skills/monkey-mini-app/templates/{insights/lib → radar/shared}/sample.ts +1 -1
  280. package/skills/monkey-mini-app/templates/radar/theme.css +47 -0
  281. package/skills/monkey-mini-app/templates/radar/ui/brief.tsx +31 -0
  282. package/skills/monkey-mini-app/templates/radar/ui.tsx +131 -0
  283. package/skills/monkey-mini-app/templates/runner/main.api.ts +91 -0
  284. package/skills/monkey-mini-app/templates/runner/manifest.json +8 -0
  285. package/skills/monkey-mini-app/templates/runner/shared/events.ts +14 -0
  286. package/skills/monkey-mini-app/templates/runner/theme.css +46 -0
  287. package/skills/monkey-mini-app/templates/runner/ui.tsx +213 -0
  288. package/skills/monkey-mini-app/templates/sheets/main.api.ts +276 -0
  289. package/skills/monkey-mini-app/templates/sheets/manifest.json +8 -0
  290. package/skills/monkey-mini-app/templates/sheets/theme.css +46 -0
  291. package/skills/monkey-mini-app/templates/sheets/ui.tsx +419 -0
  292. package/skills/monkey-mini-app/templates/{todo → today}/main.api.ts +8 -8
  293. package/skills/monkey-mini-app/templates/today/manifest.json +8 -0
  294. package/skills/monkey-mini-app/templates/today/theme.css +45 -0
  295. package/skills/monkey-mini-app/templates/today/ui/item-row.tsx +25 -0
  296. package/skills/monkey-mini-app/templates/today/ui.tsx +406 -0
  297. package/skills/monkey-mini-app/templates/{monitor → watch}/main.api.ts +8 -8
  298. package/skills/monkey-mini-app/templates/watch/manifest.json +8 -0
  299. package/skills/monkey-mini-app/templates/watch/ui.tsx +187 -0
  300. package/skills/monkey-mini-app/tsconfig.json +31 -0
  301. package/skills/monkey-mini-app/types/cdn.d.ts +1 -0
  302. package/tsup.config.ts +1 -0
  303. package/skills/monkey-mini-app/templates/agentrun/main.api.ts +0 -78
  304. package/skills/monkey-mini-app/templates/agentrun/manifest.json +0 -9
  305. package/skills/monkey-mini-app/templates/agentrun/ui.tsx +0 -125
  306. package/skills/monkey-mini-app/templates/insights/main.api.ts +0 -101
  307. package/skills/monkey-mini-app/templates/insights/manifest.json +0 -9
  308. package/skills/monkey-mini-app/templates/insights/ui.tsx +0 -138
  309. package/skills/monkey-mini-app/templates/jira/manifest.json +0 -9
  310. package/skills/monkey-mini-app/templates/jira/ui.tsx +0 -318
  311. package/skills/monkey-mini-app/templates/monitor/manifest.json +0 -9
  312. package/skills/monkey-mini-app/templates/monitor/ui.tsx +0 -176
  313. package/skills/monkey-mini-app/templates/review/main.api.ts +0 -68
  314. package/skills/monkey-mini-app/templates/review/manifest.json +0 -9
  315. package/skills/monkey-mini-app/templates/review/ui.tsx +0 -159
  316. package/skills/monkey-mini-app/templates/todo/manifest.json +0 -8
  317. package/skills/monkey-mini-app/templates/todo/ui.tsx +0 -177
@@ -0,0 +1,419 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+
3
+ import {
4
+ Badge,
5
+ Button,
6
+ Card,
7
+ CardContent,
8
+ CardDescription,
9
+ CardHeader,
10
+ CardTitle,
11
+ type ColumnDef,
12
+ DataGrid,
13
+ FileDropzone,
14
+ Icon,
15
+ IlluEmpty,
16
+ ListDetail,
17
+ Spinner,
18
+ StatCard,
19
+ Tabs,
20
+ TabsContent,
21
+ TabsList,
22
+ TabsTrigger,
23
+ useApp,
24
+ } from "@monkey-mini-app/ui";
25
+
26
+ type ColumnStat = {
27
+ header: string;
28
+ numeric: boolean;
29
+ count: number;
30
+ min?: number;
31
+ max?: number;
32
+ total?: number;
33
+ avg?: number;
34
+ };
35
+
36
+ type Sheet = {
37
+ name: string;
38
+ headers: string[];
39
+ rows: Record<string, string | number>[];
40
+ rowCount: number;
41
+ columns: ColumnStat[];
42
+ };
43
+
44
+ type Report = {
45
+ id: string;
46
+ fileName: string;
47
+ createdAt: number;
48
+ sheetCount: number;
49
+ rowCount: number;
50
+ digest?: { headline: string; bullets: string[] };
51
+ };
52
+
53
+ /**
54
+ * ⭐ The browser hands us bytes; the workbook is parsed in the **backend** by exceljs.
55
+ * A chat-generated HTML page would need SheetJS in the browser and would stop at whatever
56
+ * fits in one file — here the same bytes reach a Node client with the full format.
57
+ */
58
+ async function readAsBase64(file: File): Promise<string> {
59
+ const bytes = new Uint8Array(await file.arrayBuffer());
60
+ let binary = "";
61
+ const chunk = 0x8000;
62
+ for (let i = 0; i < bytes.length; i += chunk) {
63
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
64
+ }
65
+ return btoa(binary);
66
+ }
67
+
68
+ // ⭐ Look: desk-split — walnut desk, one warm lamp, ink only ever lands on paper.
69
+ // Wood grain: fine + wide stripe bands; lamp pool from the palette's amber primary;
70
+ // vignette pulls the corners down. All token-derived, no colour literals.
71
+ const DESK =
72
+ "repeating-linear-gradient(90deg, color-mix(in oklch, var(--foreground) 5%, transparent) 0 2px, transparent 2px 26px)," +
73
+ "repeating-linear-gradient(90deg, color-mix(in oklch, var(--foreground) 8%, transparent) 0 1px, transparent 1px 96px)," +
74
+ "radial-gradient(620px 320px at 12% -12%, color-mix(in oklch, var(--primary) 42%, transparent), transparent 70%)," +
75
+ "radial-gradient(560px 620px at 64% 116%, color-mix(in oklch, var(--foreground) 16%, transparent), transparent 72%)";
76
+
77
+ // One sheet of cream desk-paper: hairline edge, contact + lift shadow, a light along the
78
+ // top edge. Inline because Tailwind collapses the extra inset layer of arbitrary shadows.
79
+ const PAPER = {
80
+ backgroundColor: "var(--card)",
81
+ color: "var(--card-foreground)",
82
+ boxShadow:
83
+ "0 1px 2px color-mix(in oklch, var(--foreground) 24%, transparent)," +
84
+ "0 18px 44px -18px var(--shadow)," +
85
+ "inset 0 1px 0 color-mix(in oklch, var(--card) 72%, transparent)",
86
+ borderColor: "color-mix(in oklch, var(--foreground) 12%, transparent)",
87
+ } as const;
88
+
89
+ export default function Ui() {
90
+ const { call } = useApp();
91
+ const [history, setHistory] = useState<Report[]>([]);
92
+ const [report, setReport] = useState<(Report & { sheets?: Sheet[] }) | null>(
93
+ null,
94
+ );
95
+ const [sheet, setSheet] = useState("");
96
+ const [busy, setBusy] = useState<"idle" | "reading" | "digesting">("idle");
97
+ const [error, setError] = useState("");
98
+
99
+ const refresh = useCallback(async () => {
100
+ setHistory(((await call("list")) ?? []) as Report[]);
101
+ }, [call]);
102
+
103
+ useEffect(() => {
104
+ void refresh();
105
+ }, [refresh]);
106
+
107
+ const open = async (id: string) => {
108
+ setError("");
109
+ try {
110
+ const full = (await call("get", { id })) as Report & { sheets: Sheet[] };
111
+ setReport(full);
112
+ setSheet(full.sheets?.[0]?.name ?? "");
113
+ } catch (e) {
114
+ setError(e instanceof Error ? e.message : String(e));
115
+ }
116
+ };
117
+
118
+ const onFiles = async (files: File[]) => {
119
+ const file = files[0];
120
+ if (!file) return;
121
+ if (!/\.xlsx$/i.test(file.name)) {
122
+ setError("只支持 .xlsx(旧版 .xls 请先另存为 .xlsx)");
123
+ return;
124
+ }
125
+ setError("");
126
+ setBusy("reading");
127
+ try {
128
+ const base64 = await readAsBase64(file);
129
+ const parsed = (await call("ingest", {
130
+ fileName: file.name,
131
+ base64,
132
+ })) as Report & {
133
+ sheets: Sheet[];
134
+ };
135
+ setReport(parsed);
136
+ setSheet(parsed.sheets?.[0]?.name ?? "");
137
+ await refresh();
138
+ } catch (e) {
139
+ setError(e instanceof Error ? e.message : String(e));
140
+ } finally {
141
+ setBusy("idle");
142
+ }
143
+ };
144
+
145
+ const runDigest = async () => {
146
+ if (!report) return;
147
+ setBusy("digesting");
148
+ setError("");
149
+ try {
150
+ const digest = (await call("digest", { id: report.id })) as {
151
+ headline: string;
152
+ bullets: string[];
153
+ };
154
+ setReport({ ...report, digest });
155
+ await refresh();
156
+ } catch (e) {
157
+ setError(e instanceof Error ? e.message : String(e));
158
+ } finally {
159
+ setBusy("idle");
160
+ }
161
+ };
162
+
163
+ const forget = async (id: string) => {
164
+ await call("remove", { id });
165
+ if (report?.id === id) setReport(null);
166
+ await refresh();
167
+ };
168
+
169
+ // ⭐ key: ListDetail shows `empty` only when `detail` is literally undefined. Passing an
170
+ // always-present wrapper div swallows the drop target, and the app opens on a blank pane.
171
+ const hasRecord = Boolean(report) || busy === "reading" || Boolean(error);
172
+
173
+ const sheets = report?.sheets ?? [];
174
+ const active = useMemo(
175
+ () => sheets.find((s) => s.name === sheet) ?? sheets[0],
176
+ [sheets, sheet],
177
+ );
178
+
179
+ // ⭐ Columns come from the file, so the grid is built at runtime — no fixed schema.
180
+ const columns = useMemo<ColumnDef<Record<string, string | number>>[]>(() => {
181
+ if (!active) return [];
182
+ return active.headers.map((h) => ({
183
+ accessorKey: h,
184
+ header: h,
185
+ meta: { sort: true, search: "text" },
186
+ }));
187
+ }, [active]);
188
+
189
+ const numeric = active?.columns.filter((c) => c.numeric) ?? [];
190
+
191
+ return (
192
+ // ⭐ Look: desk-split — the desk is the palette's walnut `bg-background`; ink only ever
193
+ // lands on paper (`bg-card`). One long sheet: a letterhead strip on top, the ListDetail
194
+ // binder below it. The papers stay cream in BOTH modes — lamp-lit paper on a dark desk
195
+ // is the look; dark papers on wood read as mud.
196
+ <div className="bg-background relative flex h-full min-h-0 flex-col overflow-hidden">
197
+ <div
198
+ aria-hidden
199
+ className="pointer-events-none absolute inset-0"
200
+ style={{ backgroundImage: DESK }}
201
+ />
202
+ <header
203
+ style={PAPER}
204
+ className="relative mx-5 mt-4 rounded-t-2xl border border-b-0 px-5 py-3"
205
+ >
206
+ <div className="flex items-center gap-3">
207
+ <div className="min-w-0 flex-1">
208
+ <h1 className="font-serif text-lg font-semibold tracking-tight">
209
+ 表格台
210
+ </h1>
211
+ <p className="text-muted-foreground text-xs">
212
+ Excel 在本机解析,数值汇总后交给宿主模型出结论
213
+ </p>
214
+ </div>
215
+ {report ? (
216
+ <Button
217
+ variant="outline"
218
+ size="sm"
219
+ onClick={() => void forget(report.id)}
220
+ >
221
+ <Icon.Trash2 />
222
+ 删除
223
+ </Button>
224
+ ) : null}
225
+ <Button
226
+ size="sm"
227
+ disabled={!report || busy !== "idle"}
228
+ onClick={() => void runDigest()}
229
+ >
230
+ {busy === "digesting" ? (
231
+ <Spinner className="size-3.5" />
232
+ ) : (
233
+ <Icon.Sparkles />
234
+ )}
235
+ 生成摘要
236
+ </Button>
237
+ </div>
238
+ </header>
239
+ <div className="relative mx-5 mb-5 flex min-h-0 flex-1">
240
+ <div
241
+ style={PAPER}
242
+ className="flex h-full min-h-0 w-full overflow-hidden rounded-b-2xl border border-t-0"
243
+ >
244
+ <ListDetail
245
+ toolbar={
246
+ <div className="text-muted-foreground flex items-center gap-2 border-b px-3 py-2 text-xs font-medium tracking-wide uppercase">
247
+ <Icon.History className="size-3.5" />
248
+ 历史报表
249
+ <Badge variant="outline" className="ml-auto normal-case">
250
+ {history.length}
251
+ </Badge>
252
+ </div>
253
+ }
254
+ list={
255
+ <ul className="divide-border divide-y">
256
+ {history.map((r) => (
257
+ <li key={r.id}>
258
+ <button
259
+ type="button"
260
+ onClick={() => void open(r.id)}
261
+ className={
262
+ "hover:bg-accent flex w-full flex-col items-start gap-0.5 px-3 py-2 text-left text-xs " +
263
+ (report?.id === r.id ? "bg-accent" : "")
264
+ }
265
+ >
266
+ <span className="line-clamp-1 font-medium">
267
+ {r.fileName}
268
+ </span>
269
+ <span className="text-muted-foreground">
270
+ {r.sheetCount} 表 · {r.rowCount} 行
271
+ {r.digest ? " · 已摘要" : ""}
272
+ </span>
273
+ </button>
274
+ </li>
275
+ ))}
276
+ </ul>
277
+ }
278
+ detail={
279
+ hasRecord ? (
280
+ <div className="flex flex-col gap-4 p-4">
281
+ {error ? (
282
+ <div className="text-destructive border-destructive/40 bg-destructive/10 flex items-start gap-2 rounded-lg border px-3 py-2 text-sm">
283
+ <Icon.AlertCircle className="mt-0.5 size-4 shrink-0" />
284
+ <span>{error}</span>
285
+ </div>
286
+ ) : null}
287
+ {busy === "reading" ? (
288
+ <Card>
289
+ <CardContent className="flex items-center gap-2 py-6 text-sm">
290
+ <Spinner className="size-4" />
291
+ 正在读取工作簿…
292
+ </CardContent>
293
+ </Card>
294
+ ) : null}
295
+
296
+ {report && busy !== "reading" ? (
297
+ <>
298
+ <div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
299
+ <StatCard title="工作表" value={report.sheetCount} />
300
+ <StatCard title="数据行" value={report.rowCount} />
301
+ <StatCard title="数值列" value={numeric.length} />
302
+ <StatCard
303
+ title="文件"
304
+ value={
305
+ <span className="text-base">{report.fileName}</span>
306
+ }
307
+ delta={new Date(
308
+ report.createdAt,
309
+ ).toLocaleDateString()}
310
+ />
311
+ </div>
312
+
313
+ {report.digest ? (
314
+ <Card>
315
+ <CardHeader>
316
+ <CardTitle className="flex items-center gap-2 text-base">
317
+ <Icon.Sparkles className="text-primary size-4" />
318
+ {report.digest.headline}
319
+ </CardTitle>
320
+ <CardDescription>
321
+ 由宿主模型基于整表的数值汇总生成
322
+ </CardDescription>
323
+ </CardHeader>
324
+ <CardContent>
325
+ <ul className="flex flex-col gap-1.5 text-sm">
326
+ {report.digest.bullets.map((b, i) => (
327
+ <li
328
+ key={i}
329
+ className="text-muted-foreground flex gap-2"
330
+ >
331
+ <span className="text-primary">·</span>
332
+ <span>{b}</span>
333
+ </li>
334
+ ))}
335
+ </ul>
336
+ </CardContent>
337
+ </Card>
338
+ ) : null}
339
+
340
+ {sheets.length > 0 ? (
341
+ <Tabs
342
+ value={active?.name ?? ""}
343
+ onValueChange={setSheet}
344
+ className="w-full"
345
+ >
346
+ <TabsList>
347
+ {sheets.map((s) => (
348
+ <TabsTrigger key={s.name} value={s.name}>
349
+ {s.name}
350
+ <Badge variant="secondary" className="ml-1.5">
351
+ {s.rowCount}
352
+ </Badge>
353
+ </TabsTrigger>
354
+ ))}
355
+ </TabsList>
356
+ {sheets.map((s) => (
357
+ <TabsContent
358
+ key={s.name}
359
+ value={s.name}
360
+ className="flex flex-col gap-3"
361
+ >
362
+ {s.columns.some((c) => c.numeric) ? (
363
+ <div className="border-border text-muted-foreground flex flex-wrap gap-x-4 gap-y-1 rounded-lg border px-3 py-2 text-xs">
364
+ {s.columns
365
+ .filter((c) => c.numeric)
366
+ .map((c) => (
367
+ <span key={c.header}>
368
+ <span className="text-foreground font-medium">
369
+ {c.header}
370
+ </span>
371
+ {" 合计 "}
372
+ {c.total}
373
+ {" · 均值 "}
374
+ {c.avg}
375
+ {" · 区间 "}
376
+ {c.min}–{c.max}
377
+ </span>
378
+ ))}
379
+ </div>
380
+ ) : null}
381
+ <DataGrid
382
+ columns={columns}
383
+ data={s.rows}
384
+ pageSize={12}
385
+ searchPlaceholder="搜索本表…"
386
+ />
387
+ {s.rowCount > s.rows.length ? (
388
+ <p className="text-muted-foreground text-xs">
389
+ 表格显示前 {s.rows.length}{" "}
390
+ 行;上面的合计/均值按全部 {s.rowCount}{" "}
391
+ 行计算。
392
+ </p>
393
+ ) : null}
394
+ </TabsContent>
395
+ ))}
396
+ </Tabs>
397
+ ) : null}
398
+ </>
399
+ ) : null}
400
+ </div>
401
+ ) : undefined
402
+ }
403
+ empty={
404
+ <div className="mx-auto w-full max-w-xl pt-6">
405
+ <FileDropzone onFiles={(fs) => void onFiles(fs)} />
406
+ <div className="text-muted-foreground mt-6 flex flex-col items-center gap-2 text-center text-sm">
407
+ <IlluEmpty className="w-36" />
408
+ 解析、汇总、摘要都在这台机器上完成,文件不会上传
409
+ </div>
410
+ </div>
411
+ }
412
+ mobileView={hasRecord ? "detail" : "list"}
413
+ onMobileBack={() => setReport(null)}
414
+ />
415
+ </div>
416
+ </div>
417
+ </div>
418
+ );
419
+ }
@@ -1,4 +1,4 @@
1
- import { defineDashboard } from "@monkeyagent/dashboard";
1
+ import { defineApp } from "@monkey-mini-app/api";
2
2
 
3
3
  type TodoItem = { id: string; title: string; done: boolean; createdAt: number };
4
4
  type Filter = "all" | "active" | "done";
@@ -7,8 +7,8 @@ function uid() {
7
7
  return "t_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
8
8
  }
9
9
 
10
- // ⭐ 关键:本地数据用 ctx.storage(单表 get/set);多表用 ctx.storage.table(name)
11
- // todo 用主表存"进行中的任务",把已完成的归档到第二张表体现分表。
10
+ // ⭐ key: local data uses ctx.storage (single-table get/set); for multiple tables use ctx.storage.table(name).
11
+ // todo keeps in-progress items in the main table and archives done items to a second table to demo sharding.
12
12
  async function loadItems(ctx): Promise<TodoItem[]> {
13
13
  const items = await ctx.storage.get("items");
14
14
  return Array.isArray(items) ? items : [];
@@ -21,9 +21,9 @@ function statsOf(items: TodoItem[]) {
21
21
  return { total: items.length, active: items.length - done, done };
22
22
  }
23
23
 
24
- export default defineDashboard({
25
- name: "待办",
26
- description: "本地待办:CRUD + 状态筛选 + 归档到第二张表",
24
+ export default defineApp({
25
+ name: "今日台子",
26
+ description: "打开就看见我的一屏:本地事项 + 筛选 + 归档",
27
27
  api: {
28
28
  async list(ctx, args?: { filter?: Filter }) {
29
29
  const all = await loadItems(ctx);
@@ -67,8 +67,8 @@ export default defineDashboard({
67
67
  await saveItems(ctx, items.filter((i) => !i.done));
68
68
  return { ok: true };
69
69
  },
70
- // ⭐ 关键:ctx.storage.table("archive") 是另一张独立表 —— 演示多表。
71
- // table() 返回与 storage 同样的 get/set/delete/clear
70
+ // ⭐ key: ctx.storage.table("archive") is a separate, independent table — demonstrates multi-table storage.
71
+ // table() returns the same get/set/delete/clear as storage.
72
72
  async archive(ctx) {
73
73
  const items = await loadItems(ctx);
74
74
  const done = items.filter((i) => i.done);
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "com.example.today",
3
+ "name": "今日台子",
4
+ "description": "打开就看见我的一屏,点进去是一条记录",
5
+ "version": "0.1.0",
6
+ "entry": "ui.tsx",
7
+ "acronym": "JT"
8
+ }
@@ -0,0 +1,45 @@
1
+ /* name: 玻璃岛屿 */
2
+ /* Light: haze grey-blue a step deeper than pure fog, white glass, soft floating orbs that
3
+ actually read. Dark: deep indigo. Radius large for liquid glass on big panes. */
4
+ :root[data-mode="light"] {
5
+ --bg: #d5e0ed;
6
+ --fg: #243044;
7
+ --surface: #ffffff;
8
+ --surface-fg: #243044;
9
+ --border: #c2d0e0;
10
+ --muted: #c8d5e6;
11
+ --muted-fg: #5a6b80;
12
+ --primary: #6b8ab8;
13
+ --primary-fg: #ffffff;
14
+ --secondary: #d0dbe8;
15
+ --secondary-fg: #243044;
16
+ --accent: #e4ebf4;
17
+ --accent-fg: #243044;
18
+ --destructive: #c63f4f;
19
+ --destructive-fg: #ffffff;
20
+ --ring: #6b8ab8;
21
+ --input: #b8c8da;
22
+ --radius: 28px;
23
+ --shadow: rgba(60, 85, 120, 0.18);
24
+ }
25
+ :root[data-mode="dark"] {
26
+ --bg: #0e1128;
27
+ --fg: #e9edff;
28
+ --surface: #21264c;
29
+ --surface-fg: #e9edff;
30
+ --border: #2e3566;
31
+ --muted: #1d2046;
32
+ --muted-fg: #a3b0e6;
33
+ --primary: #8b94fa;
34
+ --primary-fg: #12142c;
35
+ --secondary: #232757;
36
+ --secondary-fg: #e9edff;
37
+ --accent: #1d2046;
38
+ --accent-fg: #e9edff;
39
+ --destructive: #f97066;
40
+ --destructive-fg: #20120d;
41
+ --ring: #8b94fa;
42
+ --input: #2e3566;
43
+ --radius: 28px;
44
+ --shadow: rgba(0, 4, 24, 0.66);
45
+ }
@@ -0,0 +1,25 @@
1
+ import { Badge } from "@monkey-mini-app/ui";
2
+
3
+ export type Item = { id: string; title: string; done: boolean; createdAt: number };
4
+
5
+ /** UI-only row. Backend must not import ./ui/**. */
6
+ export function ItemRow({
7
+ item,
8
+ selected,
9
+ onSelect,
10
+ }: {
11
+ item: Item;
12
+ selected: boolean;
13
+ onSelect: () => void;
14
+ }) {
15
+ return (
16
+ <button
17
+ type="button"
18
+ className={`flex w-full items-center gap-2 px-3 py-2 text-left text-sm ${selected ? "bg-muted" : ""}`}
19
+ onClick={onSelect}
20
+ >
21
+ <span className={item.done ? "text-muted-foreground line-through" : ""}>{item.title}</span>
22
+ {item.done ? <Badge variant="secondary">完</Badge> : null}
23
+ </button>
24
+ );
25
+ }