@atmos.build/ui 0.1.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 (431) hide show
  1. package/README.md +45 -0
  2. package/dist/components/alert-dialog.d.ts +14 -0
  3. package/dist/components/alert-dialog.js +40 -0
  4. package/dist/components/at-search.d.ts +35 -0
  5. package/dist/components/at-search.js +57 -0
  6. package/dist/components/attachment-thumbnail-stack.d.ts +13 -0
  7. package/dist/components/attachment-thumbnail-stack.js +23 -0
  8. package/dist/components/audio-preview.d.ts +33 -0
  9. package/dist/components/audio-preview.js +176 -0
  10. package/dist/components/avatar-uploader.d.ts +29 -0
  11. package/dist/components/avatar-uploader.js +67 -0
  12. package/dist/components/avatar.d.ts +12 -0
  13. package/dist/components/avatar.js +38 -0
  14. package/dist/components/badge.d.ts +9 -0
  15. package/dist/components/badge.js +25 -0
  16. package/dist/components/button-group.d.ts +12 -0
  17. package/dist/components/button-group.js +29 -0
  18. package/dist/components/button.d.ts +10 -0
  19. package/dist/components/button.js +42 -0
  20. package/dist/components/calendar.d.ts +26 -0
  21. package/dist/components/calendar.js +154 -0
  22. package/dist/components/channel-list.d.ts +33 -0
  23. package/dist/components/channel-list.js +40 -0
  24. package/dist/components/charts/area-chart.d.ts +2 -0
  25. package/dist/components/charts/area-chart.js +5 -0
  26. package/dist/components/charts/bar-chart.d.ts +2 -0
  27. package/dist/components/charts/bar-chart.js +58 -0
  28. package/dist/components/charts/colors.d.ts +2 -0
  29. package/dist/components/charts/colors.js +42 -0
  30. package/dist/components/charts/hover.d.ts +20 -0
  31. package/dist/components/charts/hover.js +31 -0
  32. package/dist/components/charts/index.d.ts +10 -0
  33. package/dist/components/charts/index.js +9 -0
  34. package/dist/components/charts/layout.d.ts +35 -0
  35. package/dist/components/charts/layout.js +101 -0
  36. package/dist/components/charts/legend.d.ts +6 -0
  37. package/dist/components/charts/legend.js +7 -0
  38. package/dist/components/charts/line-area-chart.d.ts +4 -0
  39. package/dist/components/charts/line-area-chart.js +86 -0
  40. package/dist/components/charts/line-chart.d.ts +2 -0
  41. package/dist/components/charts/line-chart.js +5 -0
  42. package/dist/components/charts/pie-chart.d.ts +2 -0
  43. package/dist/components/charts/pie-chart.js +22 -0
  44. package/dist/components/charts/radar-chart.d.ts +2 -0
  45. package/dist/components/charts/radar-chart.js +29 -0
  46. package/dist/components/charts/radial-chart.d.ts +2 -0
  47. package/dist/components/charts/radial-chart.js +19 -0
  48. package/dist/components/charts/scatter-chart.d.ts +2 -0
  49. package/dist/components/charts/scatter-chart.js +16 -0
  50. package/dist/components/charts/story-data.d.ts +24 -0
  51. package/dist/components/charts/story-data.js +48 -0
  52. package/dist/components/charts/types.d.ts +43 -0
  53. package/dist/components/charts/types.js +1 -0
  54. package/dist/components/checkbox.d.ts +4 -0
  55. package/dist/components/checkbox.js +10 -0
  56. package/dist/components/chip.d.ts +25 -0
  57. package/dist/components/chip.js +36 -0
  58. package/dist/components/code-editor-theme.d.ts +19 -0
  59. package/dist/components/code-editor-theme.js +100 -0
  60. package/dist/components/collapsible-section-header.d.ts +82 -0
  61. package/dist/components/collapsible-section-header.js +82 -0
  62. package/dist/components/collection-view/collection-view-group-settings.d.ts +73 -0
  63. package/dist/components/collection-view/collection-view-group-settings.js +55 -0
  64. package/dist/components/collection-view/collection-view-settings.d.ts +115 -0
  65. package/dist/components/collection-view/collection-view-settings.js +146 -0
  66. package/dist/components/collection-view/collection-view.d.ts +87 -0
  67. package/dist/components/collection-view/collection-view.js +95 -0
  68. package/dist/components/collection-view/index.d.ts +6 -0
  69. package/dist/components/collection-view/index.js +6 -0
  70. package/dist/components/collection-view/use-collection-detail-navigation.d.ts +11 -0
  71. package/dist/components/collection-view/use-collection-detail-navigation.js +12 -0
  72. package/dist/components/collection-view/use-collection-escape.d.ts +9 -0
  73. package/dist/components/collection-view/use-collection-escape.js +20 -0
  74. package/dist/components/collection-view/use-collection-selection.d.ts +42 -0
  75. package/dist/components/collection-view/use-collection-selection.js +203 -0
  76. package/dist/components/color-picker.d.ts +18 -0
  77. package/dist/components/color-picker.js +77 -0
  78. package/dist/components/color-swatch-list.d.ts +16 -0
  79. package/dist/components/color-swatch-list.js +60 -0
  80. package/dist/components/combobox/combobox.d.ts +4 -0
  81. package/dist/components/combobox/combobox.js +70 -0
  82. package/dist/components/combobox/compound.d.ts +68 -0
  83. package/dist/components/combobox/compound.js +151 -0
  84. package/dist/components/combobox/context.d.ts +34 -0
  85. package/dist/components/combobox/context.js +123 -0
  86. package/dist/components/combobox/create-step.d.ts +12 -0
  87. package/dist/components/combobox/create-step.js +8 -0
  88. package/dist/components/combobox/index.d.ts +10 -0
  89. package/dist/components/combobox/index.js +5 -0
  90. package/dist/components/combobox/inline-create-form.d.ts +24 -0
  91. package/dist/components/combobox/inline-create-form.js +43 -0
  92. package/dist/components/combobox/types.d.ts +57 -0
  93. package/dist/components/combobox/types.js +10 -0
  94. package/dist/components/command.d.ts +35 -0
  95. package/dist/components/command.js +76 -0
  96. package/dist/components/comment-pin.d.ts +13 -0
  97. package/dist/components/comment-pin.js +33 -0
  98. package/dist/components/confidence-meter.d.ts +11 -0
  99. package/dist/components/confidence-meter.js +24 -0
  100. package/dist/components/context-menu.d.ts +31 -0
  101. package/dist/components/context-menu.js +54 -0
  102. package/dist/components/copy-button.d.ts +12 -0
  103. package/dist/components/copy-button.js +32 -0
  104. package/dist/components/date-picker.d.ts +29 -0
  105. package/dist/components/date-picker.js +86 -0
  106. package/dist/components/date-tile.d.ts +11 -0
  107. package/dist/components/date-tile.js +16 -0
  108. package/dist/components/date-time-picker.d.ts +25 -0
  109. package/dist/components/date-time-picker.js +153 -0
  110. package/dist/components/detail-breadcrumb-utils.d.ts +2 -0
  111. package/dist/components/detail-breadcrumb-utils.js +18 -0
  112. package/dist/components/detail-nav-bar.d.ts +28 -0
  113. package/dist/components/detail-nav-bar.js +28 -0
  114. package/dist/components/detail-top-bar.d.ts +49 -0
  115. package/dist/components/detail-top-bar.js +41 -0
  116. package/dist/components/dialog.d.ts +22 -0
  117. package/dist/components/dialog.js +51 -0
  118. package/dist/components/dropdown-menu.d.ts +29 -0
  119. package/dist/components/dropdown-menu.js +52 -0
  120. package/dist/components/editable-doc-title.d.ts +17 -0
  121. package/dist/components/editable-doc-title.js +147 -0
  122. package/dist/components/empty-state.d.ts +12 -0
  123. package/dist/components/empty-state.js +6 -0
  124. package/dist/components/filter-condition-editor.d.ts +18 -0
  125. package/dist/components/filter-condition-editor.js +102 -0
  126. package/dist/components/form-dialog.d.ts +30 -0
  127. package/dist/components/form-dialog.js +52 -0
  128. package/dist/components/formula-editor.d.ts +18 -0
  129. package/dist/components/formula-editor.js +154 -0
  130. package/dist/components/hover-card.d.ts +52 -0
  131. package/dist/components/hover-card.js +51 -0
  132. package/dist/components/icon-button.d.ts +15 -0
  133. package/dist/components/icon-button.js +18 -0
  134. package/dist/components/inline-alert.d.ts +11 -0
  135. package/dist/components/inline-alert.js +17 -0
  136. package/dist/components/input.d.ts +3 -0
  137. package/dist/components/input.js +7 -0
  138. package/dist/components/kanban-board.d.ts +27 -0
  139. package/dist/components/kanban-board.js +145 -0
  140. package/dist/components/kbd.d.ts +3 -0
  141. package/dist/components/kbd.js +8 -0
  142. package/dist/components/label.d.ts +4 -0
  143. package/dist/components/label.js +9 -0
  144. package/dist/components/markdown-editor/index.d.ts +4 -0
  145. package/dist/components/markdown-editor/index.js +2 -0
  146. package/dist/components/markdown-editor/markdown-editor.d.ts +16 -0
  147. package/dist/components/markdown-editor/markdown-editor.js +53 -0
  148. package/dist/components/markdown-editor/serialize.d.ts +12 -0
  149. package/dist/components/markdown-editor/serialize.js +122 -0
  150. package/dist/components/markdown-editor/vim.d.ts +8 -0
  151. package/dist/components/markdown-editor/vim.js +394 -0
  152. package/dist/components/metric-grid.d.ts +41 -0
  153. package/dist/components/metric-grid.js +39 -0
  154. package/dist/components/microphone-priority.d.ts +29 -0
  155. package/dist/components/microphone-priority.js +15 -0
  156. package/dist/components/middle-truncate.d.ts +6 -0
  157. package/dist/components/middle-truncate.js +15 -0
  158. package/dist/components/multi-combobox.d.ts +48 -0
  159. package/dist/components/multi-combobox.js +221 -0
  160. package/dist/components/naut-avatar-engine.d.ts +83 -0
  161. package/dist/components/naut-avatar-engine.js +803 -0
  162. package/dist/components/naut-avatar.d.ts +31 -0
  163. package/dist/components/naut-avatar.js +108 -0
  164. package/dist/components/navigable-list.d.ts +4 -0
  165. package/dist/components/navigable-list.js +20 -0
  166. package/dist/components/note-icon-picker.d.ts +20 -0
  167. package/dist/components/note-icon-picker.js +84 -0
  168. package/dist/components/note-icon.d.ts +690 -0
  169. package/dist/components/note-icon.js +353 -0
  170. package/dist/components/note-row.d.ts +33 -0
  171. package/dist/components/note-row.js +29 -0
  172. package/dist/components/overlapping-dots.d.ts +10 -0
  173. package/dist/components/overlapping-dots.js +13 -0
  174. package/dist/components/overview-card.d.ts +12 -0
  175. package/dist/components/overview-card.js +9 -0
  176. package/dist/components/panel-header.d.ts +8 -0
  177. package/dist/components/panel-header.js +6 -0
  178. package/dist/components/panel-section-states.d.ts +9 -0
  179. package/dist/components/panel-section-states.js +10 -0
  180. package/dist/components/person-avatar.d.ts +10 -0
  181. package/dist/components/person-avatar.js +23 -0
  182. package/dist/components/photo-avatar.d.ts +11 -0
  183. package/dist/components/photo-avatar.js +24 -0
  184. package/dist/components/picker-field.d.ts +23 -0
  185. package/dist/components/picker-field.js +24 -0
  186. package/dist/components/popover-stack.d.ts +26 -0
  187. package/dist/components/popover-stack.js +89 -0
  188. package/dist/components/popover.d.ts +12 -0
  189. package/dist/components/popover.js +31 -0
  190. package/dist/components/portal-login-barrier.d.ts +12 -0
  191. package/dist/components/portal-login-barrier.js +41 -0
  192. package/dist/components/presence-dot.d.ts +8 -0
  193. package/dist/components/presence-dot.js +15 -0
  194. package/dist/components/presence-overlay.d.ts +27 -0
  195. package/dist/components/presence-overlay.js +34 -0
  196. package/dist/components/property-list.d.ts +64 -0
  197. package/dist/components/property-list.js +313 -0
  198. package/dist/components/property-panel.d.ts +54 -0
  199. package/dist/components/property-panel.js +87 -0
  200. package/dist/components/property-selector.d.ts +36 -0
  201. package/dist/components/property-selector.js +141 -0
  202. package/dist/components/provenance-chip.d.ts +12 -0
  203. package/dist/components/provenance-chip.js +17 -0
  204. package/dist/components/qr-code.d.ts +13 -0
  205. package/dist/components/qr-code.js +42 -0
  206. package/dist/components/qr-encode.d.ts +2 -0
  207. package/dist/components/qr-encode.js +469 -0
  208. package/dist/components/quantity-stepper.d.ts +25 -0
  209. package/dist/components/quantity-stepper.js +43 -0
  210. package/dist/components/radio-group.d.ts +5 -0
  211. package/dist/components/radio-group.js +13 -0
  212. package/dist/components/rename-dialog.d.ts +19 -0
  213. package/dist/components/rename-dialog.js +35 -0
  214. package/dist/components/row-surface.d.ts +1 -0
  215. package/dist/components/row-surface.js +5 -0
  216. package/dist/components/row-trailing.d.ts +30 -0
  217. package/dist/components/row-trailing.js +59 -0
  218. package/dist/components/run-status-badge.d.ts +16 -0
  219. package/dist/components/run-status-badge.js +43 -0
  220. package/dist/components/scroll-area.d.ts +5 -0
  221. package/dist/components/scroll-area.js +12 -0
  222. package/dist/components/select.d.ts +15 -0
  223. package/dist/components/select.js +39 -0
  224. package/dist/components/selectable-card.d.ts +33 -0
  225. package/dist/components/selectable-card.js +66 -0
  226. package/dist/components/separator.d.ts +3 -0
  227. package/dist/components/separator.js +8 -0
  228. package/dist/components/settings-dialog-shell.d.ts +46 -0
  229. package/dist/components/settings-dialog-shell.js +48 -0
  230. package/dist/components/shimmer-text.d.ts +8 -0
  231. package/dist/components/shimmer-text.js +26 -0
  232. package/dist/components/side-panel-tokens.d.ts +27 -0
  233. package/dist/components/side-panel-tokens.js +26 -0
  234. package/dist/components/side-panel.d.ts +94 -0
  235. package/dist/components/side-panel.js +106 -0
  236. package/dist/components/skeleton.d.ts +2 -0
  237. package/dist/components/skeleton.js +6 -0
  238. package/dist/components/sortable.d.ts +65 -0
  239. package/dist/components/sortable.js +110 -0
  240. package/dist/components/spec-strip.d.ts +18 -0
  241. package/dist/components/spec-strip.js +15 -0
  242. package/dist/components/speech-playback.d.ts +25 -0
  243. package/dist/components/speech-playback.js +35 -0
  244. package/dist/components/sql-editor.d.ts +13 -0
  245. package/dist/components/sql-editor.js +228 -0
  246. package/dist/components/stat-tile.d.ts +7 -0
  247. package/dist/components/stat-tile.js +6 -0
  248. package/dist/components/status-badge.d.ts +17 -0
  249. package/dist/components/status-badge.js +8 -0
  250. package/dist/components/status-tone.d.ts +9 -0
  251. package/dist/components/status-tone.js +10 -0
  252. package/dist/components/sticky-header-fade.d.ts +8 -0
  253. package/dist/components/sticky-header-fade.js +11 -0
  254. package/dist/components/swatch-button.d.ts +14 -0
  255. package/dist/components/swatch-button.js +25 -0
  256. package/dist/components/switch.d.ts +6 -0
  257. package/dist/components/switch.js +9 -0
  258. package/dist/components/system-load/index.d.ts +6 -0
  259. package/dist/components/system-load/index.js +6 -0
  260. package/dist/components/system-load/load-block.d.ts +20 -0
  261. package/dist/components/system-load/load-block.js +23 -0
  262. package/dist/components/system-load/load-grid.d.ts +16 -0
  263. package/dist/components/system-load/load-grid.js +23 -0
  264. package/dist/components/system-load/load-meter.d.ts +25 -0
  265. package/dist/components/system-load/load-meter.js +29 -0
  266. package/dist/components/system-load/load-tone.d.ts +21 -0
  267. package/dist/components/system-load/load-tone.js +29 -0
  268. package/dist/components/system-load/meter-row.d.ts +31 -0
  269. package/dist/components/system-load/meter-row.js +29 -0
  270. package/dist/components/system-load/resource-meter.d.ts +19 -0
  271. package/dist/components/system-load/resource-meter.js +15 -0
  272. package/dist/components/tab-title-bar.d.ts +12 -0
  273. package/dist/components/tab-title-bar.js +9 -0
  274. package/dist/components/table.d.ts +10 -0
  275. package/dist/components/table.js +29 -0
  276. package/dist/components/tabs.d.ts +11 -0
  277. package/dist/components/tabs.js +97 -0
  278. package/dist/components/template-chip-input.d.ts +36 -0
  279. package/dist/components/template-chip-input.js +271 -0
  280. package/dist/components/template-input.d.ts +24 -0
  281. package/dist/components/template-input.js +57 -0
  282. package/dist/components/terminal-spinner.d.ts +11 -0
  283. package/dist/components/terminal-spinner.js +48 -0
  284. package/dist/components/textarea.d.ts +3 -0
  285. package/dist/components/textarea.js +7 -0
  286. package/dist/components/time-column.d.ts +24 -0
  287. package/dist/components/time-column.js +60 -0
  288. package/dist/components/timestamped-transcript.d.ts +38 -0
  289. package/dist/components/timestamped-transcript.js +29 -0
  290. package/dist/components/timezone-picker.d.ts +22 -0
  291. package/dist/components/timezone-picker.js +60 -0
  292. package/dist/components/tooltip.d.ts +11 -0
  293. package/dist/components/tooltip.js +29 -0
  294. package/dist/components/transcription-overlay.d.ts +47 -0
  295. package/dist/components/transcription-overlay.js +30 -0
  296. package/dist/components/usage-bar.d.ts +17 -0
  297. package/dist/components/usage-bar.js +26 -0
  298. package/dist/components/view-query-bar.d.ts +13 -0
  299. package/dist/components/view-query-bar.js +13 -0
  300. package/dist/components/view-query-controls.d.ts +159 -0
  301. package/dist/components/view-query-controls.js +109 -0
  302. package/dist/components/view-save-menu.d.ts +20 -0
  303. package/dist/components/view-save-menu.js +13 -0
  304. package/dist/components/view-sort-editor.d.ts +40 -0
  305. package/dist/components/view-sort-editor.js +47 -0
  306. package/dist/components/voice-line.d.ts +37 -0
  307. package/dist/components/voice-line.js +293 -0
  308. package/dist/components/weekly-schedule-editor.d.ts +15 -0
  309. package/dist/components/weekly-schedule-editor.js +28 -0
  310. package/dist/flow/canvas/canvas-frame.d.ts +160 -0
  311. package/dist/flow/canvas/canvas-frame.js +521 -0
  312. package/dist/flow/canvas/collaborator-layer.d.ts +12 -0
  313. package/dist/flow/canvas/collaborator-layer.js +43 -0
  314. package/dist/flow/canvas/connector-edge.d.ts +22 -0
  315. package/dist/flow/canvas/connector-edge.js +61 -0
  316. package/dist/flow/canvas/editor-context.d.ts +23 -0
  317. package/dist/flow/canvas/editor-context.js +6 -0
  318. package/dist/flow/canvas/graph-core.d.ts +60 -0
  319. package/dist/flow/canvas/graph-core.js +296 -0
  320. package/dist/flow/canvas/minimap-sticky-overlay.d.ts +4 -0
  321. package/dist/flow/canvas/minimap-sticky-overlay.js +45 -0
  322. package/dist/flow/canvas/node-card.d.ts +46 -0
  323. package/dist/flow/canvas/node-card.js +56 -0
  324. package/dist/flow/canvas/node-library.d.ts +40 -0
  325. package/dist/flow/canvas/node-library.js +54 -0
  326. package/dist/flow/canvas/sticky-notes.d.ts +25 -0
  327. package/dist/flow/canvas/sticky-notes.js +101 -0
  328. package/dist/flow/collaborative-graph-presence.d.ts +28 -0
  329. package/dist/flow/collaborative-graph-presence.js +55 -0
  330. package/dist/flow/collaborative-graph-sync.d.ts +40 -0
  331. package/dist/flow/collaborative-graph-sync.js +127 -0
  332. package/dist/flow/editor/adapter.d.ts +64 -0
  333. package/dist/flow/editor/adapter.js +1 -0
  334. package/dist/flow/editor/command-registry.d.ts +10 -0
  335. package/dist/flow/editor/command-registry.js +35 -0
  336. package/dist/flow/editor/dag-canvas.d.ts +18 -0
  337. package/dist/flow/editor/dag-canvas.js +33 -0
  338. package/dist/flow/editor/flow-editor.d.ts +54 -0
  339. package/dist/flow/editor/flow-editor.js +199 -0
  340. package/dist/flow/editor/issues-popover.d.ts +11 -0
  341. package/dist/flow/editor/issues-popover.js +70 -0
  342. package/dist/flow/editor/library-rail.d.ts +19 -0
  343. package/dist/flow/editor/library-rail.js +25 -0
  344. package/dist/flow/editor/make-controller.d.ts +18 -0
  345. package/dist/flow/editor/make-controller.js +44 -0
  346. package/dist/flow/editor/node-chip.d.ts +2 -0
  347. package/dist/flow/editor/node-chip.js +16 -0
  348. package/dist/flow/editor/save-publish-bar.d.ts +27 -0
  349. package/dist/flow/editor/save-publish-bar.js +14 -0
  350. package/dist/flow/editor/settings-dialog.d.ts +11 -0
  351. package/dist/flow/editor/settings-dialog.js +11 -0
  352. package/dist/flow/editor/settings-shell.d.ts +21 -0
  353. package/dist/flow/editor/settings-shell.js +20 -0
  354. package/dist/flow/editor/side-rail.d.ts +22 -0
  355. package/dist/flow/editor/side-rail.js +15 -0
  356. package/dist/flow/editor/use-dag-editor.d.ts +94 -0
  357. package/dist/flow/editor/use-dag-editor.js +502 -0
  358. package/dist/flow/index.d.ts +25 -0
  359. package/dist/flow/index.js +25 -0
  360. package/dist/flow/presence-motion.d.ts +10 -0
  361. package/dist/flow/presence-motion.js +88 -0
  362. package/dist/flow/styles.css +1 -0
  363. package/dist/flow/use-collaborative-graph.d.ts +61 -0
  364. package/dist/flow/use-collaborative-graph.js +396 -0
  365. package/dist/flow/use-debounced-value.d.ts +1 -0
  366. package/dist/flow/use-debounced-value.js +10 -0
  367. package/dist/hooks/use-detail-nav.d.ts +11 -0
  368. package/dist/hooks/use-detail-nav.js +49 -0
  369. package/dist/hooks/use-flush-on-hide.d.ts +1 -0
  370. package/dist/hooks/use-flush-on-hide.js +21 -0
  371. package/dist/hooks/use-media-query.d.ts +1 -0
  372. package/dist/hooks/use-media-query.js +20 -0
  373. package/dist/hooks/use-virtualizer.d.ts +1 -0
  374. package/dist/hooks/use-virtualizer.js +1 -0
  375. package/dist/index.d.ts +139 -0
  376. package/dist/index.js +139 -0
  377. package/dist/lib/brand-style.d.ts +6 -0
  378. package/dist/lib/brand-style.js +16 -0
  379. package/dist/lib/cn.d.ts +2 -0
  380. package/dist/lib/cn.js +5 -0
  381. package/dist/lib/composited-glint.d.ts +7 -0
  382. package/dist/lib/composited-glint.js +98 -0
  383. package/dist/lib/date-time-format.d.ts +2 -0
  384. package/dist/lib/date-time-format.js +21 -0
  385. package/dist/lib/disclosure-state.d.ts +11 -0
  386. package/dist/lib/disclosure-state.js +22 -0
  387. package/dist/lib/label-swatches.d.ts +10 -0
  388. package/dist/lib/label-swatches.js +24 -0
  389. package/dist/lib/local-ui-state.d.ts +10 -0
  390. package/dist/lib/local-ui-state.js +95 -0
  391. package/dist/lib/parse-loose-datetime.d.ts +1 -0
  392. package/dist/lib/parse-loose-datetime.js +180 -0
  393. package/dist/lib/parse-loose-time.d.ts +6 -0
  394. package/dist/lib/parse-loose-time.js +53 -0
  395. package/dist/lib/parse-loose.d.ts +1 -0
  396. package/dist/lib/parse-loose.js +170 -0
  397. package/dist/lib/react-19-jsx.d.ts +8 -0
  398. package/dist/lib/react-19-jsx.js +1 -0
  399. package/dist/lib/view-chrome.d.ts +5 -0
  400. package/dist/lib/view-chrome.js +5 -0
  401. package/dist/lib/view-query/config.d.ts +26 -0
  402. package/dist/lib/view-query/config.js +162 -0
  403. package/dist/lib/view-query/evaluate.d.ts +11 -0
  404. package/dist/lib/view-query/evaluate.js +196 -0
  405. package/dist/lib/view-query/group-order.d.ts +25 -0
  406. package/dist/lib/view-query/group-order.js +49 -0
  407. package/dist/lib/view-query/index.d.ts +6 -0
  408. package/dist/lib/view-query/index.js +6 -0
  409. package/dist/lib/view-query/model.d.ts +34 -0
  410. package/dist/lib/view-query/model.js +88 -0
  411. package/dist/lib/view-query/sort.d.ts +7 -0
  412. package/dist/lib/view-query/sort.js +30 -0
  413. package/dist/lib/view-query/types.d.ts +70 -0
  414. package/dist/lib/view-query/types.js +12 -0
  415. package/dist/lib/weekly-schedule.d.ts +8 -0
  416. package/dist/lib/weekly-schedule.js +10 -0
  417. package/dist/mcp-app/index.d.ts +4 -0
  418. package/dist/mcp-app/index.js +3 -0
  419. package/dist/mcp-app/shadcn.css +629 -0
  420. package/dist/mcp-app/styles.css +72 -0
  421. package/dist/mcp-app/theme.d.ts +2 -0
  422. package/dist/mcp-app/theme.js +62 -0
  423. package/dist/mcp-app/use-atmos-mcp-app.d.ts +109 -0
  424. package/dist/mcp-app/use-atmos-mcp-app.js +30 -0
  425. package/dist/mcp-app/vite.d.ts +7 -0
  426. package/dist/mcp-app/vite.js +30 -0
  427. package/dist/tokens/index.d.ts +7 -0
  428. package/dist/tokens/index.js +7 -0
  429. package/dist/tokens/semantic.css +110 -0
  430. package/dist/tokens/tokens.css +195 -0
  431. package/package.json +98 -0
