@lar-works/design-system 0.2.0 → 0.3.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 (433) hide show
  1. package/README.md +5 -1
  2. package/dist/actions/Button.d.ts +39 -1
  3. package/dist/actions/Button.js +39 -9
  4. package/dist/actions/Button.js.map +1 -1
  5. package/dist/actions/ButtonLink.d.ts +5 -1
  6. package/dist/actions/ButtonLink.js +28 -2
  7. package/dist/actions/ButtonLink.js.map +1 -1
  8. package/dist/actions/ButtonRecipes.js +7 -0
  9. package/dist/actions/ButtonRecipes.js.map +1 -0
  10. package/dist/actions/IconButton.d.ts +2 -2
  11. package/dist/actions/IconButton.js +1 -1
  12. package/dist/actions/IconButton.js.map +1 -1
  13. package/dist/actions/ThemeSwitch.js +1 -1
  14. package/dist/board/ActivityLine.d.ts +36 -0
  15. package/dist/board/ActivityLine.js +144 -0
  16. package/dist/board/ActivityLine.js.map +1 -0
  17. package/dist/board/ActivityTrack.d.ts +11 -0
  18. package/dist/board/ActivityTrack.js +25 -0
  19. package/dist/board/ActivityTrack.js.map +1 -0
  20. package/dist/board/AddItem.d.ts +82 -0
  21. package/dist/board/AddItem.js +185 -0
  22. package/dist/board/AddItem.js.map +1 -0
  23. package/dist/board/Archive.d.ts +21 -0
  24. package/dist/board/Archive.js +63 -0
  25. package/dist/board/Archive.js.map +1 -0
  26. package/dist/board/Attention.d.ts +66 -0
  27. package/dist/board/Attention.js +122 -0
  28. package/dist/board/Attention.js.map +1 -0
  29. package/dist/board/BoardShell.d.ts +16 -0
  30. package/dist/board/BoardShell.js +35 -0
  31. package/dist/board/BoardShell.js.map +1 -0
  32. package/dist/board/BoardTitleBar.d.ts +50 -0
  33. package/dist/board/BoardTitleBar.js +125 -0
  34. package/dist/board/BoardTitleBar.js.map +1 -0
  35. package/dist/board/ButtonKinds.d.ts +24 -0
  36. package/dist/board/ButtonKinds.js +19 -0
  37. package/dist/board/ButtonKinds.js.map +1 -0
  38. package/dist/board/Cleanup.d.ts +8 -0
  39. package/dist/board/Cleanup.js +15 -0
  40. package/dist/board/Cleanup.js.map +1 -0
  41. package/dist/board/Counters.d.ts +101 -0
  42. package/dist/board/Counters.js +202 -0
  43. package/dist/board/Counters.js.map +1 -0
  44. package/dist/board/DataAttributes.d.ts +6 -0
  45. package/dist/board/Dependencies.d.ts +17 -0
  46. package/dist/board/Dependencies.js +44 -0
  47. package/dist/board/Dependencies.js.map +1 -0
  48. package/dist/board/Desk.d.ts +52 -0
  49. package/dist/board/Desk.js +130 -0
  50. package/dist/board/Desk.js.map +1 -0
  51. package/dist/board/Dossier.d.ts +100 -0
  52. package/dist/board/Dossier.js +194 -0
  53. package/dist/board/Dossier.js.map +1 -0
  54. package/dist/board/Filters.d.ts +33 -0
  55. package/dist/board/Filters.js +64 -0
  56. package/dist/board/Filters.js.map +1 -0
  57. package/dist/board/ItemDetails.d.ts +167 -0
  58. package/dist/board/ItemDetails.js +339 -0
  59. package/dist/board/ItemDetails.js.map +1 -0
  60. package/dist/board/ItemDialog.d.ts +73 -0
  61. package/dist/board/ItemDialog.js +140 -0
  62. package/dist/board/ItemDialog.js.map +1 -0
  63. package/dist/board/ItemParts.d.ts +42 -0
  64. package/dist/board/ItemParts.js +82 -0
  65. package/dist/board/ItemParts.js.map +1 -0
  66. package/dist/board/ItemProgress.d.ts +56 -0
  67. package/dist/board/ItemProgress.js +138 -0
  68. package/dist/board/ItemProgress.js.map +1 -0
  69. package/dist/board/List.d.ts +65 -0
  70. package/dist/board/List.js +118 -0
  71. package/dist/board/List.js.map +1 -0
  72. package/dist/board/LoadingScreen.d.ts +38 -0
  73. package/dist/board/LoadingScreen.js +74 -0
  74. package/dist/board/LoadingScreen.js.map +1 -0
  75. package/dist/board/NeedsYou.d.ts +13 -0
  76. package/dist/board/NeedsYou.js +31 -0
  77. package/dist/board/NeedsYou.js.map +1 -0
  78. package/dist/board/Onboarding.d.ts +53 -0
  79. package/dist/board/Onboarding.js +122 -0
  80. package/dist/board/Onboarding.js.map +1 -0
  81. package/dist/board/PartsList.d.ts +60 -0
  82. package/dist/board/PartsList.js +115 -0
  83. package/dist/board/PartsList.js.map +1 -0
  84. package/dist/board/ProjectIcon.d.ts +51 -0
  85. package/dist/board/ProjectIcon.js +120 -0
  86. package/dist/board/ProjectIcon.js.map +1 -0
  87. package/dist/board/PullRequests.d.ts +43 -0
  88. package/dist/board/PullRequests.js +83 -0
  89. package/dist/board/PullRequests.js.map +1 -0
  90. package/dist/board/RowStyles.js +14 -0
  91. package/dist/board/RowStyles.js.map +1 -0
  92. package/dist/board/Settings.d.ts +54 -0
  93. package/dist/board/Settings.js +112 -0
  94. package/dist/board/Settings.js.map +1 -0
  95. package/dist/board/Slices.d.ts +32 -0
  96. package/dist/board/Slices.js +88 -0
  97. package/dist/board/Slices.js.map +1 -0
  98. package/dist/board/SourceIcon.d.ts +12 -0
  99. package/dist/board/SourceIcon.js +24 -0
  100. package/dist/board/SourceIcon.js.map +1 -0
  101. package/dist/board/StagePane.d.ts +43 -0
  102. package/dist/board/StagePane.js +97 -0
  103. package/dist/board/StagePane.js.map +1 -0
  104. package/dist/board/StageRow.d.ts +141 -0
  105. package/dist/board/StageRow.js +287 -0
  106. package/dist/board/StageRow.js.map +1 -0
  107. package/dist/board/StageTrack.d.ts +18 -0
  108. package/dist/board/StageTrack.js +38 -0
  109. package/dist/board/StageTrack.js.map +1 -0
  110. package/dist/board/StartControls.d.ts +30 -0
  111. package/dist/board/StartControls.js +51 -0
  112. package/dist/board/StartControls.js.map +1 -0
  113. package/dist/board/StatusColors.d.ts +5 -0
  114. package/dist/board/StatusColors.js +17 -0
  115. package/dist/board/StatusColors.js.map +1 -0
  116. package/dist/board/StatusGlyph.d.ts +18 -0
  117. package/dist/board/StatusGlyph.js +51 -0
  118. package/dist/board/StatusGlyph.js.map +1 -0
  119. package/dist/board/Threads.d.ts +13 -0
  120. package/dist/board/Threads.js +35 -0
  121. package/dist/board/Threads.js.map +1 -0
  122. package/dist/board/TrackerLabels.d.ts +27 -0
  123. package/dist/board/TrackerLabels.js +56 -0
  124. package/dist/board/TrackerLabels.js.map +1 -0
  125. package/dist/board/UpdatePill.d.ts +52 -0
  126. package/dist/board/UpdatePill.js +188 -0
  127. package/dist/board/UpdatePill.js.map +1 -0
  128. package/dist/board/Vocabulary.d.ts +56 -0
  129. package/dist/board/Vocabulary.js +104 -0
  130. package/dist/board/Vocabulary.js.map +1 -0
  131. package/dist/board/Warnings.d.ts +35 -0
  132. package/dist/board/Warnings.js +85 -0
  133. package/dist/board/Warnings.js.map +1 -0
  134. package/dist/board/WorkMap.d.ts +136 -0
  135. package/dist/board/WorkMap.js +274 -0
  136. package/dist/board/WorkMap.js.map +1 -0
  137. package/dist/board/index.d.ts +42 -0
  138. package/dist/collections/CollectionState.d.ts +10 -1
  139. package/dist/collections/CollectionState.js +12 -5
  140. package/dist/collections/CollectionState.js.map +1 -1
  141. package/dist/collections/ResultList.js +1 -1
  142. package/dist/collections/ScrollRow.js +1 -1
  143. package/dist/collections/VirtualList.js +1 -1
  144. package/dist/display/Avatar.d.ts +5 -2
  145. package/dist/display/Avatar.js +2 -2
  146. package/dist/display/Avatar.js.map +1 -1
  147. package/dist/display/Badge.d.ts +6 -1
  148. package/dist/display/Badge.js +9 -4
  149. package/dist/display/Badge.js.map +1 -1
  150. package/dist/display/CheckList.js +1 -1
  151. package/dist/display/Comment.d.ts +12 -0
  152. package/dist/display/Comment.js +39 -0
  153. package/dist/display/Comment.js.map +1 -0
  154. package/dist/display/CopyButton.d.ts +10 -2
  155. package/dist/display/CopyButton.js +29 -16
  156. package/dist/display/CopyButton.js.map +1 -1
  157. package/dist/display/Diagram.d.ts +17 -0
  158. package/dist/display/Diagram.js +49 -0
  159. package/dist/display/Diagram.js.map +1 -0
  160. package/dist/display/ImagePicker.js +1 -1
  161. package/dist/display/InfoBox.js +2 -2
  162. package/dist/display/InsetPanel.d.ts +3 -1
  163. package/dist/display/InsetPanel.js +7 -4
  164. package/dist/display/InsetPanel.js.map +1 -1
  165. package/dist/display/ItemAction.js +2 -2
  166. package/dist/display/LabelChip.d.ts +26 -0
  167. package/dist/display/LabelChip.js +41 -0
  168. package/dist/display/LabelChip.js.map +1 -0
  169. package/dist/display/LabelTint.js +60 -0
  170. package/dist/display/LabelTint.js.map +1 -0
  171. package/dist/display/Person.d.ts +5 -0
  172. package/dist/display/Person.js +19 -0
  173. package/dist/display/Person.js.map +1 -0
  174. package/dist/display/PropertySheet.js +1 -1
  175. package/dist/display/RadioChoice.d.ts +9 -2
  176. package/dist/display/RadioChoice.js +5 -1
  177. package/dist/display/RadioChoice.js.map +1 -1
  178. package/dist/display/RatingLink.js +1 -1
  179. package/dist/display/RichText.d.ts +12 -0
  180. package/dist/display/RichText.js +94 -0
  181. package/dist/display/RichText.js.map +1 -0
  182. package/dist/display/RowList.js +1 -1
  183. package/dist/display/index.d.ts +6 -1
  184. package/dist/feedback/Alert.js +1 -1
  185. package/dist/feedback/AsyncState.js +1 -1
  186. package/dist/feedback/DismissButton.d.ts +12 -0
  187. package/dist/feedback/DismissButton.js +20 -0
  188. package/dist/feedback/DismissButton.js.map +1 -0
  189. package/dist/feedback/ErrorNotification.js +2 -0
  190. package/dist/feedback/ErrorNotification.js.map +1 -1
  191. package/dist/feedback/FormResult.d.ts +16 -0
  192. package/dist/feedback/FormResult.js +30 -0
  193. package/dist/feedback/FormResult.js.map +1 -0
  194. package/dist/feedback/LiveRegion.d.ts +7 -0
  195. package/dist/feedback/LiveRegion.js +15 -0
  196. package/dist/feedback/LiveRegion.js.map +1 -0
  197. package/dist/feedback/Loading.d.ts +19 -0
  198. package/dist/feedback/Loading.js +63 -0
  199. package/dist/feedback/Loading.js.map +1 -0
  200. package/dist/feedback/Notifications.d.ts +35 -1
  201. package/dist/feedback/Notifications.js +196 -4
  202. package/dist/feedback/Notifications.js.map +1 -1
  203. package/dist/feedback/Progress.d.ts +15 -0
  204. package/dist/feedback/Progress.js +38 -0
  205. package/dist/feedback/Progress.js.map +1 -0
  206. package/dist/feedback/ProgressStatusRow.js +1 -1
  207. package/dist/feedback/StatusIndicator.d.ts +6 -1
  208. package/dist/feedback/StatusIndicator.js +19 -5
  209. package/dist/feedback/StatusIndicator.js.map +1 -1
  210. package/dist/feedback/index.d.ts +8 -4
  211. package/dist/forms/Checkbox.js +1 -1
  212. package/dist/forms/ColorSwatches.d.ts +21 -0
  213. package/dist/forms/ColorSwatches.js +26 -0
  214. package/dist/forms/ColorSwatches.js.map +1 -0
  215. package/dist/forms/FormSection.d.ts +68 -6
  216. package/dist/forms/FormSection.js +139 -8
  217. package/dist/forms/FormSection.js.map +1 -1
  218. package/dist/forms/HiddenField.d.ts +6 -0
  219. package/dist/forms/HiddenField.js +13 -0
  220. package/dist/forms/HiddenField.js.map +1 -0
  221. package/dist/forms/Input.d.ts +12 -2
  222. package/dist/forms/Input.js +10 -3
  223. package/dist/forms/Input.js.map +1 -1
  224. package/dist/forms/LabelPicker.d.ts +43 -0
  225. package/dist/forms/LabelPicker.js +107 -0
  226. package/dist/forms/LabelPicker.js.map +1 -0
  227. package/dist/forms/MarkdownEditor.d.ts +21 -0
  228. package/dist/forms/MarkdownEditor.js +175 -0
  229. package/dist/forms/MarkdownEditor.js.map +1 -0
  230. package/dist/forms/MarkdownToolbar.js +204 -0
  231. package/dist/forms/MarkdownToolbar.js.map +1 -0
  232. package/dist/forms/OptionSelect.d.ts +30 -9
  233. package/dist/forms/OptionSelect.js +53 -13
  234. package/dist/forms/OptionSelect.js.map +1 -1
  235. package/dist/forms/Select.d.ts +4 -1
  236. package/dist/forms/Select.js +3 -1
  237. package/dist/forms/Select.js.map +1 -1
  238. package/dist/forms/Switch.d.ts +4 -1
  239. package/dist/forms/Switch.js +5 -2
  240. package/dist/forms/Switch.js.map +1 -1
  241. package/dist/forms/TagInput.js +1 -1
  242. package/dist/forms/index.d.ts +7 -3
  243. package/dist/foundations/AmbientMotion.d.ts +2 -0
  244. package/dist/foundations/AmbientMotion.js +39 -0
  245. package/dist/foundations/AmbientMotion.js.map +1 -0
  246. package/dist/foundations/DesignSystemProvider.d.ts +34 -0
  247. package/dist/foundations/DesignSystemProvider.js +26 -1
  248. package/dist/foundations/DesignSystemProvider.js.map +1 -1
  249. package/dist/foundations/index.d.ts +2 -1
  250. package/dist/icons/BrandIcons.d.ts +8 -2
  251. package/dist/icons/BrandIcons.js +14 -3
  252. package/dist/icons/BrandIcons.js.map +1 -1
  253. package/dist/icons/dynamic.d.ts +2 -0
  254. package/dist/icons/dynamic.js +1 -0
  255. package/dist/icons/index.d.ts +2 -2
  256. package/dist/icons/index.js +1 -1
  257. package/dist/icons.d.ts +2 -2
  258. package/dist/icons.js +1 -1
  259. package/dist/index.d.ts +71 -10
  260. package/dist/index.js +78 -21
  261. package/dist/layout/Site.js +1 -1
  262. package/dist/layout/TitleBar.js +1 -1
  263. package/dist/layout/index.d.ts +2 -2
  264. package/dist/layout/index.js +3 -3
  265. package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +17 -2
  266. package/dist/layout/toolbar/CommandPaletteTrigger.js +89 -6
  267. package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -1
  268. package/dist/layout/toolbar/TriggerFit.js +56 -0
  269. package/dist/layout/toolbar/TriggerFit.js.map +1 -0
  270. package/dist/navigation/CollectionBrowseSelector.js +1 -1
  271. package/dist/navigation/CollectionViewToggle.d.ts +26 -0
  272. package/dist/navigation/CollectionViewToggle.js +54 -23
  273. package/dist/navigation/CollectionViewToggle.js.map +1 -1
  274. package/dist/navigation/DrilldownBrowseSelector.js +1 -1
  275. package/dist/navigation/FolderSelector.js +2 -2
  276. package/dist/navigation/SortMenu.d.ts +10 -0
  277. package/dist/navigation/SortMenu.js +33 -0
  278. package/dist/navigation/SortMenu.js.map +1 -0
  279. package/dist/navigation/index.d.ts +3 -2
  280. package/dist/overlays/CommandPalette.d.ts +38 -4
  281. package/dist/overlays/CommandPalette.js +140 -54
  282. package/dist/overlays/CommandPalette.js.map +1 -1
  283. package/dist/overlays/Drawer.js +1 -1
  284. package/dist/overlays/DropdownMenu.d.ts +7 -1
  285. package/dist/overlays/DropdownMenu.js +13 -2
  286. package/dist/overlays/DropdownMenu.js.map +1 -1
  287. package/dist/overlays/HelpTip.d.ts +8 -0
  288. package/dist/overlays/HelpTip.js +29 -0
  289. package/dist/overlays/HelpTip.js.map +1 -0
  290. package/dist/overlays/ImageViewer.js +2 -2
  291. package/dist/overlays/Modal.d.ts +5 -0
  292. package/dist/overlays/Modal.js +17 -2
  293. package/dist/overlays/Modal.js.map +1 -1
  294. package/dist/overlays/ModalExpandButton.d.ts +18 -0
  295. package/dist/overlays/ModalExpandButton.js +43 -0
  296. package/dist/overlays/ModalExpandButton.js.map +1 -0
  297. package/dist/overlays/Popover.d.ts +2 -1
  298. package/dist/overlays/Popover.js +1 -0
  299. package/dist/overlays/Popover.js.map +1 -1
  300. package/dist/overlays/index.d.ts +4 -2
  301. package/dist/showcase/Cards.js +1 -1
  302. package/dist/showcase/FeatureRow.js +1 -1
  303. package/dist/showcase/PhotoSearchConcept.js +1 -1
  304. package/dist/showcase/ProductBand.js +1 -1
  305. package/dist/showcase/Status.js +1 -1
  306. package/dist/typography/Code.d.ts +18 -0
  307. package/dist/typography/Code.js +24 -0
  308. package/dist/typography/Code.js.map +1 -0
  309. package/dist/typography/Link.d.ts +7 -2
  310. package/dist/typography/Link.js +15 -5
  311. package/dist/typography/Link.js.map +1 -1
  312. package/dist/typography/Typography.d.ts +19 -1
  313. package/dist/typography/Typography.js +11 -3
  314. package/dist/typography/Typography.js.map +1 -1
  315. package/dist/typography/index.d.ts +3 -3
  316. package/package.json +26 -3
  317. package/src/actions/Button.tsx +78 -11
  318. package/src/actions/ButtonLink.tsx +34 -0
  319. package/src/actions/ButtonRecipes.ts +10 -0
  320. package/src/actions/IconButton.tsx +7 -4
  321. package/src/board/ActivityLine.tsx +176 -0
  322. package/src/board/ActivityTrack.tsx +23 -0
  323. package/src/board/AddItem.tsx +259 -0
  324. package/src/board/Archive.tsx +75 -0
  325. package/src/board/Attention.tsx +135 -0
  326. package/src/board/BoardShell.tsx +30 -0
  327. package/src/board/BoardTitleBar.tsx +167 -0
  328. package/src/board/ButtonKinds.ts +32 -0
  329. package/src/board/Cleanup.tsx +19 -0
  330. package/src/board/Counters.tsx +224 -0
  331. package/src/board/DataAttributes.ts +3 -0
  332. package/src/board/Dependencies.tsx +49 -0
  333. package/src/board/Desk.tsx +155 -0
  334. package/src/board/Dossier.tsx +262 -0
  335. package/src/board/Filters.tsx +85 -0
  336. package/src/board/ItemDetails.tsx +435 -0
  337. package/src/board/ItemDialog.tsx +179 -0
  338. package/src/board/ItemParts.tsx +128 -0
  339. package/src/board/ItemProgress.tsx +164 -0
  340. package/src/board/List.tsx +154 -0
  341. package/src/board/LoadingScreen.tsx +78 -0
  342. package/src/board/NeedsYou.tsx +30 -0
  343. package/src/board/Onboarding.tsx +124 -0
  344. package/src/board/PartsList.tsx +160 -0
  345. package/src/board/ProjectIcon.tsx +172 -0
  346. package/src/board/PullRequests.tsx +106 -0
  347. package/src/board/RowStyles.ts +17 -0
  348. package/src/board/Settings.tsx +124 -0
  349. package/src/board/Slices.tsx +103 -0
  350. package/src/board/SourceIcon.tsx +33 -0
  351. package/src/board/StagePane.tsx +128 -0
  352. package/src/board/StageRow.tsx +320 -0
  353. package/src/board/StageTrack.tsx +61 -0
  354. package/src/board/StartControls.tsx +77 -0
  355. package/src/board/StatusColors.ts +28 -0
  356. package/src/board/StatusGlyph.tsx +70 -0
  357. package/src/board/Threads.tsx +38 -0
  358. package/src/board/TrackerLabels.tsx +75 -0
  359. package/src/board/UpdatePill.tsx +222 -0
  360. package/src/board/Vocabulary.tsx +155 -0
  361. package/src/board/Warnings.tsx +83 -0
  362. package/src/board/WorkMap.tsx +436 -0
  363. package/src/board/base.css +121 -0
  364. package/src/board/button-kinds.css +8 -0
  365. package/src/board/index.ts +224 -0
  366. package/src/board/items.css +75 -0
  367. package/src/board/loading-screen.css +171 -0
  368. package/src/board/rows.css +180 -0
  369. package/src/board/title-bar.css +56 -0
  370. package/src/board/tokens.css +52 -0
  371. package/src/board.css +19 -0
  372. package/src/collections/CollectionState.tsx +20 -7
  373. package/src/display/Avatar.tsx +6 -3
  374. package/src/display/Badge.tsx +25 -3
  375. package/src/display/Comment.tsx +26 -0
  376. package/src/display/CopyButton.tsx +48 -18
  377. package/src/display/Diagram.tsx +59 -0
  378. package/src/display/InsetPanel.tsx +4 -1
  379. package/src/display/LabelChip.tsx +73 -0
  380. package/src/display/LabelTint.ts +72 -0
  381. package/src/display/Person.tsx +11 -0
  382. package/src/display/RadioChoice.tsx +11 -2
  383. package/src/display/RichText.tsx +114 -0
  384. package/src/display/index.ts +5 -0
  385. package/src/feedback/DismissButton.tsx +28 -0
  386. package/src/feedback/ErrorNotification.ts +3 -0
  387. package/src/feedback/FormResult.tsx +50 -0
  388. package/src/feedback/LiveRegion.tsx +10 -0
  389. package/src/feedback/Loading.tsx +75 -0
  390. package/src/feedback/Notifications.tsx +267 -2
  391. package/src/feedback/Progress.tsx +44 -0
  392. package/src/feedback/StatusIndicator.tsx +34 -3
  393. package/src/feedback/index.ts +12 -2
  394. package/src/forms/ColorSwatches.tsx +50 -0
  395. package/src/forms/FormSection.tsx +245 -10
  396. package/src/forms/HiddenField.tsx +4 -0
  397. package/src/forms/Input.tsx +26 -4
  398. package/src/forms/LabelPicker.tsx +140 -0
  399. package/src/forms/MarkdownEditor.tsx +283 -0
  400. package/src/forms/MarkdownToolbar.tsx +267 -0
  401. package/src/forms/OptionSelect.tsx +110 -25
  402. package/src/forms/Select.tsx +20 -13
  403. package/src/forms/Switch.tsx +16 -2
  404. package/src/forms/index.ts +16 -2
  405. package/src/foundations/AmbientMotion.ts +51 -0
  406. package/src/foundations/DesignSystemProvider.tsx +19 -0
  407. package/src/foundations/index.ts +1 -0
  408. package/src/foundations/theme.css +64 -0
  409. package/src/icons/BrandIcons.tsx +12 -3
  410. package/src/icons/dynamic.ts +4 -0
  411. package/src/icons/index.ts +1 -1
  412. package/src/index.ts +2 -1
  413. package/src/layout/index.ts +1 -1
  414. package/src/layout/toolbar/CommandPaletteTrigger.tsx +187 -31
  415. package/src/layout/toolbar/TriggerFit.ts +84 -0
  416. package/src/navigation/CollectionViewToggle.tsx +94 -24
  417. package/src/navigation/SortMenu.tsx +41 -0
  418. package/src/navigation/index.ts +2 -1
  419. package/src/overlays/CommandPalette.tsx +190 -60
  420. package/src/overlays/DropdownMenu.tsx +12 -1
  421. package/src/overlays/HelpTip.tsx +29 -0
  422. package/src/overlays/Modal.tsx +23 -0
  423. package/src/overlays/ModalExpandButton.tsx +48 -0
  424. package/src/overlays/Popover.tsx +3 -1
  425. package/src/overlays/index.ts +9 -1
  426. package/src/showcase.css +6 -0
  427. package/src/styles.css +9 -1
  428. package/src/typography/Code.tsx +24 -0
  429. package/src/typography/Link.tsx +19 -10
  430. package/src/typography/Typography.tsx +25 -2
  431. package/src/typography/index.ts +1 -1
  432. package/dist/feedback/index.js +0 -11
  433. package/dist/typography/index.js +0 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LabelChip.js","names":[],"sources":["../../src/display/LabelChip.tsx"],"sourcesContent":["import { LockIcon } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { Badge } from './Badge';\n\ntype DataAttributes = { [key: `data-${string}`]: string | undefined };\n\ninterface LabelChipProps extends DataAttributes {\n /** The label's name, truncating, which its tooltip gives whole. */\n label: string;\n /** The label's own colour, such as a tracker's, as Badge's `labelColor`; none keeps the neutral badge. */\n color?: string | undefined;\n /** Follows the name, faded, such as \"new\" for a label still to be created. */\n note?: ReactNode;\n /** A lock before the name, for a label that can't be edited here; `lockedLabel` says why. */\n locked?: boolean;\n lockedLabel?: string;\n /** A × after the name, for a chip inside a control that removes it, such as an active filter's. */\n removable?: boolean;\n /** Its own × button, which `removeLabel` names, that removes the label. */\n onRemove?: () => void;\n removeLabel?: string;\n disabled?: boolean;\n}\n\n/** A label as a chip in its own colour, such as a tracker's: its name truncating, then any note, and a lock or a × that\n * removes it. */\nexport function LabelChip({\n label,\n color,\n note,\n locked = false,\n lockedLabel,\n removable = false,\n onRemove,\n removeLabel,\n disabled = false,\n ...data\n}: LabelChipProps) {\n return (\n <Badge\n data-label-chip=\"\"\n {...data}\n title={locked ? lockedLabel : undefined}\n className=\"max-w-full min-w-0\"\n labelColor={color}\n >\n {locked && <LockIcon aria-label={lockedLabel} />}\n <span className=\"max-w-52 truncate\" title={label}>\n {label}\n </span>\n {note && (\n <>\n {' '}\n <span className=\"opacity-70\">{note}</span>\n </>\n )}\n {onRemove ? (\n <button\n type=\"button\"\n className=\"cursor-pointer bg-transparent p-0\"\n aria-label={removeLabel}\n disabled={disabled}\n onClick={onRemove}\n >\n ×\n </button>\n ) : (\n removable && <span aria-hidden=\"true\">×</span>\n )}\n </Badge>\n );\n}\n"],"mappings":";;;;;;AA2BA,SAAgB,UAAU,EACtB,OACA,OACA,MACA,SAAS,OACT,aACA,YAAY,OACZ,UACA,aACA,WAAW,OACX,GAAG,QACY;CACf,OACI,qBAAC,OAAD;EACI,mBAAgB;EAChB,GAAI;EACJ,OAAO,SAAS,cAAc,KAAA;EAC9B,WAAU;EACV,YAAY;EALhB,UAAA;GAOK,UAAU,oBAAC,UAAD,EAAU,cAAY,YAAc,CAAA;GAC/C,oBAAC,QAAD;IAAM,WAAU;IAAoB,OAAO;IACtC,UAAA;GACC,CAAA;GACL,QACG,qBAAA,UAAA,EAAA,UAAA,CACK,KACD,oBAAC,QAAD;IAAM,WAAU;IAAc,UAAA;GAAW,CAAA,CAC3C,EAAA,CAAA;GAEL,WACG,oBAAC,UAAD;IACI,MAAK;IACL,WAAU;IACV,cAAY;IACF;IACV,SAAS;IACZ,UAAA;GAEO,CAAA,IAER,aAAa,oBAAC,QAAD;IAAM,eAAY;IAAO,UAAA;GAAO,CAAA;EAE9C;;AAEf"}
@@ -0,0 +1,60 @@
1
+ // src/display/LabelTint.ts
2
+ /** WCAG AA for text this small. */
3
+ const CONTRAST_FLOOR = 4.5;
4
+ /** The palette's foreground, and the surface a chip's text contrasts least with: the accent a hovered or picked row fills with. */
5
+ const PALETTE = {
6
+ light: {
7
+ foreground: "#27272a",
8
+ surface: "#f4f4f5"
9
+ },
10
+ dark: {
11
+ foreground: "#f5f5f5",
12
+ surface: "#161616"
13
+ }
14
+ };
15
+ const FILL = .16;
16
+ const TEXT_SHARE = .55;
17
+ const rgbOf = (hex) => {
18
+ const digits = /^#?([0-9a-f]{6})$/i.exec(hex)?.[1];
19
+ return digits ? [
20
+ 0,
21
+ 2,
22
+ 4
23
+ ].map((at) => parseInt(digits.slice(at, at + 2), 16)) : null;
24
+ };
25
+ const mixed = (a, b, share) => a.map((part, at) => part * share + b[at] * (1 - share));
26
+ const hexOf = (color) => `#${color.map((part) => Math.round(part).toString(16).padStart(2, "0")).join("")}`;
27
+ const luminance = (color) => {
28
+ const [r, g, b] = color.map((part) => {
29
+ const linear = part / 255;
30
+ return linear <= .03928 ? linear / 12.92 : ((linear + .055) / 1.055) ** 2.4;
31
+ });
32
+ return .2126 * r + .7152 * g + .0722 * b;
33
+ };
34
+ /** The WCAG contrast ratio of two colours. */
35
+ function contrastRatio(a, b) {
36
+ const [lighter, darker] = [luminance(rgbOf(a)), luminance(rgbOf(b))].sort((x, y) => y - x);
37
+ return (lighter + .05) / (darker + .05);
38
+ }
39
+ /** A chip's fill in `mode`, as tint's `color-mix` paints it over the palette's surface. */
40
+ const chipFill = (color, mode) => hexOf(mixed(rgbOf(color), rgbOf(PALETTE[mode].surface), FILL));
41
+ /** A chip's text in `mode`: as much of the label's colour as the contrast floor allows. The foreground alone always clears it. */
42
+ function chipText(color, mode) {
43
+ const label = rgbOf(color);
44
+ const foreground = rgbOf(PALETTE[mode].foreground);
45
+ const fill = chipFill(color, mode);
46
+ for (let share = TEXT_SHARE; share > 0; share -= .05) {
47
+ const text = hexOf(mixed(label, foreground, share));
48
+ if (contrastRatio(text, fill) >= 4.5) return text;
49
+ }
50
+ return PALETTE[mode].foreground;
51
+ }
52
+ /** A soft tint of a tracker's label colour with its name readable in both modes; none, or one that isn't a colour, keeps the Badge's neutral style. */
53
+ const tint = (color) => color && rgbOf(color) ? {
54
+ backgroundColor: `color-mix(in srgb, ${color} ${FILL * 100}%, transparent)`,
55
+ color: `light-dark(${chipText(color, "light")}, ${chipText(color, "dark")})`,
56
+ boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${color} 40%, transparent)`
57
+ } : void 0;
58
+ export { CONTRAST_FLOOR, PALETTE, chipFill, chipText, contrastRatio, tint };
59
+
60
+ //# sourceMappingURL=LabelTint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LabelTint.js","names":[],"sources":["../../src/display/LabelTint.ts"],"sourcesContent":["// A tracker's label colour (GitHub's, say) as a chip's style. A label's colour says nothing about what it sits on, so the text starts from a\n// mix with the foreground and moves towards the foreground, in each mode, until it reaches the contrast a chip's name needs.\n\ntype Rgb = readonly [number, number, number];\ntype Mode = 'light' | 'dark';\n\n/** WCAG AA for text this small. */\nexport const CONTRAST_FLOOR = 4.5;\n\n/** The palette's foreground, and the surface a chip's text contrasts least with: the accent a hovered or picked row fills with. */\nexport const PALETTE: Record<Mode, { foreground: string; surface: string }> = {\n light: { foreground: '#27272a', surface: '#f4f4f5' },\n dark: { foreground: '#f5f5f5', surface: '#161616' },\n};\n\nconst FILL = 0.16;\nconst TEXT_SHARE = 0.55;\n\nconst rgbOf = (hex: string): Rgb | null => {\n const digits = /^#?([0-9a-f]{6})$/i.exec(hex)?.[1];\n\n return digits ? ([0, 2, 4].map((at) => parseInt(digits.slice(at, at + 2), 16)) as unknown as Rgb) : null;\n};\nconst mixed = (a: Rgb, b: Rgb, share: number): Rgb =>\n a.map((part, at) => part * share + b[at]! * (1 - share)) as unknown as Rgb;\nconst hexOf = (color: Rgb) => `#${color.map((part) => Math.round(part).toString(16).padStart(2, '0')).join('')}`;\n\nconst luminance = (color: Rgb): number => {\n const [r, g, b] = color.map((part) => {\n const linear = part / 255;\n\n return linear <= 0.03928 ? linear / 12.92 : ((linear + 0.055) / 1.055) ** 2.4;\n }) as unknown as Rgb;\n\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n};\n\n/** The WCAG contrast ratio of two colours. */\nexport function contrastRatio(a: string, b: string): number {\n const [lighter, darker] = [luminance(rgbOf(a)!), luminance(rgbOf(b)!)].sort((x, y) => y - x) as [number, number];\n\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/** A chip's fill in `mode`, as tint's `color-mix` paints it over the palette's surface. */\nexport const chipFill = (color: string, mode: Mode): string =>\n hexOf(mixed(rgbOf(color)!, rgbOf(PALETTE[mode].surface)!, FILL));\n\n/** A chip's text in `mode`: as much of the label's colour as the contrast floor allows. The foreground alone always clears it. */\nexport function chipText(color: string, mode: Mode): string {\n const label = rgbOf(color)!;\n const foreground = rgbOf(PALETTE[mode].foreground)!;\n const fill = chipFill(color, mode);\n\n for (let share = TEXT_SHARE; share > 0; share -= 0.05) {\n const text = hexOf(mixed(label, foreground, share));\n\n if (contrastRatio(text, fill) >= CONTRAST_FLOOR) return text;\n }\n\n return PALETTE[mode].foreground;\n}\n\n/** A soft tint of a tracker's label colour with its name readable in both modes; none, or one that isn't a colour, keeps the Badge's neutral style. */\nexport const tint = (color: string | undefined) =>\n color && rgbOf(color)\n ? {\n backgroundColor: `color-mix(in srgb, ${color} ${FILL * 100}%, transparent)`,\n color: `light-dark(${chipText(color, 'light')}, ${chipText(color, 'dark')})`,\n boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${color} 40%, transparent)`,\n }\n : undefined;\n"],"mappings":";;AAOA,MAAa,iBAAiB;;AAG9B,MAAa,UAAiE;CAC1E,OAAO;EAAE,YAAY;EAAW,SAAS;CAAU;CACnD,MAAM;EAAE,YAAY;EAAW,SAAS;CAAU;AACtD;AAEA,MAAM,OAAO;AACb,MAAM,aAAa;AAEnB,MAAM,SAAS,QAA4B;CACvC,MAAM,SAAS,qBAAqB,KAAK,GAAG,CAAC,GAAG;CAEhD,OAAO,SAAU;EAAC;EAAG;EAAG;CAAC,CAAC,CAAC,KAAK,OAAO,SAAS,OAAO,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC,IAAuB;AACxG;AACA,MAAM,SAAS,GAAQ,GAAQ,UAC3B,EAAE,KAAK,MAAM,OAAO,OAAO,QAAQ,EAAE,OAAQ,IAAI,MAAM;AAC3D,MAAM,SAAS,UAAe,IAAI,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AAE7G,MAAM,aAAa,UAAuB;CACtC,MAAM,CAAC,GAAG,GAAG,KAAK,MAAM,KAAK,SAAS;EAClC,MAAM,SAAS,OAAO;EAEtB,OAAO,UAAU,SAAU,SAAS,UAAU,SAAS,QAAS,UAAU;CAC9E,CAAC;CAED,OAAO,QAAS,IAAI,QAAS,IAAI,QAAS;AAC9C;;AAGA,SAAgB,cAAc,GAAW,GAAmB;CACxD,MAAM,CAAC,SAAS,UAAU,CAAC,UAAU,MAAM,CAAC,CAAE,GAAG,UAAU,MAAM,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAE3F,QAAQ,UAAU,QAAS,SAAS;AACxC;;AAGA,MAAa,YAAY,OAAe,SACpC,MAAM,MAAM,MAAM,KAAK,GAAI,MAAM,QAAQ,KAAK,CAAC,OAAO,GAAI,IAAI,CAAC;;AAGnE,SAAgB,SAAS,OAAe,MAAoB;CACxD,MAAM,QAAQ,MAAM,KAAK;CACzB,MAAM,aAAa,MAAM,QAAQ,KAAK,CAAC,UAAU;CACjD,MAAM,OAAO,SAAS,OAAO,IAAI;CAEjC,KAAK,IAAI,QAAQ,YAAY,QAAQ,GAAG,SAAS,KAAM;EACnD,MAAM,OAAO,MAAM,MAAM,OAAO,YAAY,KAAK,CAAC;EAElD,IAAI,cAAc,MAAM,IAAI,KAAA,KAAqB,OAAO;CAC5D;CAEA,OAAO,QAAQ,KAAK,CAAC;AACzB;;AAGA,MAAa,QAAQ,UACjB,SAAS,MAAM,KAAK,IACd;CACI,iBAAiB,sBAAsB,MAAM,GAAG,OAAO,IAAI;CAC3D,OAAO,cAAc,SAAS,OAAO,OAAO,EAAE,IAAI,SAAS,OAAO,MAAM,EAAE;CAC1E,WAAW,sCAAsC,MAAM;AAC3D,IACA,KAAA"}
@@ -0,0 +1,5 @@
1
+ /** A person: their avatar and name, the name wrapping. */
2
+ export declare function Person({ name }: {
3
+ name: string;
4
+ }): import("react").JSX.Element;
5
+ //# sourceMappingURL=Person.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { Avatar } from "./Avatar.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ // src/display/Person.tsx
4
+ /** A person: their avatar and name, the name wrapping. */
5
+ function Person({ name }) {
6
+ return /* @__PURE__ */ jsxs("span", {
7
+ className: "inline-flex max-w-full min-w-0 items-center gap-1.5",
8
+ children: [/* @__PURE__ */ jsx(Avatar, {
9
+ name,
10
+ compact: true
11
+ }), /* @__PURE__ */ jsx("span", {
12
+ className: "min-w-0 wrap-anywhere",
13
+ children: name
14
+ })]
15
+ });
16
+ }
17
+ export { Person };
18
+
19
+ //# sourceMappingURL=Person.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Person.js","names":[],"sources":["../../src/display/Person.tsx"],"sourcesContent":["import { Avatar } from './Avatar';\n\n/** A person: their avatar and name, the name wrapping. */\nexport function Person({ name }: { name: string }) {\n return (\n <span className=\"inline-flex max-w-full min-w-0 items-center gap-1.5\">\n <Avatar name={name} compact />\n <span className=\"min-w-0 wrap-anywhere\">{name}</span>\n </span>\n );\n}\n"],"mappings":";;;;AAGA,SAAgB,OAAO,EAAE,QAA0B;CAC/C,OACI,qBAAC,QAAD;EAAM,WAAU;EAAhB,UAAA,CACI,oBAAC,QAAD;GAAc;GAAM,SAAA;EAAS,CAAA,GAC7B,oBAAC,QAAD;GAAM,WAAU;GAAyB,UAAA;EAAW,CAAA,CAClD;;AAEd"}
@@ -3,8 +3,8 @@ import { Heading, Text } from "../typography/Typography.js";
3
3
  import { BadgeList } from "./BadgeList.js";