@@ -0,0 +1,313 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { ChevronRight, Plus, X } from 'lucide-react';
5
+ import { cn } from '../lib/cn.js';
6
+ const DEFAULT_LABELS = {
7
+ empty: '—',
8
+ redacted: 'Redacted',
9
+ yes: 'Yes',
10
+ no: 'No',
11
+ fields: (n) => `${n} ${n === 1 ? 'field' : 'fields'}`,
12
+ items: (n) => `${n} ${n === 1 ? 'item' : 'items'}`,
13
+ addItem: 'Add item',
14
+ removeItem: 'Remove item',
15
+ };
16
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
17
+ const URL_RE = /^https?:\/\/\S+$/i;
18
+ const LONG_STRING = 56;
19
+ export function humanizeKey(key) {
20
+ const spaced = key
21
+ .replace(/[_-]+/g, ' ')
22
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
23
+ .replace(/\s+/g, ' ')
24
+ .trim();
25
+ if (!spaced)
26
+ return key;
27
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
28
+ }
29
+ function isPlainObject(value) {
30
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
31
+ }
32
+ function isEmptyScalar(value) {
33
+ return value === null || value === undefined || (typeof value === 'string' && value.trim() === '');
34
+ }
35
+ function isScalarArray(value) {
36
+ return Array.isArray(value) && value.every((item) => !isPlainObject(item) && !Array.isArray(item));
37
+ }
38
+ export function formatScalar(value, locale) {
39
+ if (isEmptyScalar(value))
40
+ return { kind: 'empty', text: '' };
41
+ if (typeof value === 'boolean')
42
+ return { kind: 'bool', text: '', bool: value };
43
+ if (typeof value === 'number')
44
+ return { kind: 'number', text: String(value) };
45
+ const s = String(value);
46
+ if (URL_RE.test(s))
47
+ return { kind: 'url', text: s };
48
+ if (ISO_DATE_RE.test(s)) {
49
+ const date = new Date(s);
50
+ if (!Number.isNaN(date.getTime())) {
51
+ const hasTime = s.includes('T');
52
+ const text = new Intl.DateTimeFormat(locale, hasTime ? { dateStyle: 'medium', timeStyle: 'short' } : { dateStyle: 'medium' }).format(date);
53
+ return { kind: 'date', text };
54
+ }
55
+ }
56
+ return { kind: 'text', text: s };
57
+ }
58
+ function getAtPath(root, path) {
59
+ return path.reduce((acc, key) => (acc == null ? acc : acc[key]), root);
60
+ }
61
+ function setAtPath(root, path, value) {
62
+ if (path.length === 0)
63
+ return value;
64
+ const [head, ...rest] = path;
65
+ if (Array.isArray(root)) {
66
+ const copy = root.slice();
67
+ copy[head] = setAtPath(root[head], rest, value);
68
+ return copy;
69
+ }
70
+ const obj = (isPlainObject(root) ? root : {});
71
+ const key = head;
72
+ return { ...obj, [key]: setAtPath(obj[key], rest, value) };
73
+ }
74
+ function removeAtPath(root, path) {
75
+ const parentPath = path.slice(0, -1);
76
+ const key = path[path.length - 1];
77
+ const parent = getAtPath(root, parentPath);
78
+ if (Array.isArray(parent)) {
79
+ return setAtPath(root, parentPath, parent.filter((_, i) => i !== key));
80
+ }
81
+ if (isPlainObject(parent)) {
82
+ const { [key]: _removed, ...next } = parent;
83
+ return setAtPath(root, parentPath, next);
84
+ }
85
+ return root;
86
+ }
87
+ const EditContext = React.createContext({
88
+ editable: false,
89
+ set: () => { },
90
+ removeItem: () => { },
91
+ });
92
+ const GroupContext = React.createContext({ isOpen: () => true, toggle: () => { } });
93
+ const LabelsContext = React.createContext(DEFAULT_LABELS);
94
+ const LocaleContext = React.createContext(undefined);
95
+ const ScalarRenderContext = React.createContext(undefined);
96
+ const KeyFormatContext = React.createContext(undefined);
97
+ function useKeyLabel() {
98
+ return React.useContext(KeyFormatContext) ?? humanizeKey;
99
+ }
100
+ const useIsoLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
101
+ // --- value editors / views --------------------------------------------------
102
+ function BoolValue({ path, value }) {
103
+ const labels = React.useContext(LabelsContext);
104
+ const { editable, set } = React.useContext(EditContext);
105
+ const dot = (_jsx("span", { className: cn('size-1.5 rounded-full', value ? 'bg-foreground/70' : 'border-muted-foreground/50 border bg-transparent') }));
106
+ const body = (_jsxs(_Fragment, { children: [dot, value ? labels.yes : labels.no] }));
107
+ const base = 'bg-muted text-foreground inline-flex items-center gap-1 rounded-sm px-1.5 py-0.5 text-[11px]';
108
+ if (!editable)
109
+ return _jsx("span", { className: base, children: body });
110
+ return (_jsx("button", { type: "button", role: "switch", "aria-checked": value, onClick: () => set(path, !value), className: cn(base, 'hover:bg-muted/70 focus-visible:ring-ring cursor-pointer border border-transparent focus-visible:ring-2 focus-visible:outline-none'), children: body }));
111
+ }
112
+ function ScalarInput({ path, value }) {
113
+ const labels = React.useContext(LabelsContext);
114
+ const { set } = React.useContext(EditContext);
115
+ const wasNumber = typeof value === 'number';
116
+ const commit = (raw) => {
117
+ if (raw === '')
118
+ return set(path, null);
119
+ const trimmed = raw.trim();
120
+ if (wasNumber && /^-?\d+(\.\d+)?$/.test(trimmed))
121
+ return set(path, Number(trimmed));
122
+ set(path, raw);
123
+ };
124
+ return (_jsx("input", { "data-hybrid-value": true, value: value == null ? '' : String(value), placeholder: labels.empty, spellCheck: false, onChange: (e) => commit(e.currentTarget.value), className: cn('text-foreground placeholder:text-muted-foreground/60 w-full min-w-0 rounded-sm border border-transparent bg-transparent px-1 py-0.5 text-right text-[12.5px] leading-5 outline-none', 'hover:border-input focus:border-ring focus:bg-background focus:ring-ring/30 focus:ring-2', 'group-data-[stacked]/row:text-left', wasNumber && 'tabular-nums') }));
125
+ }
126
+ function ScalarTextarea({ path, value }) {
127
+ const { set } = React.useContext(EditContext);
128
+ const ref = React.useRef(null);
129
+ const grow = React.useCallback(() => {
130
+ const el = ref.current;
131
+ if (!el)
132
+ return;
133
+ el.style.height = 'auto';
134
+ el.style.height = `${el.scrollHeight}px`;
135
+ }, []);
136
+ useIsoLayoutEffect(grow, [grow, value]);
137
+ return (_jsx("textarea", { ref: ref, rows: 1, value: value, spellCheck: false, onChange: (e) => {
138
+ set(path, e.currentTarget.value);
139
+ grow();
140
+ }, className: "text-foreground border-input focus:border-ring focus:ring-ring/30 mt-1 block w-full resize-none overflow-hidden rounded-sm border bg-transparent px-1.5 py-1 text-[12.5px] leading-5 outline-none focus:ring-2" }));
141
+ }
142
+ function ScalarView({ value, locale, fieldKey, }) {
143
+ const labels = React.useContext(LabelsContext);
144
+ const renderScalar = React.useContext(ScalarRenderContext);
145
+ if (renderScalar) {
146
+ const custom = renderScalar(value, fieldKey ?? '');
147
+ if (custom !== undefined)
148
+ return _jsx(_Fragment, { children: custom });
149
+ }
150
+ const f = formatScalar(value, locale);
151
+ if (f.kind === 'empty')
152
+ return _jsx("span", { className: "text-muted-foreground", children: labels.empty });
153
+ if (f.kind === 'number')
154
+ return _jsx("span", { className: "tabular-nums", children: f.text });
155
+ if (f.kind === 'url') {
156
+ return (_jsx("a", { href: f.text, target: "_blank", rel: "noopener noreferrer", className: "text-primary break-all underline underline-offset-2 hover:opacity-80", children: f.text }));
157
+ }
158
+ if (f.kind === 'date')
159
+ return _jsx("span", { children: f.text });
160
+ return _jsx("span", { className: "group-data-[stacked]/row:break-words", children: f.text });
161
+ }
162
+ function ScalarArrayValue({ path, value }) {
163
+ const labels = React.useContext(LabelsContext);
164
+ const { editable, set, removeItem } = React.useContext(EditContext);
165
+ const renderScalar = React.useContext(ScalarRenderContext);
166
+ const arrayKey = String(path[path.length - 1] ?? '');
167
+ const [adding, setAdding] = React.useState(false);
168
+ const chip = 'bg-muted inline-flex items-center gap-1 rounded-sm px-1.5 py-0.5 text-[11px]';
169
+ return (_jsxs(_Fragment, { children: [value.map((item, i) => {
170
+ const custom = renderScalar?.(item, arrayKey);
171
+ return (_jsxs("span", { className: chip, children: [custom !== undefined ? custom : String(item), editable ? (_jsx("button", { type: "button", "aria-label": labels.removeItem, onClick: () => removeItem([...path, i]), className: "text-muted-foreground hover:text-destructive -mr-0.5 rounded-sm", children: _jsx(X, { className: "size-3", strokeWidth: 1.8 }) })) : null] }, i));
172
+ }), editable ? (adding ? (_jsx("input", { ref: (el) => el?.focus(), "aria-label": labels.addItem, spellCheck: false, onBlur: (e) => {
173
+ const v = e.currentTarget.value.trim();
174
+ if (v)
175
+ set([...path, value.length], v);
176
+ setAdding(false);
177
+ }, onKeyDown: (e) => {
178
+ if (e.key === 'Enter')
179
+ e.currentTarget.blur();
180
+ if (e.key === 'Escape')
181
+ setAdding(false);
182
+ }, className: "border-ring bg-background focus:ring-ring/30 w-24 rounded-sm border px-1.5 py-0.5 text-[11px] outline-none focus:ring-2" })) : (_jsx("button", { type: "button", "aria-label": labels.addItem, onClick: () => setAdding(true), className: "border-input text-muted-foreground hover:text-foreground hover:border-ring inline-flex items-center rounded-sm border border-dashed px-1.5 py-0.5", children: _jsx(Plus, { className: "size-3", strokeWidth: 1.8 }) }))) : null] }));
183
+ }
184
+ // --- rows -------------------------------------------------------------------
185
+ function HybridRow({ keyName, children }) {
186
+ const label = useKeyLabel()(keyName);
187
+ return (_jsxs("div", { "data-hybrid-row": true, className: "group/row border-border/55 flex flex-wrap items-baseline gap-x-3 gap-y-0.5 border-t py-1 first:border-t-0", children: [_jsx("span", { className: "text-foreground shrink-0 text-[12.5px] leading-5", title: label, children: label }), children] }));
188
+ }
189
+ /**
190
+ * The right-aligned value slot that collapses to full-width on overflow. The slot
191
+ * clips inline overflow; the inner `Measured` probe lays out at its natural width
192
+ * (`w-max`) so the measurement pass can compare it against the slot's width
193
+ * regardless of alignment direction.
194
+ */
195
+ function Slot({ children }) {
196
+ return (_jsx("div", { className: "ml-auto flex min-w-0 flex-1 overflow-hidden text-[12.5px] leading-5 group-data-[stacked]/row:mt-0.5 group-data-[stacked]/row:basis-full group-data-[stacked]/row:overflow-visible", children: children }));
197
+ }
198
+ function Measured({ children }) {
199
+ return (_jsx("div", { "data-hybrid-value": true, className: "ml-auto flex w-max max-w-none flex-nowrap justify-end gap-1 text-right whitespace-nowrap group-data-[stacked]/row:w-full group-data-[stacked]/row:flex-wrap group-data-[stacked]/row:justify-start group-data-[stacked]/row:text-left group-data-[stacked]/row:break-words", children: children }));
200
+ }
201
+ function ScalarField({ path, keyName, value, locale, }) {
202
+ const { editable } = React.useContext(EditContext);
203
+ const keyLabel = useKeyLabel();
204
+ if (typeof value === 'boolean') {
205
+ return (_jsx(HybridRow, { keyName: keyName, children: _jsx(Slot, { children: _jsx("span", { className: "ml-auto", children: _jsx(BoolValue, { path: path, value: value }) }) }) }));
206
+ }
207
+ if (editable && typeof value === 'string' && value.length > LONG_STRING) {
208
+ return (_jsxs("div", { className: "border-border/55 flex flex-col border-t py-1 first:border-t-0", children: [_jsx("span", { className: "text-foreground text-[12.5px] leading-5", children: keyLabel(keyName) }), _jsx(ScalarTextarea, { path: path, value: value })] }));
209
+ }
210
+ return (_jsx(HybridRow, { keyName: keyName, children: _jsx(Slot, { children: editable ? (_jsx(ScalarInput, { path: path, value: value })) : (_jsx(Measured, { children: _jsx(ScalarView, { value: value, locale: locale, fieldKey: keyName }) })) }) }));
211
+ }
212
+ function ScalarArrayField({ path, keyName, value, }) {
213
+ return (_jsx(HybridRow, { keyName: keyName, children: _jsx(Slot, { children: _jsx(Measured, { children: _jsx(ScalarArrayValue, { path: path, value: value }) }) }) }));
214
+ }
215
+ function Group({ path, keyName, value, depth, }) {
216
+ const labels = React.useContext(LabelsContext);
217
+ const { isOpen, toggle } = React.useContext(GroupContext);
218
+ const key = path.join('');
219
+ const open = isOpen(key, depth);
220
+ const count = Array.isArray(value) ? value.length : Object.keys(value).length;
221
+ const summary = Array.isArray(value) ? labels.items(count) : labels.fields(count);
222
+ const keyLabel = useKeyLabel();
223
+ return (_jsxs("div", { className: "group/row border-border/55 border-t py-1 first:border-t-0", children: [_jsxs("button", { type: "button", "aria-expanded": open, onClick: () => toggle(key, depth), className: "focus-visible:ring-ring flex w-full items-center gap-1.5 rounded-sm text-left text-[12.5px] focus-visible:ring-2 focus-visible:outline-none", children: [_jsx(ChevronRight, { className: cn('text-muted-foreground size-2.5 shrink-0 transition-transform', open && 'rotate-90'), strokeWidth: 2 }), _jsx("span", { className: "text-foreground font-medium", children: keyLabel(keyName) }), _jsx("span", { className: "text-muted-foreground/70", children: summary })] }), open ? (_jsx("div", { className: "border-border mt-1 ml-1 border-l-2 pl-2.5", children: _jsx(ValueNode, { value: value, path: path, depth: depth + 1 }) })) : null] }));
224
+ }
225
+ function ValueNode({ value, path, depth }) {
226
+ const locale = React.useContext(LocaleContext);
227
+ const labels = React.useContext(LabelsContext);
228
+ if (isPlainObject(value)) {
229
+ const entries = Object.entries(value);
230
+ if (entries.length === 0)
231
+ return _jsx("span", { className: "text-muted-foreground text-[12.5px]", children: labels.empty });
232
+ return (_jsx("div", { className: "min-w-0", children: entries.map(([k, child]) => (_jsx(Row, { path: [...path, k], keyName: k, value: child, depth: depth, locale: locale }, k))) }));
233
+ }
234
+ if (Array.isArray(value)) {
235
+ if (value.length === 0)
236
+ return _jsx("span", { className: "text-muted-foreground text-[12.5px]", children: labels.empty });
237
+ if (isScalarArray(value)) {
238
+ // A bare scalar array at the top: render as a single value block.
239
+ return (_jsx("div", { className: "flex flex-wrap gap-1 text-[12.5px]", children: _jsx(ScalarArrayValue, { path: path, value: value }) }));
240
+ }
241
+ return (_jsx("div", { className: "flex min-w-0 flex-col gap-1", children: value.map((item, i) => (_jsx("div", { className: "border-border/55 border-t pt-1 first:border-t-0 first:pt-0", children: _jsx(ValueNode, { value: item, path: [...path, i], depth: depth }) }, i))) }));
242
+ }
243
+ // Bare scalar at the top level.
244
+ return (_jsx("div", { className: "text-[12.5px]", children: _jsx(ScalarView, { value: value, locale: locale, fieldKey: String(path[path.length - 1] ?? '') }) }));
245
+ }
246
+ function Row({ path, keyName, value, depth, locale, }) {
247
+ if (isPlainObject(value) || (Array.isArray(value) && !isScalarArray(value))) {
248
+ return (_jsx(Group, { path: path, keyName: keyName, value: value, depth: depth }));
249
+ }
250
+ if (isScalarArray(value))
251
+ return _jsx(ScalarArrayField, { path: path, keyName: keyName, value: value });
252
+ return _jsx(ScalarField, { path: path, keyName: keyName, value: value, locale: locale });
253
+ }
254
+ /**
255
+ * Renders an arbitrary JSON-ish value as friendly, labeled fields — humanized
256
+ * keys, formatted primitives (dates, links, yes/no), collapsible nested groups.
257
+ * Scalar rows are hybrid: the value sits inline (right-aligned) when it fits the
258
+ * width and drops to its own full-width line when it doesn't, so values never
259
+ * shred vertically in a narrow panel. With `editable`, scalars become inline
260
+ * editors. The non-technical alternative to a raw JSON dump. App-agnostic:
261
+ * inject localized `labels`.
262
+ */
263
+ export function PropertyList({ value, redacted = false, labels, locale, collapseDepth = 3, editable = false, onValueChange, renderScalar, formatKey, className, ...props }) {
264
+ const merged = React.useMemo(() => ({ ...DEFAULT_LABELS, ...labels }), [labels]);
265
+ const [overrides, setOverrides] = React.useState(() => new Map());
266
+ const rootRef = React.useRef(null);
267
+ const groupCtx = React.useMemo(() => ({
268
+ isOpen: (key, depth) => {
269
+ const stored = overrides.get(key);
270
+ return stored === undefined ? depth < collapseDepth : stored;
271
+ },
272
+ toggle: (key, depth) => setOverrides((prev) => {
273
+ const next = new Map(prev);
274
+ const stored = prev.get(key);
275
+ const current = stored === undefined ? depth < collapseDepth : stored;
276
+ next.set(key, !current);
277
+ return next;
278
+ }),
279
+ }), [overrides, collapseDepth]);
280
+ const editCtx = React.useMemo(() => ({
281
+ editable: editable && Boolean(onValueChange),
282
+ set: (path, next) => onValueChange?.(setAtPath(value, path, next)),
283
+ removeItem: (path) => onValueChange?.(removeAtPath(value, path)),
284
+ }), [editable, onValueChange, value]);
285
+ // Hybrid measurement: always measure in the un-stacked state, then decide.
286
+ const measure = React.useCallback(() => {
287
+ const root = rootRef.current;
288
+ if (!root)
289
+ return;
290
+ const rows = Array.from(root.querySelectorAll('[data-hybrid-row]'));
291
+ rows.forEach((r) => delete r.dataset.stacked);
292
+ void root.offsetWidth;
293
+ rows.forEach((r) => {
294
+ const measured = r.querySelector('[data-hybrid-value]');
295
+ if (!measured)
296
+ return;
297
+ const isField = measured.tagName === 'INPUT' || measured.tagName === 'TEXTAREA';
298
+ const available = isField ? measured.clientWidth : (measured.parentElement?.clientWidth ?? 0);
299
+ if (measured.scrollWidth > available + 1)
300
+ r.dataset.stacked = '';
301
+ });
302
+ }, []);
303
+ useIsoLayoutEffect(measure);
304
+ React.useEffect(() => {
305
+ const root = rootRef.current;
306
+ if (!root || typeof ResizeObserver === 'undefined')
307
+ return;
308
+ const ro = new ResizeObserver(() => measure());
309
+ ro.observe(root);
310
+ return () => ro.disconnect();
311
+ }, [measure]);
312
+ return (_jsx("div", { ref: rootRef, "data-slot": "property-list", className: cn('min-w-0 text-[12.5px]', className), ...props, children: redacted ? (_jsxs("span", { className: "text-muted-foreground/70 inline-flex items-center gap-1 font-mono text-[11px]", children: [_jsx("span", { className: "bg-muted-foreground/40 size-1 rounded-full" }), merged.redacted] })) : (_jsx(LabelsContext.Provider, { value: merged, children: _jsx(LocaleContext.Provider, { value: locale, children: _jsx(GroupContext.Provider, { value: groupCtx, children: _jsx(EditContext.Provider, { value: editCtx, children: _jsx(ScalarRenderContext.Provider, { value: renderScalar, children: _jsx(KeyFormatContext.Provider, { value: formatKey, children: _jsx(ValueNode, { value: value, path: [], depth: 0 }) }) }) }) }) }) })) }));
313
+ }
@@ -0,0 +1,54 @@
1
+ import * as React from 'react';
2
+ import { type PropertyListLabels } from './property-list.js';
3
+ export interface PropertyPanelLabels extends PropertyListLabels {
4
+ /** Segmented-control tab for the friendly field view. */
5
+ formatted: string;
6
+ /** Segmented-control tab for the raw JSON view. */
7
+ raw: string;
8
+ /** Copy-to-clipboard button (idle). */
9
+ copy: string;
10
+ /** Copy-to-clipboard button (just copied). */
11
+ copied: string;
12
+ /** Shown under the raw editor when the text isn't valid JSON. */
13
+ invalidJson: string;
14
+ }
15
+ type View = 'formatted' | 'raw';
16
+ export interface PropertyPanelProps extends Omit<React.ComponentProps<'div'>, 'onChange' | 'title'> {
17
+ /** Any JSON-ish value. */
18
+ value: unknown;
19
+ /** Replace the whole rendering with the redacted note. */
20
+ redacted?: boolean;
21
+ /** Turn the formatted view into inline editors and the raw view into a textarea. */
22
+ editable?: boolean;
23
+ /** Called with the next value on every valid edit (formatted or raw). */
24
+ onValueChange?: (next: unknown) => void;
25
+ /** Editable only: reports whether the current raw text parses to a valid JSON object. */
26
+ onValidityChange?: (valid: boolean) => void;
27
+ /** Localized copy; superset of the field-renderer labels. */
28
+ labels?: Partial<PropertyPanelLabels>;
29
+ /** BCP-47 locale for date formatting. */
30
+ locale?: string;
31
+ /** Nesting depth at/beyond which groups collapse by default. */
32
+ collapseDepth?: number;
33
+ /** Which view to open on. */
34
+ defaultView?: View;
35
+ /** Controlled view: when set, the segmented control is hidden and the view is fixed by the host. */
36
+ view?: View;
37
+ /** Optional heading rendered inline with the view toggle (e.g. a section label). */
38
+ title?: React.ReactNode;
39
+ /** Extra classes for the body container. */
40
+ bodyClassName?: string;
41
+ /** Per-scalar renderer for the formatted view (see {@link PropertyList.renderScalar}). */
42
+ renderScalar?: (value: unknown, key: string) => React.ReactNode | undefined;
43
+ /** Key-label formatter for the formatted view (see {@link PropertyList.formatKey}). */
44
+ formatKey?: (key: string) => string;
45
+ }
46
+ /**
47
+ * A JSON-ish value with a Formatted ⇄ Raw toggle. Formatted uses {@link PropertyList}
48
+ * (hybrid key/value fields, collapsible groups, optionally editable); Raw is a
49
+ * copy-friendly JSON view (a read-only block with a copy button, or an editable
50
+ * textarea). In editable mode the two views stay in sync and invalid raw JSON is
51
+ * surfaced without emitting a change. application-agnostic: inject localized `labels`.
52
+ */
53
+ export declare function PropertyPanel({ value, redacted, editable, onValueChange, onValidityChange, labels, locale, collapseDepth, defaultView, view: controlledView, title, bodyClassName, renderScalar, formatKey, className, ...props }: PropertyPanelProps): React.JSX.Element;
54
+ export {};
@@ -0,0 +1,87 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../lib/cn.js';
5
+ import { CopyButton } from './copy-button.js';
6
+ import { PropertyList } from './property-list.js';
7
+ const DEFAULT_PANEL_LABELS = {
8
+ empty: '—',
9
+ redacted: 'Redacted',
10
+ yes: 'Yes',
11
+ no: 'No',
12
+ fields: (n) => `${n} ${n === 1 ? 'field' : 'fields'}`,
13
+ items: (n) => `${n} ${n === 1 ? 'item' : 'items'}`,
14
+ addItem: 'Add item',
15
+ removeItem: 'Remove item',
16
+ formatted: 'Formatted',
17
+ raw: 'Raw',
18
+ copy: 'Copy',
19
+ copied: 'Copied',
20
+ invalidJson: 'Input must be valid JSON.',
21
+ };
22
+ function serialize(value) {
23
+ try {
24
+ return JSON.stringify(value ?? {}, null, 2);
25
+ }
26
+ catch {
27
+ return '{}';
28
+ }
29
+ }
30
+ function parseObject(text) {
31
+ try {
32
+ const parsed = JSON.parse(text || '{}');
33
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
34
+ return { ok: false };
35
+ return { ok: true, value: parsed };
36
+ }
37
+ catch {
38
+ return { ok: false };
39
+ }
40
+ }
41
+ function SegButton({ active, children, onClick, }) {
42
+ return (_jsx("button", { type: "button", role: "tab", "aria-selected": active, onClick: onClick, className: cn('focus-visible:ring-ring rounded-sm px-2 py-0.5 font-mono text-[10.5px] transition-colors focus-visible:ring-2 focus-visible:outline-none', active
43
+ ? 'bg-background text-foreground shadow-sm'
44
+ : 'text-foreground/80 hover:text-foreground'), children: children }));
45
+ }
46
+ /**
47
+ * A JSON-ish value with a Formatted ⇄ Raw toggle. Formatted uses {@link PropertyList}
48
+ * (hybrid key/value fields, collapsible groups, optionally editable); Raw is a
49
+ * copy-friendly JSON view (a read-only block with a copy button, or an editable
50
+ * textarea). In editable mode the two views stay in sync and invalid raw JSON is
51
+ * surfaced without emitting a change. application-agnostic: inject localized `labels`.
52
+ */
53
+ export function PropertyPanel({ value, redacted = false, editable = false, onValueChange, onValidityChange, labels, locale, collapseDepth = 3, defaultView = 'formatted', view: controlledView, title, bodyClassName, renderScalar, formatKey, className, ...props }) {
54
+ const merged = React.useMemo(() => ({ ...DEFAULT_PANEL_LABELS, ...labels }), [labels]);
55
+ const [internalView, setView] = React.useState(defaultView);
56
+ const view = controlledView ?? internalView;
57
+ const controlled = controlledView != null;
58
+ const [rawText, setRawText] = React.useState(() => serialize(value));
59
+ const [rawInvalid, setRawInvalid] = React.useState(false);
60
+ const goToRaw = () => {
61
+ setRawText(serialize(value));
62
+ setRawInvalid(false);
63
+ setView('raw');
64
+ };
65
+ const goToFormatted = () => {
66
+ if (rawInvalid)
67
+ return;
68
+ setView('formatted');
69
+ };
70
+ const onRawChange = (text) => {
71
+ setRawText(text);
72
+ const result = parseObject(text);
73
+ if (result.ok) {
74
+ setRawInvalid(false);
75
+ onValidityChange?.(true);
76
+ onValueChange?.(result.value);
77
+ }
78
+ else {
79
+ setRawInvalid(true);
80
+ onValidityChange?.(false);
81
+ }
82
+ };
83
+ if (redacted) {
84
+ return (_jsx("div", { className: cn('min-w-0', className), ...props, children: _jsx("div", { className: bodyClassName, children: _jsx(PropertyList, { value: value, redacted: true, labels: merged, locale: locale }) }) }));
85
+ }
86
+ return (_jsxs("div", { className: cn('min-w-0', className), ...props, children: [controlled && !title ? null : (_jsxs("div", { className: cn('mb-1 flex items-center gap-2', title ? 'justify-between' : 'justify-end'), children: [title ? _jsx("div", { className: "min-w-0 flex-1 truncate", children: title }) : null, _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [controlled ? null : (_jsxs("div", { role: "tablist", className: "bg-muted inline-flex gap-0.5 rounded-md p-0.5", children: [_jsx(SegButton, { active: view === 'formatted', onClick: goToFormatted, children: merged.formatted }), _jsx(SegButton, { active: view === 'raw', onClick: goToRaw, children: merged.raw })] })), _jsx(CopyButton, { size: "card", value: serialize(value), label: merged.copy, copiedLabel: merged.copied })] })] })), _jsx("div", { className: cn(view === 'raw' && 'border-border/60 bg-background rounded-md border', bodyClassName), children: view === 'formatted' ? (_jsx("div", { className: "border-border border-l-2 pl-2.5", children: _jsx(PropertyList, { value: value, labels: merged, locale: locale, collapseDepth: collapseDepth, ...(renderScalar ? { renderScalar } : {}), ...(formatKey ? { formatKey } : {}), ...(editable ? { editable, onValueChange } : {}) }) })) : editable ? (_jsx("textarea", { value: rawText, spellCheck: false, onChange: (e) => onRawChange(e.currentTarget.value), className: cn('text-foreground min-h-[160px] w-full resize-y bg-transparent p-2 font-mono text-[11px] leading-relaxed outline-none', rawInvalid && 'text-destructive') })) : (_jsx("pre", { className: "text-foreground p-2 font-mono text-[11px] leading-relaxed break-words whitespace-pre-wrap", children: serialize(value) })) }), rawInvalid ? (_jsx("p", { className: "text-destructive mt-1 text-[11px]", children: merged.invalidJson })) : null] }));
87
+ }
@@ -0,0 +1,36 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface PropertySelectorLabels {
3
+ noMatches: string;
4
+ create: string;
5
+ }
6
+ export interface PropertySelectorItem {
7
+ id: string;
8
+ label: string;
9
+ description?: string;
10
+ keywords?: string[];
11
+ icon?: ReactNode;
12
+ shortcut?: string;
13
+ selected?: boolean;
14
+ }
15
+ export interface PropertySelectorProps {
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ children: ReactNode;
19
+ items: PropertySelectorItem[];
20
+ onSelect: (item: PropertySelectorItem) => void;
21
+ allowCreate?: boolean;
22
+ onCreate?: (label: string) => void;
23
+ createLabel?: string;
24
+ searchPlaceholder: string;
25
+ triggerKey?: string;
26
+ contentClassName?: string;
27
+ /**
28
+ * Merge the popover-trigger semantics onto the trigger element itself instead
29
+ * of a wrapping div. Use this when the trigger is a direct member of a
30
+ * ButtonGroup so the group's corner-radius/border rules reach the button.
31
+ */
32
+ triggerAsChild?: boolean;
33
+ 'aria-label'?: string;
34
+ labels?: Partial<PropertySelectorLabels>;
35
+ }
36
+ export declare function PropertySelector({ open, onOpenChange, children, items, onSelect, allowCreate, onCreate, createLabel, searchPlaceholder, triggerKey, contentClassName, triggerAsChild, 'aria-label': ariaLabel, labels: labelsProp, }: PropertySelectorProps): import("react").JSX.Element;
@@ -0,0 +1,141 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useId, useMemo, useRef, useState, } from 'react';
4
+ import { Check, Plus } from 'lucide-react';
5
+ import { Slot } from 'radix-ui';
6
+ import { StackedPopover, StackedPopoverContent, StackedPopoverTrigger, } from './popover-stack.js';
7
+ import { Kbd } from './kbd.js';
8
+ import { EmptyState } from './empty-state.js';
9
+ import { cn } from '../lib/cn.js';
10
+ const DEFAULT_LABELS = {
11
+ noMatches: 'No matches',
12
+ create: 'Create',
13
+ };
14
+ const CREATE_ROW = '__create__';
15
+ export function PropertySelector({ open, onOpenChange, children, items, onSelect, allowCreate = false, onCreate, createLabel, searchPlaceholder, triggerKey, contentClassName, triggerAsChild = false, 'aria-label': ariaLabel, labels: labelsProp, }) {
16
+ const labels = { ...DEFAULT_LABELS, ...labelsProp };
17
+ const [query, setQuery] = useState('');
18
+ const [activeOverride, setActiveOverride] = useState(null);
19
+ const inputRef = useRef(null);
20
+ const triggerRef = useRef(null);
21
+ const wheelCleanupRef = useRef(null);
22
+ const listId = useId();
23
+ // The list is portalled to <body>, outside the scroll-lock (react-remove-scroll) of any
24
+ // enclosing dialog. That lock's document-level, bubble-phase `wheel` handler cancels
25
+ // mouse-wheel scrolling on portalled content (trackpad deltas slip its overscroll heuristic,
26
+ // discrete wheel ticks don't). Stopping the wheel event at the list keeps it from reaching that
27
+ // handler, so the list scrolls natively while the dialog's background stays locked. A callback
28
+ // ref (re)attaches the listener every time the list mounts, since it only exists while open.
29
+ const listRefCallback = useCallback((node) => {
30
+ wheelCleanupRef.current?.();
31
+ wheelCleanupRef.current = null;
32
+ if (!node)
33
+ return;
34
+ const stop = (event) => event.stopPropagation();
35
+ node.addEventListener('wheel', stop, { passive: true });
36
+ wheelCleanupRef.current = () => node.removeEventListener('wheel', stop);
37
+ }, []);
38
+ const filtered = useMemo(() => {
39
+ const q = query.trim().toLowerCase();
40
+ if (!q)
41
+ return items;
42
+ return items.filter((i) => i.label.toLowerCase().includes(q) ||
43
+ i.description?.toLowerCase().includes(q) ||
44
+ i.keywords?.some((keyword) => keyword.toLowerCase().includes(q)));
45
+ }, [items, query]);
46
+ const trimmedQuery = query.trim();
47
+ const hasExactMatch = useMemo(() => {
48
+ if (!trimmedQuery)
49
+ return false;
50
+ const needle = trimmedQuery.toLowerCase();
51
+ return items.some((i) => i.label.toLowerCase() === needle);
52
+ }, [items, trimmedQuery]);
53
+ const showCreate = allowCreate && Boolean(onCreate) && trimmedQuery.length > 0 && !hasExactMatch;
54
+ const rowIds = useMemo(() => {
55
+ const ids = filtered.map((i) => i.id);
56
+ if (showCreate)
57
+ ids.push(CREATE_ROW);
58
+ return ids;
59
+ }, [filtered, showCreate]);
60
+ const activeId = activeOverride && rowIds.includes(activeOverride)
61
+ ? activeOverride
62
+ : (rowIds[0] ?? null);
63
+ const handleOpenChange = useCallback((next) => {
64
+ if (next) {
65
+ setQuery('');
66
+ setActiveOverride(null);
67
+ }
68
+ onOpenChange(next);
69
+ }, [onOpenChange]);
70
+ const handleSelect = useCallback((item) => {
71
+ onSelect(item);
72
+ handleOpenChange(false);
73
+ }, [onSelect, handleOpenChange]);
74
+ const handleCreate = useCallback(() => {
75
+ if (!trimmedQuery || !onCreate)
76
+ return;
77
+ onCreate(trimmedQuery);
78
+ handleOpenChange(false);
79
+ }, [trimmedQuery, onCreate, handleOpenChange]);
80
+ const handleKeyDown = useCallback((e) => {
81
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
82
+ if (rowIds.length === 0)
83
+ return;
84
+ e.preventDefault();
85
+ const idx = activeId ? rowIds.indexOf(activeId) : -1;
86
+ const delta = e.key === 'ArrowDown' ? 1 : -1;
87
+ const next = (idx + delta + rowIds.length) % rowIds.length;
88
+ setActiveOverride(rowIds[next] ?? null);
89
+ return;
90
+ }
91
+ if (e.key === 'Enter') {
92
+ if (!activeId)
93
+ return;
94
+ e.preventDefault();
95
+ if (activeId === CREATE_ROW) {
96
+ handleCreate();
97
+ return;
98
+ }
99
+ const item = filtered.find((i) => i.id === activeId);
100
+ if (item)
101
+ handleSelect(item);
102
+ return;
103
+ }
104
+ if (e.key === 'Escape') {
105
+ e.preventDefault();
106
+ handleOpenChange(false);
107
+ return;
108
+ }
109
+ if (e.key.length === 1 &&
110
+ !e.metaKey &&
111
+ !e.ctrlKey &&
112
+ !e.altKey &&
113
+ query.length === 0) {
114
+ const key = e.key.toLowerCase();
115
+ const hit = items.find((i) => i.shortcut?.toLowerCase() === key);
116
+ if (hit) {
117
+ e.preventDefault();
118
+ handleSelect(hit);
119
+ }
120
+ }
121
+ }, [rowIds, activeId, filtered, items, query.length, handleSelect, handleCreate, handleOpenChange]);
122
+ const activeDomId = activeId ? `${listId}-row-${activeId}` : undefined;
123
+ return (_jsxs(StackedPopover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(StackedPopoverTrigger, { asChild: true, children: triggerAsChild ? (_jsx(Slot.Root, { ref: triggerRef, "aria-haspopup": "listbox", "aria-expanded": open, children: children })) : (_jsx("div", { ref: triggerRef, className: "inline-flex w-full", "aria-haspopup": "listbox", "aria-expanded": open, children: children })) }), _jsxs(StackedPopoverContent, { className: cn('w-64 p-0 gap-0 overflow-hidden', contentClassName), align: "start", "aria-label": ariaLabel, onCloseAutoFocus: (e) => {
124
+ e.preventDefault();
125
+ const el = triggerRef.current;
126
+ const focusable = el?.matches('button, [tabindex]:not([tabindex="-1"])')
127
+ ? el
128
+ : el?.querySelector('button, [tabindex]:not([tabindex="-1"])');
129
+ focusable?.focus();
130
+ }, onOpenAutoFocus: (e) => {
131
+ e.preventDefault();
132
+ inputRef.current?.focus();
133
+ }, children: [_jsxs("div", { className: "flex items-center gap-2 px-2.5 pt-2.5 pb-1.5 border-b border-border/60", children: [_jsx("input", { ref: inputRef, type: "text", role: "combobox", "aria-autocomplete": "list", "aria-controls": listId, "aria-expanded": true, "aria-activedescendant": activeDomId, value: query, placeholder: searchPlaceholder, onChange: (e) => setQuery(e.target.value), onKeyDown: handleKeyDown, className: "flex-1 min-w-0 bg-transparent outline-none text-[13px] placeholder:text-muted-foreground/70" }), triggerKey ? (_jsx(Kbd, { className: "text-[10.5px] shrink-0", children: triggerKey })) : null] }), _jsxs("ul", { ref: listRefCallback, id: listId, role: "listbox", "aria-label": ariaLabel, className: "max-h-[280px] overflow-y-auto overscroll-contain py-1", children: [filtered.length === 0 && !showCreate ? (_jsx("li", { children: _jsx(EmptyState, { title: labels.noMatches, className: "py-6" }) })) : (filtered.map((item) => {
134
+ const active = activeId === item.id;
135
+ return (
136
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- keyboard handled by the parent input via aria-activedescendant
137
+ _jsxs("li", { id: `${listId}-row-${item.id}`, role: "option", "aria-selected": item.selected ?? false, "data-active": active || undefined, onMouseEnter: () => setActiveOverride(item.id), onClick: () => handleSelect(item), className: cn('mx-1 px-2 py-1.5 rounded-md cursor-pointer text-[13px] text-foreground', 'flex gap-2', item.description ? 'items-start' : 'items-center', active && 'bg-muted'), children: [item.icon ? (_jsx("span", { className: cn('shrink-0 inline-flex items-center justify-center', item.description && 'pt-0.5'), children: item.icon })) : null, _jsxs("span", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "block truncate", children: item.label }), item.description ? (_jsx("span", { className: "block truncate text-[11px] leading-snug text-muted-foreground", children: item.description })) : null] }), _jsxs("span", { className: cn('shrink-0 inline-flex items-center gap-1 text-muted-foreground', item.description && 'pt-0.5'), children: [item.selected ? _jsx(Check, { className: "size-3.5", "aria-hidden": true }) : null, item.shortcut ? (_jsx(Kbd, { className: "text-[10.5px]", children: item.shortcut })) : null] })] }, item.id));
138
+ })), showCreate ? (
139
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- keyboard handled by the parent input via aria-activedescendant
140
+ _jsxs("li", { id: `${listId}-row-${CREATE_ROW}`, role: "option", "aria-selected": false, "data-active": activeId === CREATE_ROW || undefined, onMouseEnter: () => setActiveOverride(CREATE_ROW), onClick: handleCreate, className: cn('mx-1 mt-1 px-2 py-1.5 rounded-md cursor-pointer text-[13px]', 'flex items-center gap-2', filtered.length > 0 && 'border-t border-border/60 pt-2', activeId === CREATE_ROW && 'bg-muted'), children: [_jsx(Plus, { className: "size-3.5 text-muted-foreground shrink-0", strokeWidth: 1.8, "aria-hidden": true }), _jsxs("span", { className: "text-foreground truncate", children: [createLabel ?? labels.create, ":", ' ', _jsxs("span", { className: "text-foreground/90", children: ["\"", trimmedQuery, "\""] })] })] })) : null] })] })] }));
141
+ }
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ export type ProvenanceMethod = 'dtmf' | 'deterministic' | 'llm';
3
+ export interface ProvenanceChipProps extends Omit<React.ComponentProps<'span'>, 'children'> {
4
+ method: ProvenanceMethod;
5
+ label: string;
6
+ raw?: string;
7
+ rawLabel?: string;
8
+ expandLabel?: string;
9
+ confidence?: number;
10
+ confidenceLabel?: string;
11
+ }
12
+ export declare function ProvenanceChip({ method, label, raw, rawLabel, expandLabel, confidence, confidenceLabel, className, ...props }: ProvenanceChipProps): React.JSX.Element;