4
4
  import { InsetPanel } from "./InsetPanel.js";
5
5
  import { useId } from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
6
  import { ChevronDownIcon } from "lucide-react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
8
  // src/display/PropertySheet.tsx
9
9
  /** A titled sheet of facts about one thing; the body is label/value rows, a row of tags, or a short note. */
10
10
  function PropertySheetRoot({ children, loading = false, loadingLabel, title }) {
@@ -1,9 +1,16 @@
1
1
  import { ReactNode } from "react";
2
- export declare function RadioChoice({ name, checked, onChange, children, trailing }: {
2
+ type DataAttributes = {
3
+ [key: `data-${string}`]: string | undefined;
4
+ };
5
+ /** One choice of a group of radios, a row of an InsetPanel's `settings` panel: the radio and its content, which can
6
+ * shrink so a long title in it truncates, then any `trailing` content. Data attributes, such as the value it names,
7
+ * go on the row. */
8
+ export declare function RadioChoice({ name, checked, onChange, children, trailing, ...data }: {
3
9
  name: string;
4
10
  checked: boolean;
5
11
  onChange: () => void;
6
12
  children: ReactNode;
7
13
  trailing?: ReactNode;
8
- }): import("react").JSX.Element;
14
+ } & DataAttributes): import("react").JSX.Element;
15
+ export {};
9
16
  //# sourceMappingURL=RadioChoice.d.ts.map
@@ -1,8 +1,12 @@
1
1
  import { tabbable } from "../foundations/KeyboardFocus.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  // src/display/RadioChoice.tsx
4
- function RadioChoice({ name, checked, onChange, children, trailing }) {
4
+ /** One choice of a group of radios, a row of an InsetPanel's `settings` panel: the radio and its content, which can
5
+ * shrink so a long title in it truncates, then any `trailing` content. Data attributes, such as the value it names,
6
+ * go on the row. */
7
+ function RadioChoice({ name, checked, onChange, children, trailing, ...data }) {
5
8
  return /* @__PURE__ */ jsxs("div", {
9
+ ...data,
6
10
  className: "hover:bg-base-100 has-checked:bg-primary/10 has-focus-visible:ring-primary flex min-w-0 items-center gap-3 transition-colors has-focus-visible:ring-2 has-focus-visible:ring-inset has-disabled:opacity-60",
7
11
  children: [/* @__PURE__ */ jsxs("label", {
8
12
  className: "flex min-w-0 flex-1 cursor-pointer items-center gap-3 px-4 py-3 has-disabled:cursor-default",
@@ -1 +1 @@
1
- {"version":3,"file":"RadioChoice.js","names":[],"sources":["../../src/display/RadioChoice.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { tabbable } from '../foundations/KeyboardFocus';\n\nexport function RadioChoice({\n name,\n checked,\n onChange,\n children,\n trailing,\n}: {\n name: string;\n checked: boolean;\n onChange: () => void;\n children: ReactNode;\n trailing?: ReactNode;\n}) {\n return (\n <div className=\"hover:bg-base-100 has-checked:bg-primary/10 has-focus-visible:ring-primary flex min-w-0 items-center gap-3 transition-colors has-focus-visible:ring-2 has-focus-visible:ring-inset has-disabled:opacity-60\">\n <label className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-3 px-4 py-3 has-disabled:cursor-default\">\n <input\n {...tabbable}\n type=\"radio\"\n name={name}\n checked={checked}\n onChange={onChange}\n className=\"accent-primary size-4 shrink-0\"\n />\n <span className=\"min-w-0 flex-1\">{children}</span>\n </label>\n {trailing ? <div className=\"flex shrink-0 items-center gap-3 pr-4\">{trailing}</div> : null}\n </div>\n );\n}\n"],"mappings":";;;AAIA,SAAgB,YAAY,EACxB,MACA,SACA,UACA,UACA,YAOD;CACC,OACI,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACI,qBAAC,SAAD;GAAO,WAAU;GAAjB,UAAA,CACI,oBAAC,SAAD;IACI,GAAI;IACJ,MAAK;IACC;IACG;IACC;IACV,WAAU;GACb,CAAA,GACD,oBAAC,QAAD;IAAM,WAAU;IAAkB;GAAe,CAAA,CAC9C;EACN,CAAA,GAAA,WAAW,oBAAC,OAAD;GAAK,WAAU;GAAyC,UAAA;EAAc,CAAA,IAAI,IACrF;;AAEb"}
1
+ {"version":3,"file":"RadioChoice.js","names":[],"sources":["../../src/display/RadioChoice.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { tabbable } from '../foundations/KeyboardFocus';\n\ntype DataAttributes = { [key: `data-${string}`]: string | undefined };\n\n/** One choice of a group of radios, a row of an InsetPanel's `settings` panel: the radio and its content, which can\n * shrink so a long title in it truncates, then any `trailing` content. Data attributes, such as the value it names,\n * go on the row. */\nexport function RadioChoice({\n name,\n checked,\n onChange,\n children,\n trailing,\n ...data\n}: {\n name: string;\n checked: boolean;\n onChange: () => void;\n children: ReactNode;\n trailing?: ReactNode;\n} & DataAttributes) {\n return (\n <div\n {...data}\n className=\"hover:bg-base-100 has-checked:bg-primary/10 has-focus-visible:ring-primary flex min-w-0 items-center gap-3 transition-colors has-focus-visible:ring-2 has-focus-visible:ring-inset has-disabled:opacity-60\"\n >\n <label className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-3 px-4 py-3 has-disabled:cursor-default\">\n <input\n {...tabbable}\n type=\"radio\"\n name={name}\n checked={checked}\n onChange={onChange}\n className=\"accent-primary size-4 shrink-0\"\n />\n <span className=\"min-w-0 flex-1\">{children}</span>\n </label>\n {trailing ? <div className=\"flex shrink-0 items-center gap-3 pr-4\">{trailing}</div> : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AASA,SAAgB,YAAY,EACxB,MACA,SACA,UACA,UACA,UACA,GAAG,QAOa;CAChB,OACI,qBAAC,OAAD;EACI,GAAI;EACJ,WAAU;EAFd,UAAA,CAII,qBAAC,SAAD;GAAO,WAAU;GAAjB,UAAA,CACI,oBAAC,SAAD;IACI,GAAI;IACJ,MAAK;IACC;IACG;IACC;IACV,WAAU;GACb,CAAA,GACD,oBAAC,QAAD;IAAM,WAAU;IAAkB;GAAe,CAAA,CAC9C;EACN,CAAA,GAAA,WAAW,oBAAC,OAAD;GAAK,WAAU;GAAyC,UAAA;EAAc,CAAA,IAAI,IACrF;;AAEb"}
@@ -1,7 +1,7 @@
1
1
  import { Link } from "../typography/Link.js";
2
2
  import { Text } from "../typography/Typography.js";
3
- import { jsx, jsxs } from "react/jsx-runtime";
4
3
  import { CheckIcon } from "lucide-react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
5
  // src/display/RatingLink.tsx
6
6
  /** The sources' own marks and colors, as the Apple apps draw them. Anything else reads by its name. */
7
7
  function ratingMark(source) {
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from "react";
2
+ export type RichTextFormat = 'markdown' | 'html';
3
+ interface RichTextProps {
4
+ text: string;
5
+ format: RichTextFormat;
6
+ /** Draws each fenced ```mermaid block of Markdown, such as with `Diagram`, between the text around it. */
7
+ renderDiagram?: (source: string) => ReactNode;
8
+ }
9
+ /** A provider's text, sanitized and styled; with `renderDiagram`, Markdown's Mermaid blocks draw as diagrams. */
10
+ export declare function RichText({ text, format, renderDiagram }: RichTextProps): import("react").JSX.Element | null;
11
+ export {};
12
+ //# sourceMappingURL=RichText.d.ts.map
@@ -0,0 +1,94 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { toJsxRuntime } from "hast-util-to-jsx-runtime";
3
+ import Markdown from "react-markdown";
4
+ import rehypeParse from "rehype-parse";
5
+ import rehypeRaw from "rehype-raw";
6
+ import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
7
+ import remarkGfm from "remark-gfm";
8
+ import { unified } from "unified";
9
+ // src/display/RichText.tsx
10
+ const link = (properties, children) => ({
11
+ type: "element",
12
+ tagName: "a",
13
+ properties: {
14
+ ...properties,
15
+ target: "_blank",
16
+ rel: ["noopener", "noreferrer"]
17
+ },
18
+ children
19
+ });
20
+ /** Turns every image into a link to it and gives every link a new tab. An image inside a link, or without a
21
+ * usable source, becomes its text, since a link cannot hold a link. */
22
+ function rehypeImagesAsLinks() {
23
+ const walk = (node, inLink) => {
24
+ node.children = node.children.map((child) => {
25
+ if (child.type !== "element") return child;
26
+ if (child.tagName === "img") {
27
+ const src = typeof child.properties.src === "string" ? child.properties.src : "";
28
+ const text = {
29
+ type: "text",
30
+ value: String(child.properties.alt || src)
31
+ };
32
+ return src && !inLink ? link({ href: src }, [text]) : text;
33
+ }
34
+ walk(child, inLink || child.tagName === "a");
35
+ return child.tagName === "a" ? link(child.properties, child.children) : child;
36
+ });
37
+ };
38
+ return (tree) => walk(tree, false);
39
+ }
40
+ const schema = {
41
+ ...defaultSchema,
42
+ strip: [...defaultSchema.strip ?? [], "style"]
43
+ };
44
+ const rehypePlugins = [
45
+ rehypeRaw,
46
+ [rehypeSanitize, schema],
47
+ rehypeImagesAsLinks
48
+ ];
49
+ const htmlProcessor = unified().use(rehypeParse, { fragment: true }).use(rehypeSanitize, schema).use(rehypeImagesAsLinks);
50
+ const body = [
51
+ "min-w-0 max-w-full text-sm leading-relaxed break-words [overflow-wrap:anywhere]",
52
+ "[&>:first-child]:mt-0 [&>:last-child]:mb-0 [&_p]:my-2 [&_ul]:my-2 [&_ol]:my-2 [&_blockquote]:my-2",
53
+ "[&_h1]:mt-4 [&_h1]:mb-2 [&_h1]:text-lg [&_h1]:font-semibold [&_h2]:mt-4 [&_h2]:mb-2 [&_h2]:text-base [&_h2]:font-semibold",
54
+ "[&_h3]:mt-3 [&_h3]:mb-1.5 [&_h3]:font-semibold [&_h4]:mt-3 [&_h4]:mb-1.5 [&_h4]:font-semibold [&_h5]:font-semibold [&_h6]:font-semibold",
55
+ "[&_ul]:list-disc [&_ul]:ps-6 [&_ol]:list-decimal [&_ol]:ps-6 [&_li]:my-0.5 [&_.task-list-item]:list-none [&_.task-list-item]:ms-[-1.5rem] [&_input]:me-1.5",
56
+ "[&_a]:text-(--lar-info-text) [&_a]:underline [&_a]:underline-offset-2",
57
+ "[&_blockquote]:border-s-2 [&_blockquote]:ps-3 [&_blockquote]:text-base-700",
58
+ "[&_hr]:my-4",
59
+ "[&_pre]:my-2 [&_pre]:max-w-full [&_pre]:overflow-x-hidden [&_pre]:whitespace-pre-wrap [&_pre]:rounded-md [&_pre]:bg-base-200 [&_pre]:p-3 [&_pre]:font-mono [&_pre]:text-xs",
60
+ "[&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-base-200 [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-xs",
61
+ "[&_table]:my-2 [&_table]:w-full [&_table]:max-w-full [&_table]:table-fixed [&_th]:border [&_th]:px-2 [&_th]:py-1 [&_th]:text-start [&_td]:border [&_td]:px-2 [&_td]:py-1",
62
+ "[&_details]:my-2 [&_summary]:cursor-pointer [&_summary]:font-medium"
63
+ ].join(" ");
64
+ /** A provider's text, sanitized and styled; with `renderDiagram`, Markdown's Mermaid blocks draw as diagrams. */
65
+ function RichText({ text, format, renderDiagram }) {
66
+ if (text === "") return null;
67
+ if (renderDiagram && format === "markdown") {
68
+ const parts = text.split(/```mermaid[^\S\r\n]*\r?\n([\s\S]*?)```/g);
69
+ if (parts.length > 1) return /* @__PURE__ */ jsx("div", {
70
+ className: "grid min-w-0 gap-3",
71
+ "data-slot": "rich-text-with-diagrams",
72
+ children: parts.map((part, index) => index % 2 === 1 ? /* @__PURE__ */ jsx(Fragment, { children: renderDiagram(part.trim()) }, index) : part.trim() ? /* @__PURE__ */ jsx(RichText, {
73
+ text: part,
74
+ format: "markdown"
75
+ }, index) : null)
76
+ });
77
+ }
78
+ return /* @__PURE__ */ jsx("div", {
79
+ className: body,
80
+ "data-slot": "rich-text",
81
+ children: format === "markdown" ? /* @__PURE__ */ jsx(Markdown, {
82
+ rehypePlugins,
83
+ remarkPlugins: [remarkGfm],
84
+ children: text
85
+ }) : toJsxRuntime(htmlProcessor.runSync(htmlProcessor.parse(text)), {
86
+ Fragment,
87
+ jsx,
88
+ jsxs
89
+ })
90
+ });
91
+ }
92
+ export { RichText };
93
+
94
+ //# sourceMappingURL=RichText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichText.js","names":[],"sources":["../../src/display/RichText.tsx"],"sourcesContent":["// Renders a GitHub or Azure DevOps description or comment the way the provider shows it. Markdown is\n// GitHub-flavoured and may hold raw HTML; an Azure DevOps field may be HTML. Both go through the same\n// sanitizer, then images become links (the page never loads a remote image) and links open in a new tab. The output\n// never makes its container scroll sideways.\nimport type { Element, ElementContent, Root } from 'hast';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport type { ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport { Fragment, jsx, jsxs } from 'react/jsx-runtime';\nimport rehypeParse from 'rehype-parse';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize';\nimport remarkGfm from 'remark-gfm';\nimport { unified } from 'unified';\nimport type { PluggableList } from 'unified';\n\nexport type RichTextFormat = 'markdown' | 'html';\n\nconst link = (properties: Element['properties'], children: ElementContent[]): Element => ({\n type: 'element',\n tagName: 'a',\n properties: { ...properties, target: '_blank', rel: ['noopener', 'noreferrer'] },\n children,\n});\n\n/** Turns every image into a link to it and gives every link a new tab. An image inside a link, or without a\n * usable source, becomes its text, since a link cannot hold a link. */\nfunction rehypeImagesAsLinks() {\n const walk = (node: Root | Element, inLink: boolean): void => {\n node.children = node.children.map((child) => {\n if (child.type !== 'element') return child;\n\n if (child.tagName === 'img') {\n const src = typeof child.properties.src === 'string' ? child.properties.src : '';\n const text: ElementContent = { type: 'text', value: String(child.properties.alt || src) };\n\n return src && !inLink ? link({ href: src }, [text]) : text;\n }\n\n walk(child, inLink || child.tagName === 'a');\n\n return child.tagName === 'a' ? link(child.properties, child.children) : child;\n });\n };\n\n return (tree: Root) => walk(tree, false);\n}\n\n// The default schema is GitHub's: it keeps <details>, tables and task-list checkboxes and drops scripts,\n// handlers, javascript: URLs, iframes and styles. It keeps a dropped <style>'s text, so strip that element whole.\nconst schema = { ...defaultSchema, strip: [...(defaultSchema.strip ?? []), 'style'] };\nconst rehypePlugins: PluggableList = [rehypeRaw, [rehypeSanitize, schema], rehypeImagesAsLinks];\nconst htmlProcessor = unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeSanitize, schema)\n .use(rehypeImagesAsLinks);\n\n// Tailwind has no typography plugin and its preflight resets headings, lists and tables, so the elements a\n// provider's text holds are styled here.\nconst body = [\n 'min-w-0 max-w-full text-sm leading-relaxed break-words [overflow-wrap:anywhere]',\n '[&>:first-child]:mt-0 [&>:last-child]:mb-0 [&_p]:my-2 [&_ul]:my-2 [&_ol]:my-2 [&_blockquote]:my-2',\n '[&_h1]:mt-4 [&_h1]:mb-2 [&_h1]:text-lg [&_h1]:font-semibold [&_h2]:mt-4 [&_h2]:mb-2 [&_h2]:text-base [&_h2]:font-semibold',\n '[&_h3]:mt-3 [&_h3]:mb-1.5 [&_h3]:font-semibold [&_h4]:mt-3 [&_h4]:mb-1.5 [&_h4]:font-semibold [&_h5]:font-semibold [&_h6]:font-semibold',\n '[&_ul]:list-disc [&_ul]:ps-6 [&_ol]:list-decimal [&_ol]:ps-6 [&_li]:my-0.5 [&_.task-list-item]:list-none [&_.task-list-item]:ms-[-1.5rem] [&_input]:me-1.5',\n '[&_a]:text-(--lar-info-text) [&_a]:underline [&_a]:underline-offset-2',\n '[&_blockquote]:border-s-2 [&_blockquote]:ps-3 [&_blockquote]:text-base-700',\n '[&_hr]:my-4',\n '[&_pre]:my-2 [&_pre]:max-w-full [&_pre]:overflow-x-hidden [&_pre]:whitespace-pre-wrap [&_pre]:rounded-md [&_pre]:bg-base-200 [&_pre]:p-3 [&_pre]:font-mono [&_pre]:text-xs',\n '[&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-base-200 [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-xs',\n '[&_table]:my-2 [&_table]:w-full [&_table]:max-w-full [&_table]:table-fixed [&_th]:border [&_th]:px-2 [&_th]:py-1 [&_th]:text-start [&_td]:border [&_td]:px-2 [&_td]:py-1',\n '[&_details]:my-2 [&_summary]:cursor-pointer [&_summary]:font-medium',\n].join(' ');\n\ninterface RichTextProps {\n text: string;\n format: RichTextFormat;\n /** Draws each fenced ```mermaid block of Markdown, such as with `Diagram`, between the text around it. */\n renderDiagram?: (source: string) => ReactNode;\n}\n\n/** A provider's text, sanitized and styled; with `renderDiagram`, Markdown's Mermaid blocks draw as diagrams. */\nexport function RichText({ text, format, renderDiagram }: RichTextProps) {\n if (text === '') return null;\n\n if (renderDiagram && format === 'markdown') {\n const parts = text.split(/```mermaid[^\\S\\r\\n]*\\r?\\n([\\s\\S]*?)```/g);\n\n if (parts.length > 1)\n return (\n <div className=\"grid min-w-0 gap-3\" data-slot=\"rich-text-with-diagrams\">\n {parts.map((part, index) =>\n index % 2 === 1 ? (\n <Fragment key={index}>{renderDiagram(part.trim())}</Fragment>\n ) : part.trim() ? (\n <RichText key={index} text={part} format=\"markdown\" />\n ) : null,\n )}\n </div>\n );\n }\n\n return (\n <div className={body} data-slot=\"rich-text\">\n {format === 'markdown' ? (\n <Markdown rehypePlugins={rehypePlugins} remarkPlugins={[remarkGfm]}>\n {text}\n </Markdown>\n ) : (\n toJsxRuntime(htmlProcessor.runSync(htmlProcessor.parse(text)), { Fragment, jsx, jsxs })\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAkBA,MAAM,QAAQ,YAAmC,cAAyC;CACtF,MAAM;CACN,SAAS;CACT,YAAY;EAAE,GAAG;EAAY,QAAQ;EAAU,KAAK,CAAC,YAAY,YAAY;CAAE;CAC/E;AACJ;;;AAIA,SAAS,sBAAsB;CAC3B,MAAM,QAAQ,MAAsB,WAA0B;EAC1D,KAAK,WAAW,KAAK,SAAS,KAAK,UAAU;GACzC,IAAI,MAAM,SAAS,WAAW,OAAO;GAErC,IAAI,MAAM,YAAY,OAAO;IACzB,MAAM,MAAM,OAAO,MAAM,WAAW,QAAQ,WAAW,MAAM,WAAW,MAAM;IAC9E,MAAM,OAAuB;KAAE,MAAM;KAAQ,OAAO,OAAO,MAAM,WAAW,OAAO,GAAG;IAAE;IAExF,OAAO,OAAO,CAAC,SAAS,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI;GAC1D;GAEA,KAAK,OAAO,UAAU,MAAM,YAAY,GAAG;GAE3C,OAAO,MAAM,YAAY,MAAM,KAAK,MAAM,YAAY,MAAM,QAAQ,IAAI;EAC5E,CAAC;CACL;CAEA,QAAQ,SAAe,KAAK,MAAM,KAAK;AAC3C;AAIA,MAAM,SAAS;CAAE,GAAG;CAAe,OAAO,CAAC,GAAI,cAAc,SAAS,CAAC,GAAI,OAAO;AAAE;AACpF,MAAM,gBAA+B;CAAC;CAAW,CAAC,gBAAgB,MAAM;CAAG;AAAmB;AAC9F,MAAM,gBAAgB,QAAQ,CAAC,CAC1B,IAAI,aAAa,EAAE,UAAU,KAAK,CAAC,CAAC,CACpC,IAAI,gBAAgB,MAAM,CAAC,CAC3B,IAAI,mBAAmB;AAI5B,MAAM,OAAO;CACT;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ,CAAC,CAAC,KAAK,GAAG;;AAUV,SAAgB,SAAS,EAAE,MAAM,QAAQ,iBAAgC;CACrE,IAAI,SAAS,IAAI,OAAO;CAExB,IAAI,iBAAiB,WAAW,YAAY;EACxC,MAAM,QAAQ,KAAK,MAAM,yCAAyC;EAElE,IAAI,MAAM,SAAS,GACf,OACI,oBAAC,OAAD;GAAK,WAAU;GAAqB,aAAU;GACzC,UAAA,MAAM,KAAK,MAAM,UACd,QAAQ,MAAM,IACV,oBAAC,UAAD,EAAA,UAAuB,cAAc,KAAK,KAAK,CAAC,EAAY,GAA7C,KAA6C,IAC5D,KAAK,KAAK,IACV,oBAAC,UAAD;IAAsB,MAAM;IAAM,QAAO;GAAY,GAAtC,KAAsC,IACrD,IACR;EACC,CAAA;CAEjB;CAEA,OACI,oBAAC,OAAD;EAAK,WAAW;EAAM,aAAU;EAC3B,UAAA,WAAW,aACR,oBAAC,UAAD;GAAyB;GAAe,eAAe,CAAC,SAAS;GAC5D,UAAA;EACK,CAAA,IAEV,aAAa,cAAc,QAAQ,cAAc,MAAM,IAAI,CAAC,GAAG;GAAE;GAAU;GAAK;EAAK,CAAC;CAEzF,CAAA;AAEb"}
@@ -1,8 +1,8 @@
1
1
  import { LinkBox, LinkOverlay } from "../typography/Link.js";
2
2
  import { Text } from "../typography/Typography.js";
3
3
  import { toneTileClasses } from "./ToneTile.js";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
4
  import { ChevronRightIcon } from "lucide-react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  // src/display/RowList.tsx
7
7
  /** Rows of one list inside a single bordered panel, separated by rules; or ruled rows in two columns on wide screens. */
8
8
  function RowList({ children, label, layout = "panel" }) {
@@ -8,11 +8,13 @@ import { BrandLink, BrandMark } from "./BrandMark.js";
8
8
  import { ChangeList, ChangeListItem } from "./ChangeList.js";
9
9
  import { CheckList, CheckListItem } from "./CheckList.js";
10
10
  import { CodeBlock } from "./CodeBlock.js";
11
+ import { Comment, CommentList } from "./Comment.js";
11
12
  import { CopyButton } from "./CopyButton.js";
12
13
  import { DataTable, DataTableCell, DataTableRow } from "./DataTable.js";
13
14
  import { DetailHero, DetailHeroDetail, DetailHeroDetails, DetailHeroTags } from "./DetailHero.js";
14
15
  import { DetailList } from "./DetailList.js";
15
16
  import { DeviceCard } from "./DeviceCard.js";
17
+ import { Diagram } from "./Diagram.js";
16
18
  import { Identity } from "./Identity.js";
17
19
  import { ImageCard } from "./ImageCard.js";
18
20
  import { ImagePicker, ImagePickerGrid, ImagePickerOption, ImageUpload } from "./ImagePicker.js";
@@ -20,19 +22,22 @@ import { InfoBox } from "./InfoBox.js";
20
22
  import { InsetPanel } from "./InsetPanel.js";
21
23
  import { Kbd } from "./Kbd.js";
22
24
  import { KindIcon } from "./KindIcon.js";
25
+ import { LabelChip } from "./LabelChip.js";
23
26
  import { NoticeCard } from "./NoticeCard.js";
24
27
  import { PairingList, PairingListItem } from "./PairingList.js";
25
28
  import { PathList } from "./PathList.js";
26
29
  import { PeoplePreview } from "./PeoplePreview.js";
30
+ import { Person } from "./Person.js";
27
31
  import { PropertySheet, PropertySheetRow, PropertySheetTag } from "./PropertySheet.js";
28
32
  import { QrCode } from "./QrCode.js";
29
33
  import { RadioChoice } from "./RadioChoice.js";
30
34
  import { RatingLink } from "./RatingLink.js";
31
35
  import { ResourceCard, ResourceCardSkeleton } from "./ResourceCard.js";
36
+ import { RichText, RichTextFormat } from "./RichText.js";
32
37
  import { RowList, RowListItem } from "./RowList.js";
33
38
  import { MeterLegend, MeterSegment, MeterTone, StackedMeter } from "./StackedMeter.js";
34
39
  import { StatTile } from "./StatTile.js";
35
40
  import { StepList } from "./StepList.js";
36
41
  import { TextPreview } from "./TextPreview.js";
37
42
  import { TimeSeriesChart, TimeSeriesChartSkeleton, TimeSeriesPoint } from "./TimeSeriesChart.js";
38
- export { ActivityCard, ActivityCardSkeleton, Artwork, Avatar, Badge, BadgeList, type BadgeListItem, type BadgeProps, BrandLink, BrandMark, ChangeList, type ChangeListItem, CheckList, type CheckListItem, CodeBlock, CopyButton, DataTable, type DataTableCell, type DataTableRow, DetailHero, DetailHeroDetail, DetailHeroDetails, DetailHeroTags, DetailList, DeviceCard, Identity, ImageCard, ImagePicker, ImagePickerGrid, ImagePickerOption, ImageUpload, InfoBox, InsetPanel, ItemAction, Kbd, KindIcon, MeterLegend, type MeterSegment, type MeterTone, NoticeCard, PairingList, type PairingListItem, PathList, PeoplePreview, PropertySheet, type PropertySheetRow, type PropertySheetTag, QrCode, RadioChoice, RatingLink, ResourceCard, ResourceCardSkeleton, RowList, RowListItem, StackedMeter, StatTile, StepList, TextPreview, TimeSeriesChart, TimeSeriesChartSkeleton, type TimeSeriesPoint };
43
+ export { ActivityCard, ActivityCardSkeleton, Artwork, Avatar, Badge, BadgeList, type BadgeListItem, type BadgeProps, BrandLink, BrandMark, ChangeList, type ChangeListItem, CheckList, type CheckListItem, CodeBlock, Comment, CommentList, CopyButton, DataTable, type DataTableCell, type DataTableRow, DetailHero, DetailHeroDetail, DetailHeroDetails, DetailHeroTags, DetailList, DeviceCard, Diagram, Identity, ImageCard, ImagePicker, ImagePickerGrid, ImagePickerOption, ImageUpload, InfoBox, InsetPanel, ItemAction, Kbd, KindIcon, LabelChip, MeterLegend, type MeterSegment, type MeterTone, NoticeCard, PairingList, type PairingListItem, PathList, PeoplePreview, Person, PropertySheet, type PropertySheetRow, type PropertySheetTag, QrCode, RadioChoice, RatingLink, ResourceCard, ResourceCardSkeleton, RichText, type RichTextFormat, RowList, RowListItem, StackedMeter, StatTile, StepList, TextPreview, TimeSeriesChart, TimeSeriesChartSkeleton, type TimeSeriesPoint };
@@ -1,5 +1,5 @@
1
- import { jsx } from "react/jsx-runtime";
2
1
  import { Alert } from "@ninna-ui/feedback";
2
+ import { jsx } from "react/jsx-runtime";
3
3
  // src/feedback/Alert.tsx
4
4
  /**
5
5
  * An immediate status about a condition or operation. Compact notes can hold short inline guidance.
@@ -1,7 +1,7 @@
1
1
  import { Button } from "../actions/Button.js";
2
2
  import { SkeletonLoader } from "./SkeletonLoader.js";
3
- import { jsx } from "react/jsx-runtime";
4
3
  import { Alert } from "@ninna-ui/feedback";
4
+ import { jsx } from "react/jsx-runtime";
5
5
  // src/feedback/AsyncState.tsx
6
6
  /** Owns a region's loading geometry and load failure; use Alert for other operation feedback. */
7
7
  function AsyncState({ error, errorTitle, label, loading, onRetry, presentation = "card", placeholder, retryLabel, retrying = false }) {
@@ -0,0 +1,12 @@
1
+ import { MouseEvent } from "react";
2
+ /**
3
+ * The close button every failure, warning and notification carries; `label` names what it closes, such as
4
+ * "Dismiss: Moved #61". In the `corner` it floats to the top right of the text it closes; `inline` sits in a line of
5
+ * text, after an error message.
6
+ */
7
+ export declare function DismissButton({ label, onClick, placement }: {
8
+ label: string;
9
+ onClick: (event: MouseEvent<HTMLButtonElement>) => void;
10
+ placement?: 'corner' | 'inline';
11
+ }): import("react").JSX.Element;
12
+ //# sourceMappingURL=DismissButton.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { IconButton } from "../actions/IconButton.js";
2
+ import { XIcon } from "lucide-react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ // src/feedback/DismissButton.tsx
5
+ /**
6
+ * The close button every failure, warning and notification carries; `label` names what it closes, such as
7
+ * "Dismiss: Moved #61". In the `corner` it floats to the top right of the text it closes; `inline` sits in a line of
8
+ * text, after an error message.
9
+ */
10
+ function DismissButton({ label, onClick, placement = "corner" }) {
11
+ return /* @__PURE__ */ jsx(IconButton, {
12
+ className: `dismiss ${placement === "inline" ? "float-none -my-1 ml-0.5 align-middle" : "float-right -mt-0.75 -mr-1.5 ml-2"}`,
13
+ "aria-label": label,
14
+ icon: /* @__PURE__ */ jsx(XIcon, {}),
15
+ onClick
16
+ });
17
+ }
18
+ export { DismissButton };
19
+
20
+ //# sourceMappingURL=DismissButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DismissButton.js","names":[],"sources":["../../src/feedback/DismissButton.tsx"],"sourcesContent":["import { XIcon } from 'lucide-react';\nimport type { MouseEvent } from 'react';\n\nimport { IconButton } from '../actions/IconButton';\n\n/**\n * The close button every failure, warning and notification carries; `label` names what it closes, such as\n * \"Dismiss: Moved #61\". In the `corner` it floats to the top right of the text it closes; `inline` sits in a line of\n * text, after an error message.\n */\nexport function DismissButton({\n label,\n onClick,\n placement = 'corner',\n}: {\n label: string;\n onClick: (event: MouseEvent<HTMLButtonElement>) => void;\n placement?: 'corner' | 'inline';\n}) {\n return (\n <IconButton\n className={`dismiss ${placement === 'inline' ? 'float-none -my-1 ml-0.5 align-middle' : 'float-right -mt-0.75 -mr-1.5 ml-2'}`}\n aria-label={label}\n icon={<XIcon />}\n onClick={onClick}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,SAAgB,cAAc,EAC1B,OACA,SACA,YAAY,YAKb;CACC,OACI,oBAAC,YAAD;EACI,WAAW,WAAW,cAAc,WAAW,yCAAyC;EACxF,cAAY;EACZ,MAAM,oBAAC,OAAD,CAAQ,CAAA;EACL;CACZ,CAAA;AAET"}
@@ -1,7 +1,9 @@
1
+ import { forgetNotificationSlots } from "./Notifications.js";
1
2
  import { toast } from "@ninna-ui/feedback";
2
3
  // src/feedback/ErrorNotification.ts
3
4
  function dismissAllNotifications() {
4
5
  toast.dismissAll();
6
+ forgetNotificationSlots();
5
7
  }
6
8
  function showErrorNotification(notification) {
7
9
  toast.create({
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorNotification.js","names":[],"sources":["../../src/feedback/ErrorNotification.ts"],"sourcesContent":["import { toast } from '@ninna-ui/feedback';\n\nexport interface ErrorNotification {\n description: string;\n title: string;\n}\n\nexport function dismissAllNotifications(): void {\n toast.dismissAll();\n}\n\nexport function showErrorNotification(notification: ErrorNotification): void {\n toast.create({\n ...notification,\n color: 'danger',\n });\n}\n\nexport function showSuccessNotification(message: string): void {\n toast.create({\n color: 'success',\n title: message,\n });\n}\n"],"mappings":";;AAOA,SAAgB,0BAAgC;CAC5C,MAAM,WAAW;AACrB;AAEA,SAAgB,sBAAsB,cAAuC;CACzE,MAAM,OAAO;EACT,GAAG;EACH,OAAO;CACX,CAAC;AACL;AAEA,SAAgB,wBAAwB,SAAuB;CAC3D,MAAM,OAAO;EACT,OAAO;EACP,OAAO;CACX,CAAC;AACL"}
1
+ {"version":3,"file":"ErrorNotification.js","names":[],"sources":["../../src/feedback/ErrorNotification.ts"],"sourcesContent":["import { toast } from '@ninna-ui/feedback';\n\nimport { forgetNotificationSlots } from './Notifications';\n\nexport interface ErrorNotification {\n description: string;\n title: string;\n}\n\nexport function dismissAllNotifications(): void {\n toast.dismissAll();\n forgetNotificationSlots();\n}\n\nexport function showErrorNotification(notification: ErrorNotification): void {\n toast.create({\n ...notification,\n color: 'danger',\n });\n}\n\nexport function showSuccessNotification(message: string): void {\n toast.create({\n color: 'success',\n title: message,\n });\n}\n"],"mappings":";;;AASA,SAAgB,0BAAgC;CAC5C,MAAM,WAAW;CACjB,wBAAwB;AAC5B;AAEA,SAAgB,sBAAsB,cAAuC;CACzE,MAAM,OAAO;EACT,GAAG;EACH,OAAO;CACX,CAAC;AACL;AAEA,SAAgB,wBAAwB,SAAuB;CAC3D,MAAM,OAAO;EACT,OAAO;EACP,OAAO;CACX,CAAC;AACL"}
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from "react";
2
+ /**
3
+ * A form's result, such as a dialog's validation message or what its submit did. It stays mounted as a live region,
4
+ * so screen readers hear each new message; empty, it has no border, padding or icon. With no tone it is a warning, as
5
+ * a validation message is. Line breaks in `text` show.
6
+ */
7
+ export declare function FormResult({ id, text, tone, children, list }: {
8
+ id: string;
9
+ text: string;
10
+ tone?: 'success' | 'warning' | 'error' | undefined;
11
+ /** Shown under the text. */
12
+ children?: ReactNode;
13
+ /** A list under the text, such as the paths a call touched, indented and wrapping normally. */
14
+ list?: readonly ReactNode[] | undefined;
15
+ }): import("react").JSX.Element;
16
+ //# sourceMappingURL=FormResult.d.ts.map
@@ -0,0 +1,30 @@
1
+ import { Alert } from "./Alert.js";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ // src/feedback/FormResult.tsx
4
+ /**
5
+ * A form's result, such as a dialog's validation message or what its submit did. It stays mounted as a live region,
6
+ * so screen readers hear each new message; empty, it has no border, padding or icon. With no tone it is a warning, as
7
+ * a validation message is. Line breaks in `text` show.
8
+ */
9
+ function FormResult({ id, text, tone = "warning", children, list }) {
10
+ return /* @__PURE__ */ jsx(Alert, {
11
+ id,
12
+ tone: tone === "error" ? "danger" : tone,
13
+ "data-tone": tone,
14
+ role: "status",
15
+ "aria-atomic": "true",
16
+ showIcon: Boolean(text),
17
+ className: text ? "wrap-anywhere whitespace-pre-line" : "border-0 p-0",
18
+ children: text && /* @__PURE__ */ jsxs(Fragment, { children: [
19
+ text,
20
+ children,
21
+ list && list.length > 0 && /* @__PURE__ */ jsx("ul", {
22
+ className: "pl-4.5 whitespace-normal",
23
+ children: list.map((entry, index) => /* @__PURE__ */ jsx("li", { children: entry }, index))
24
+ })
25
+ ] })
26
+ });
27
+ }
28
+ export { FormResult };
29
+
30
+ //# sourceMappingURL=FormResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormResult.js","names":[],"sources":["../../src/feedback/FormResult.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { Alert } from './Alert';\n\n/**\n * A form's result, such as a dialog's validation message or what its submit did. It stays mounted as a live region,\n * so screen readers hear each new message; empty, it has no border, padding or icon. With no tone it is a warning, as\n * a validation message is. Line breaks in `text` show.\n */\nexport function FormResult({\n id,\n text,\n tone = 'warning',\n children,\n list,\n}: {\n id: string;\n text: string;\n tone?: 'success' | 'warning' | 'error' | undefined;\n /** Shown under the text. */\n children?: ReactNode;\n /** A list under the text, such as the paths a call touched, indented and wrapping normally. */\n list?: readonly ReactNode[] | undefined;\n}) {\n return (\n <Alert\n id={id}\n tone={tone === 'error' ? 'danger' : tone}\n data-tone={tone}\n role=\"status\"\n aria-atomic=\"true\"\n showIcon={Boolean(text)}\n className={text ? 'wrap-anywhere whitespace-pre-line' : 'border-0 p-0'}\n >\n {text && (\n <>\n {text}\n {children}\n {list && list.length > 0 && (\n <ul className=\"pl-4.5 whitespace-normal\">\n {list.map((entry, index) => (\n <li key={index}>{entry}</li>\n ))}\n </ul>\n )}\n </>\n )}\n </Alert>\n );\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,WAAW,EACvB,IACA,MACA,OAAO,WACP,UACA,QASD;CACC,OACI,oBAAC,OAAD;EACQ;EACJ,MAAM,SAAS,UAAU,WAAW;EACpC,aAAW;EACX,MAAK;EACL,eAAY;EACZ,UAAU,QAAQ,IAAI;EACtB,WAAW,OAAO,sCAAsC;EAEvD,UAAA,QACG,qBAAA,UAAA,EAAA,UAAA;GACK;GACA;GACA,QAAQ,KAAK,SAAS,KACnB,oBAAC,MAAD;IAAI,WAAU;IACT,UAAA,KAAK,KAAK,OAAO,UACd,oBAAC,MAAD,EAAA,UAAiB,MAAU,GAAlB,KAAkB,CAC9B;GACD,CAAA;EAEV,EAAA,CAAA;CAEH,CAAA;AAEf"}
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from "react";
2
+ /** An out-of-sight polite live region: screen readers read what it says each time that changes, such as "Copied". */
3
+ export declare function LiveRegion({ id, children }: {
4
+ id?: string;
5
+ children?: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ //# sourceMappingURL=LiveRegion.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ // src/feedback/LiveRegion.tsx
3
+ /** An out-of-sight polite live region: screen readers read what it says each time that changes, such as "Copied". */
4
+ function LiveRegion({ id, children }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ id,
7
+ className: "sr-only",
8
+ role: "status",
9
+ "aria-live": "polite",
10
+ children
11
+ });
12
+ }
13
+ export { LiveRegion };
14
+
15
+ //# sourceMappingURL=LiveRegion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiveRegion.js","names":[],"sources":["../../src/feedback/LiveRegion.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\n/** An out-of-sight polite live region: screen readers read what it says each time that changes, such as \"Copied\". */\nexport function LiveRegion({ id, children }: { id?: string; children?: ReactNode }) {\n return (\n <div id={id} className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {children}\n </div>\n );\n}\n"],"mappings":";;;AAGA,SAAgB,WAAW,EAAE,IAAI,YAAmD;CAChF,OACI,oBAAC,OAAD;EAAS;EAAI,WAAU;EAAU,MAAK;EAAS,aAAU;EACpD;CACA,CAAA;AAEb"}
@@ -0,0 +1,19 @@
1
+ import { LoadingProps } from "@ninna-ui/feedback";
2
+ import "lucide-react";
3
+ /** What shows in place of something still loading: ninna-ui's announced spinner, or with a `presentation`, a small
4
+ * spinner, still under reduced motion, and what loads. */
5
+ declare const Loading$1: import("react").ForwardRefExoticComponent<Omit<LoadingProps, "title"> & {
6
+ /** What loads. Without a `presentation` it names ninna-ui's spinner for screen readers only; with one it shows
7
+ * beside the spinner. */
8
+ label?: string;
9
+ /** With no label, names the spinner alone, as a cue beside values already shown. */
10
+ title?: string | undefined;
11
+ /** Stops it spinning. */
12
+ still?: boolean;
13
+ /** Without it, ninna-ui's announced spinner. `inline` is a small spinner and what loads in a line of 12px text;
14
+ * `line` stands on its own line of body text; `status` is a step's own loading line, announced, muted body text
15
+ * with room above and below that keeps turning as a pending action's spinner does. */
16
+ presentation?: 'inline' | 'line' | 'status';
17
+ } & import("react").RefAttributes<HTMLDivElement>>;
18
+ export { Loading$1 as Loading };
19
+ //# sourceMappingURL=Loading.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { ambientMotion } from "../foundations/AmbientMotion.js";
2
+ import { forwardRef } from "react";
3
+ import { Loading } from "@ninna-ui/feedback";
4
+ import { LoaderCircleIcon } from "lucide-react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ // src/feedback/Loading.tsx
7
+ const motions = {
8
+ spin: "motion-safe:animate-spin",
9
+ always: "animate-spin",
10
+ status: "status-spin",
11
+ still: ""
12
+ };
13
+ /**
14
+ * The loader icon, spinning on a box around it: above a device scale of 1 Chromium can't run a root svg's transform on
15
+ * the compositor, so the page would render every frame. It pauses while out of view or in a hidden window.
16
+ */
17
+ function SpinnerIcon({ motion = "spin", ...icon }) {
18
+ const spin = motions[motion];
19
+ return /* @__PURE__ */ jsx("span", {
20
+ ref: spin ? ambientMotion : void 0,
21
+ className: `flex w-fit shrink-0 ${spin}`,
22
+ children: /* @__PURE__ */ jsx(LoaderCircleIcon, { ...icon })
23
+ });
24
+ }
25
+ /** What shows in place of something still loading: ninna-ui's announced spinner, or with a `presentation`, a small
26
+ * spinner, still under reduced motion, and what loads. */
27
+ const Loading$1 = forwardRef(({ presentation, label, title, still = false, ...props }, ref) => {
28
+ if (!presentation) return /* @__PURE__ */ jsx(Loading, {
29
+ ref,
30
+ label,
31
+ title,
32
+ ...props
33
+ });
34
+ if (presentation === "status") return /* @__PURE__ */ jsxs("p", {
35
+ role: "status",
36
+ className: "text-base-700 m-0 flex items-center gap-2 py-4 text-sm",
37
+ children: [/* @__PURE__ */ jsx(SpinnerIcon, {
38
+ motion: still ? "still" : "always",
39
+ "aria-hidden": "true",
40
+ className: "size-4"
41
+ }), label]
42
+ });
43
+ return /* @__PURE__ */ jsxs("span", {
44
+ "data-loader": true,
45
+ className: "inline-flex min-w-0 items-center gap-1.5",
46
+ title,
47
+ children: [/* @__PURE__ */ jsx(SpinnerIcon, {
48
+ motion: still ? "still" : "spin",
49
+ "aria-hidden": "true",
50
+ className: presentation === "line" ? "size-4" : "size-3"
51
+ }), label ? /* @__PURE__ */ jsx("span", {
52
+ className: "truncate",
53
+ children: label
54
+ }) : title && /* @__PURE__ */ jsx("span", {
55
+ className: "sr-only",
56
+ children: title
57
+ })]
58
+ });
59
+ });
60
+ Loading$1.displayName = "Loading";
61
+ export { Loading$1 as Loading, SpinnerIcon };
62
+
63
+ //# sourceMappingURL=Loading.js.map