@lar-works/design-system 0.0.0-stage → 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 (555) hide show
  1. package/README.md +24 -2
  2. package/dist/actions/Button.d.ts +25 -0
  3. package/dist/actions/Button.js +55 -0
  4. package/dist/actions/Button.js.map +1 -0
  5. package/dist/actions/ButtonLink.d.ts +21 -0
  6. package/dist/actions/ButtonLink.js +40 -0
  7. package/dist/actions/ButtonLink.js.map +1 -0
  8. package/dist/actions/IconButton.d.ts +14 -0
  9. package/dist/actions/IconButton.js +29 -0
  10. package/dist/actions/IconButton.js.map +1 -0
  11. package/dist/actions/ThemeSwitch.d.ts +7 -0
  12. package/dist/actions/ThemeSwitch.js +42 -0
  13. package/dist/actions/ThemeSwitch.js.map +1 -0
  14. package/dist/actions/index.d.ts +5 -0
  15. package/dist/collections/CollectionSectionHeader.d.ts +5 -0
  16. package/dist/collections/CollectionSectionHeader.js +18 -0
  17. package/dist/collections/CollectionSectionHeader.js.map +1 -0
  18. package/dist/collections/CollectionState.d.ts +37 -0
  19. package/dist/collections/CollectionState.js +69 -0
  20. package/dist/collections/CollectionState.js.map +1 -0
  21. package/dist/collections/CollectionTokens.d.ts +16 -0
  22. package/dist/collections/CollectionTokens.js +19 -0
  23. package/dist/collections/CollectionTokens.js.map +1 -0
  24. package/dist/collections/CollectionViewport.js +36 -0
  25. package/dist/collections/CollectionViewport.js.map +1 -0
  26. package/dist/collections/DataRow.d.ts +23 -0
  27. package/dist/collections/DataRow.js +57 -0
  28. package/dist/collections/DataRow.js.map +1 -0
  29. package/dist/collections/ResultList.d.ts +29 -0
  30. package/dist/collections/ResultList.js +128 -0
  31. package/dist/collections/ResultList.js.map +1 -0
  32. package/dist/collections/ScrollRow.d.ts +23 -0
  33. package/dist/collections/ScrollRow.js +59 -0
  34. package/dist/collections/ScrollRow.js.map +1 -0
  35. package/dist/collections/VirtualGrid.d.ts +14 -0
  36. package/dist/collections/VirtualGrid.js +71 -0
  37. package/dist/collections/VirtualGrid.js.map +1 -0
  38. package/dist/collections/VirtualList.d.ts +34 -0
  39. package/dist/collections/VirtualList.js +128 -0
  40. package/dist/collections/VirtualList.js.map +1 -0
  41. package/dist/collections/index.d.ts +10 -0
  42. package/dist/collections/useCollectionMotion.d.ts +3 -0
  43. package/dist/collections/useCollectionMotion.js +34 -0
  44. package/dist/collections/useCollectionMotion.js.map +1 -0
  45. package/dist/collections/useScrollRow.d.ts +17 -0
  46. package/dist/collections/useScrollRow.js +63 -0
  47. package/dist/collections/useScrollRow.js.map +1 -0
  48. package/dist/display/ActivityCard.d.ts +17 -0
  49. package/dist/display/ActivityCard.js +58 -0
  50. package/dist/display/ActivityCard.js.map +1 -0
  51. package/dist/display/Artwork.d.ts +25 -0
  52. package/dist/display/Artwork.js +97 -0
  53. package/dist/display/Artwork.js.map +1 -0
  54. package/dist/display/Avatar.d.ts +5 -0
  55. package/dist/display/Avatar.js +13 -0
  56. package/dist/display/Avatar.js.map +1 -0
  57. package/dist/display/Badge.d.ts +10 -0
  58. package/dist/display/Badge.js +28 -0
  59. package/dist/display/Badge.js.map +1 -0
  60. package/dist/display/BadgeList.d.ts +11 -0
  61. package/dist/display/BadgeList.js +20 -0
  62. package/dist/display/BadgeList.js.map +1 -0
  63. package/dist/display/BrandMark.d.ts +21 -0
  64. package/dist/display/BrandMark.js +60 -0
  65. package/dist/display/BrandMark.js.map +1 -0
  66. package/dist/display/ChangeList.d.ts +16 -0
  67. package/dist/display/ChangeList.js +56 -0
  68. package/dist/display/ChangeList.js.map +1 -0
  69. package/dist/display/CheckList.d.ts +10 -0
  70. package/dist/display/CheckList.js +25 -0
  71. package/dist/display/CheckList.js.map +1 -0
  72. package/dist/display/CodeBlock.d.ts +6 -0
  73. package/dist/display/CodeBlock.js +12 -0
  74. package/dist/display/CodeBlock.js.map +1 -0
  75. package/dist/display/CopyButton.d.ts +9 -0
  76. package/dist/display/CopyButton.js +59 -0
  77. package/dist/display/CopyButton.js.map +1 -0
  78. package/dist/display/DataTable.d.ts +35 -0
  79. package/dist/display/DataTable.js +53 -0
  80. package/dist/display/DataTable.js.map +1 -0
  81. package/dist/display/DetailHero.d.ts +39 -0
  82. package/dist/display/DetailHero.js +146 -0
  83. package/dist/display/DetailHero.js.map +1 -0
  84. package/dist/display/DetailList.d.ts +15 -0
  85. package/dist/display/DetailList.js +53 -0
  86. package/dist/display/DetailList.js.map +1 -0
  87. package/dist/display/DeviceCard.d.ts +18 -0
  88. package/dist/display/DeviceCard.js +48 -0
  89. package/dist/display/DeviceCard.js.map +1 -0
  90. package/dist/display/Identity.d.ts +14 -0
  91. package/dist/display/Identity.js +54 -0
  92. package/dist/display/Identity.js.map +1 -0
  93. package/dist/display/ImageCard.d.ts +22 -0
  94. package/dist/display/ImageCard.js +63 -0
  95. package/dist/display/ImageCard.js.map +1 -0
  96. package/dist/display/ImagePicker.d.ts +30 -0
  97. package/dist/display/ImagePicker.js +108 -0
  98. package/dist/display/ImagePicker.js.map +1 -0
  99. package/dist/display/InfoBox.d.ts +15 -0
  100. package/dist/display/InfoBox.js +41 -0
  101. package/dist/display/InfoBox.js.map +1 -0
  102. package/dist/display/InsetPanel.d.ts +13 -0
  103. package/dist/display/InsetPanel.js +26 -0
  104. package/dist/display/InsetPanel.js.map +1 -0
  105. package/dist/display/ItemAction.d.ts +10 -0
  106. package/dist/display/ItemAction.js +35 -0
  107. package/dist/display/ItemAction.js.map +1 -0
  108. package/dist/display/Kbd.d.ts +6 -0
  109. package/dist/display/Kbd.js +12 -0
  110. package/dist/display/Kbd.js.map +1 -0
  111. package/dist/display/KindIcon.d.ts +8 -0
  112. package/dist/display/KindIcon.js +15 -0
  113. package/dist/display/KindIcon.js.map +1 -0
  114. package/dist/display/NoticeCard.d.ts +24 -0
  115. package/dist/display/NoticeCard.js +59 -0
  116. package/dist/display/NoticeCard.js.map +1 -0
  117. package/dist/display/PairingList.d.ts +19 -0
  118. package/dist/display/PairingList.js +53 -0
  119. package/dist/display/PairingList.js.map +1 -0
  120. package/dist/display/PathList.d.ts +9 -0
  121. package/dist/display/PathList.js +21 -0
  122. package/dist/display/PathList.js.map +1 -0
  123. package/dist/display/PeoplePreview.d.ts +16 -0
  124. package/dist/display/PeoplePreview.js +41 -0
  125. package/dist/display/PeoplePreview.js.map +1 -0
  126. package/dist/display/PropertySheet.d.ts +56 -0
  127. package/dist/display/PropertySheet.js +150 -0
  128. package/dist/display/PropertySheet.js.map +1 -0
  129. package/dist/display/QrCode.d.ts +6 -0
  130. package/dist/display/QrCode.js +47 -0
  131. package/dist/display/QrCode.js.map +1 -0
  132. package/dist/display/RadioChoice.d.ts +9 -0
  133. package/dist/display/RadioChoice.js +28 -0
  134. package/dist/display/RadioChoice.js.map +1 -0
  135. package/dist/display/RatingLink.d.ts +10 -0
  136. package/dist/display/RatingLink.js +80 -0
  137. package/dist/display/RatingLink.js.map +1 -0
  138. package/dist/display/ResourceCard.d.ts +20 -0
  139. package/dist/display/ResourceCard.js +200 -0
  140. package/dist/display/ResourceCard.js.map +1 -0
  141. package/dist/display/RowList.d.ts +28 -0
  142. package/dist/display/RowList.js +76 -0
  143. package/dist/display/RowList.js.map +1 -0
  144. package/dist/display/StackedMeter.d.ts +28 -0
  145. package/dist/display/StackedMeter.js +48 -0
  146. package/dist/display/StackedMeter.js.map +1 -0
  147. package/dist/display/StatTile.d.ts +13 -0
  148. package/dist/display/StatTile.js +35 -0
  149. package/dist/display/StatTile.js.map +1 -0
  150. package/dist/display/StepList.d.ts +5 -0
  151. package/dist/display/StepList.js +12 -0
  152. package/dist/display/StepList.js.map +1 -0
  153. package/dist/display/TextPreview.d.ts +14 -0
  154. package/dist/display/TextPreview.js +46 -0
  155. package/dist/display/TextPreview.js.map +1 -0
  156. package/dist/display/TimeSeriesChart.d.ts +19 -0
  157. package/dist/display/TimeSeriesChart.js +163 -0
  158. package/dist/display/TimeSeriesChart.js.map +1 -0
  159. package/dist/display/ToneTile.js +12 -0
  160. package/dist/display/ToneTile.js.map +1 -0
  161. package/dist/display/index.d.ts +38 -0
  162. package/dist/feedback/Alert.d.ts +15 -0
  163. package/dist/feedback/Alert.js +19 -0
  164. package/dist/feedback/Alert.js.map +1 -0
  165. package/dist/feedback/AsyncState.d.ts +16 -0
  166. package/dist/feedback/AsyncState.js +29 -0
  167. package/dist/feedback/AsyncState.js.map +1 -0
  168. package/dist/feedback/ErrorNotification.d.ts +8 -0
  169. package/dist/feedback/ErrorNotification.js +20 -0
  170. package/dist/feedback/ErrorNotification.js.map +1 -0
  171. package/dist/feedback/Notifications.d.ts +2 -0
  172. package/dist/feedback/Notifications.js +9 -0
  173. package/dist/feedback/Notifications.js.map +1 -0
  174. package/dist/feedback/ProgressStatusRow.d.ts +23 -0
  175. package/dist/feedback/ProgressStatusRow.js +74 -0
  176. package/dist/feedback/ProgressStatusRow.js.map +1 -0
  177. package/dist/feedback/SkeletonLoader.d.ts +19 -0
  178. package/dist/feedback/SkeletonLoader.js +59 -0
  179. package/dist/feedback/SkeletonLoader.js.map +1 -0
  180. package/dist/feedback/StatusIndicator.d.ts +9 -0
  181. package/dist/feedback/StatusIndicator.js +28 -0
  182. package/dist/feedback/StatusIndicator.js.map +1 -0
  183. package/dist/feedback/StatusPopoverContent.d.ts +13 -0
  184. package/dist/feedback/StatusPopoverContent.js +50 -0
  185. package/dist/feedback/StatusPopoverContent.js.map +1 -0
  186. package/dist/feedback/StatusRow.d.ts +16 -0
  187. package/dist/feedback/StatusRow.js +60 -0
  188. package/dist/feedback/StatusRow.js.map +1 -0
  189. package/dist/feedback/index.d.ts +11 -0
  190. package/dist/feedback/index.js +11 -0
  191. package/dist/forms/Checkbox.d.ts +10 -0
  192. package/dist/forms/Checkbox.js +48 -0
  193. package/dist/forms/Checkbox.js.map +1 -0
  194. package/dist/forms/Field.d.ts +5 -0
  195. package/dist/forms/Field.js +15 -0
  196. package/dist/forms/Field.js.map +1 -0
  197. package/dist/forms/FormControlStyles.js +14 -0
  198. package/dist/forms/FormControlStyles.js.map +1 -0
  199. package/dist/forms/FormSection.d.ts +48 -0
  200. package/dist/forms/FormSection.js +142 -0
  201. package/dist/forms/FormSection.js.map +1 -0
  202. package/dist/forms/InlineFields.d.ts +13 -0
  203. package/dist/forms/InlineFields.js +24 -0
  204. package/dist/forms/InlineFields.js.map +1 -0
  205. package/dist/forms/Input.d.ts +5 -0
  206. package/dist/forms/Input.js +18 -0
  207. package/dist/forms/Input.js.map +1 -0
  208. package/dist/forms/OptionSelect.d.ts +21 -0
  209. package/dist/forms/OptionSelect.js +28 -0
  210. package/dist/forms/OptionSelect.js.map +1 -0
  211. package/dist/forms/RadioGroup.d.ts +5 -0
  212. package/dist/forms/RadioGroup.js +35 -0
  213. package/dist/forms/RadioGroup.js.map +1 -0
  214. package/dist/forms/Select.d.ts +6 -0
  215. package/dist/forms/Select.js +36 -0
  216. package/dist/forms/Select.js.map +1 -0
  217. package/dist/forms/Switch.d.ts +4 -0
  218. package/dist/forms/Switch.js +16 -0
  219. package/dist/forms/Switch.js.map +1 -0
  220. package/dist/forms/TagInput.d.ts +19 -0
  221. package/dist/forms/TagInput.js +60 -0
  222. package/dist/forms/TagInput.js.map +1 -0
  223. package/dist/forms/Textarea.d.ts +4 -0
  224. package/dist/forms/Textarea.js +15 -0
  225. package/dist/forms/Textarea.js.map +1 -0
  226. package/dist/forms/index.d.ts +12 -0
  227. package/dist/foundations/DesignSystemProvider.d.ts +64 -0
  228. package/dist/foundations/DesignSystemProvider.js +66 -0
  229. package/dist/foundations/DesignSystemProvider.js.map +1 -0
  230. package/dist/foundations/KeyboardFocus.d.ts +9 -0
  231. package/dist/foundations/KeyboardFocus.js +10 -0
  232. package/dist/foundations/KeyboardFocus.js.map +1 -0
  233. package/dist/foundations/KeyboardShortcut.d.ts +5 -0
  234. package/dist/foundations/KeyboardShortcut.js +10 -0
  235. package/dist/foundations/KeyboardShortcut.js.map +1 -0
  236. package/dist/foundations/Theme.d.ts +14 -0
  237. package/dist/foundations/Theme.js +56 -0
  238. package/dist/foundations/Theme.js.map +1 -0
  239. package/dist/foundations/index.d.ts +5 -0
  240. package/dist/icons/BrandIcons.d.ts +3 -0
  241. package/dist/icons/BrandIcons.js +14 -0
  242. package/dist/icons/BrandIcons.js.map +1 -0
  243. package/dist/icons/index.d.ts +3 -0
  244. package/dist/icons/index.js +2 -0
  245. package/dist/icons.d.ts +4 -0
  246. package/dist/icons.js +2 -0
  247. package/dist/index.d.ts +133 -0
  248. package/dist/index.js +125 -0
  249. package/dist/layout/AppShell.d.ts +11 -0
  250. package/dist/layout/AppShell.js +46 -0
  251. package/dist/layout/AppShell.js.map +1 -0
  252. package/dist/layout/AuthLayout.d.ts +11 -0
  253. package/dist/layout/AuthLayout.js +48 -0
  254. package/dist/layout/AuthLayout.js.map +1 -0
  255. package/dist/layout/ContentContainer.d.ts +9 -0
  256. package/dist/layout/ContentContainer.js +15 -0
  257. package/dist/layout/ContentContainer.js.map +1 -0
  258. package/dist/layout/Flow.d.ts +26 -0
  259. package/dist/layout/Flow.js +65 -0
  260. package/dist/layout/Flow.js.map +1 -0
  261. package/dist/layout/PageLayout.d.ts +12 -0
  262. package/dist/layout/PageLayout.js +31 -0
  263. package/dist/layout/PageLayout.js.map +1 -0
  264. package/dist/layout/PageSection.d.ts +43 -0
  265. package/dist/layout/PageSection.js +63 -0
  266. package/dist/layout/PageSection.js.map +1 -0
  267. package/dist/layout/ScrollArea.d.ts +4 -0
  268. package/dist/layout/ScrollArea.js +11 -0
  269. package/dist/layout/ScrollArea.js.map +1 -0
  270. package/dist/layout/Section.d.ts +12 -0
  271. package/dist/layout/Section.js +36 -0
  272. package/dist/layout/Section.js.map +1 -0
  273. package/dist/layout/Site.d.ts +41 -0
  274. package/dist/layout/Site.js +157 -0
  275. package/dist/layout/Site.js.map +1 -0
  276. package/dist/layout/TitleBar.d.ts +28 -0
  277. package/dist/layout/TitleBar.js +83 -0
  278. package/dist/layout/TitleBar.js.map +1 -0
  279. package/dist/layout/WorkspaceActionsHeader.d.ts +8 -0
  280. package/dist/layout/WorkspaceActionsHeader.js +18 -0
  281. package/dist/layout/WorkspaceActionsHeader.js.map +1 -0
  282. package/dist/layout/index.d.ts +19 -0
  283. package/dist/layout/index.js +19 -0
  284. package/dist/layout/sidebar/SidebarNavigationItem.d.ts +10 -0
  285. package/dist/layout/sidebar/SidebarNavigationItem.js +36 -0
  286. package/dist/layout/sidebar/SidebarNavigationItem.js.map +1 -0
  287. package/dist/layout/sidebar/SidebarPane.d.ts +13 -0
  288. package/dist/layout/sidebar/SidebarPane.js +30 -0
  289. package/dist/layout/sidebar/SidebarPane.js.map +1 -0
  290. package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +11 -0
  291. package/dist/layout/toolbar/CommandPaletteTrigger.js +46 -0
  292. package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -0
  293. package/dist/layout/toolbar/ToolbarStatusGroup.d.ts +5 -0
  294. package/dist/layout/toolbar/ToolbarStatusGroup.js +14 -0
  295. package/dist/layout/toolbar/ToolbarStatusGroup.js.map +1 -0
  296. package/dist/layout/toolbar/ToolbarStatusItem.d.ts +9 -0
  297. package/dist/layout/toolbar/ToolbarStatusItem.js +18 -0
  298. package/dist/layout/toolbar/ToolbarStatusItem.js.map +1 -0
  299. package/dist/navigation/ArtworkTabs.d.ts +18 -0
  300. package/dist/navigation/ArtworkTabs.js +72 -0
  301. package/dist/navigation/ArtworkTabs.js.map +1 -0
  302. package/dist/navigation/Breadcrumbs.d.ts +13 -0
  303. package/dist/navigation/Breadcrumbs.js +32 -0
  304. package/dist/navigation/Breadcrumbs.js.map +1 -0
  305. package/dist/navigation/CollectionBrowseSelector.d.ts +22 -0
  306. package/dist/navigation/CollectionBrowseSelector.js +70 -0
  307. package/dist/navigation/CollectionBrowseSelector.js.map +1 -0
  308. package/dist/navigation/CollectionViewToggle.d.ts +12 -0
  309. package/dist/navigation/CollectionViewToggle.js +36 -0
  310. package/dist/navigation/CollectionViewToggle.js.map +1 -0
  311. package/dist/navigation/DrilldownBrowseSelector.d.ts +31 -0
  312. package/dist/navigation/DrilldownBrowseSelector.js +174 -0
  313. package/dist/navigation/DrilldownBrowseSelector.js.map +1 -0
  314. package/dist/navigation/FolderSelector.d.ts +24 -0
  315. package/dist/navigation/FolderSelector.js +142 -0
  316. package/dist/navigation/FolderSelector.js.map +1 -0
  317. package/dist/navigation/TabKeys.js +13 -0
  318. package/dist/navigation/TabKeys.js.map +1 -0
  319. package/dist/navigation/ViewTabs.d.ts +19 -0
  320. package/dist/navigation/ViewTabs.js +48 -0
  321. package/dist/navigation/ViewTabs.js.map +1 -0
  322. package/dist/navigation/index.d.ts +8 -0
  323. package/dist/overlays/ActionModal.d.ts +21 -0
  324. package/dist/overlays/ActionModal.js +48 -0
  325. package/dist/overlays/ActionModal.js.map +1 -0
  326. package/dist/overlays/CommandPalette.d.ts +43 -0
  327. package/dist/overlays/CommandPalette.js +163 -0
  328. package/dist/overlays/CommandPalette.js.map +1 -0
  329. package/dist/overlays/Drawer.d.ts +19 -0
  330. package/dist/overlays/Drawer.js +83 -0
  331. package/dist/overlays/Drawer.js.map +1 -0
  332. package/dist/overlays/DropdownMenu.d.ts +47 -0
  333. package/dist/overlays/DropdownMenu.js +58 -0
  334. package/dist/overlays/DropdownMenu.js.map +1 -0
  335. package/dist/overlays/ImageViewer.d.ts +21 -0
  336. package/dist/overlays/ImageViewer.js +82 -0
  337. package/dist/overlays/ImageViewer.js.map +1 -0
  338. package/dist/overlays/Modal.d.ts +36 -0
  339. package/dist/overlays/Modal.js +149 -0
  340. package/dist/overlays/Modal.js.map +1 -0
  341. package/dist/overlays/Popover.d.ts +19 -0
  342. package/dist/overlays/Popover.js +26 -0
  343. package/dist/overlays/Popover.js.map +1 -0
  344. package/dist/overlays/Tooltip.d.ts +12 -0
  345. package/dist/overlays/Tooltip.js +54 -0
  346. package/dist/overlays/Tooltip.js.map +1 -0
  347. package/dist/overlays/index.d.ts +9 -0
  348. package/dist/overlays/useModalAutoFocus.js +84 -0
  349. package/dist/overlays/useModalAutoFocus.js.map +1 -0
  350. package/dist/overlays/useScrollFade.js +43 -0
  351. package/dist/overlays/useScrollFade.js.map +1 -0
  352. package/dist/showcase/CallToAction.d.ts +11 -0
  353. package/dist/showcase/CallToAction.js +54 -0
  354. package/dist/showcase/CallToAction.js.map +1 -0
  355. package/dist/showcase/Cards.d.ts +34 -0
  356. package/dist/showcase/Cards.js +122 -0
  357. package/dist/showcase/Cards.js.map +1 -0
  358. package/dist/showcase/Devices.d.ts +72 -0
  359. package/dist/showcase/Devices.js +249 -0
  360. package/dist/showcase/Devices.js.map +1 -0
  361. package/dist/showcase/FeatureRow.d.ts +30 -0
  362. package/dist/showcase/FeatureRow.js +91 -0
  363. package/dist/showcase/FeatureRow.js.map +1 -0
  364. package/dist/showcase/Hero.d.ts +15 -0
  365. package/dist/showcase/Hero.js +73 -0
  366. package/dist/showcase/Hero.js.map +1 -0
  367. package/dist/showcase/PhotoSearchConcept.d.ts +14 -0
  368. package/dist/showcase/PhotoSearchConcept.js +43 -0
  369. package/dist/showcase/PhotoSearchConcept.js.map +1 -0
  370. package/dist/showcase/Platforms.d.ts +15 -0
  371. package/dist/showcase/Platforms.js +48 -0
  372. package/dist/showcase/Platforms.js.map +1 -0
  373. package/dist/showcase/ProductBand.d.ts +38 -0
  374. package/dist/showcase/ProductBand.js +120 -0
  375. package/dist/showcase/ProductBand.js.map +1 -0
  376. package/dist/showcase/Roadmap.d.ts +21 -0
  377. package/dist/showcase/Roadmap.js +111 -0
  378. package/dist/showcase/Roadmap.js.map +1 -0
  379. package/dist/showcase/RouteDiagram.d.ts +14 -0
  380. package/dist/showcase/RouteDiagram.js +57 -0
  381. package/dist/showcase/RouteDiagram.js.map +1 -0
  382. package/dist/showcase/ServerUnit.d.ts +50 -0
  383. package/dist/showcase/ServerUnit.js +175 -0
  384. package/dist/showcase/ServerUnit.js.map +1 -0
  385. package/dist/showcase/Stage.d.ts +46 -0
  386. package/dist/showcase/Stage.js +106 -0
  387. package/dist/showcase/Stage.js.map +1 -0
  388. package/dist/showcase/Status.d.ts +30 -0
  389. package/dist/showcase/Status.js +84 -0
  390. package/dist/showcase/Status.js.map +1 -0
  391. package/dist/showcase/StepFlow.d.ts +13 -0
  392. package/dist/showcase/StepFlow.js +47 -0
  393. package/dist/showcase/StepFlow.js.map +1 -0
  394. package/dist/showcase/index.d.ts +15 -0
  395. package/dist/testing.d.ts +5 -0
  396. package/dist/testing.js +43 -0
  397. package/dist/testing.js.map +1 -0
  398. package/dist/typography/Link.d.ts +21 -0
  399. package/dist/typography/Link.js +60 -0
  400. package/dist/typography/Link.js.map +1 -0
  401. package/dist/typography/Typography.d.ts +53 -0
  402. package/dist/typography/Typography.js +67 -0
  403. package/dist/typography/Typography.js.map +1 -0
  404. package/dist/typography/index.d.ts +4 -0
  405. package/dist/typography/index.js +4 -0
  406. package/package.json +80 -3
  407. package/src/actions/Button.tsx +68 -0
  408. package/src/actions/ButtonLink.tsx +75 -0
  409. package/src/actions/IconButton.tsx +55 -0
  410. package/src/actions/ThemeSwitch.tsx +46 -0
  411. package/src/actions/index.ts +4 -0
  412. package/src/collections/CollectionSectionHeader.tsx +13 -0
  413. package/src/collections/CollectionState.tsx +76 -0
  414. package/src/collections/CollectionTokens.ts +12 -0
  415. package/src/collections/CollectionViewport.ts +40 -0
  416. package/src/collections/DataRow.tsx +79 -0
  417. package/src/collections/ResultList.tsx +164 -0
  418. package/src/collections/ScrollRow.tsx +90 -0
  419. package/src/collections/VirtualGrid.tsx +92 -0
  420. package/src/collections/VirtualList.tsx +224 -0
  421. package/src/collections/index.ts +10 -0
  422. package/src/collections/useCollectionMotion.ts +42 -0
  423. package/src/collections/useScrollRow.ts +64 -0
  424. package/src/display/ActivityCard.tsx +76 -0
  425. package/src/display/Artwork.tsx +140 -0
  426. package/src/display/Avatar.tsx +7 -0
  427. package/src/display/Badge.tsx +33 -0
  428. package/src/display/BadgeList.tsx +25 -0
  429. package/src/display/BrandMark.tsx +72 -0
  430. package/src/display/ChangeList.tsx +41 -0
  431. package/src/display/CheckList.tsx +27 -0
  432. package/src/display/CodeBlock.tsx +12 -0
  433. package/src/display/CopyButton.tsx +77 -0
  434. package/src/display/DataTable.tsx +80 -0
  435. package/src/display/DetailHero.tsx +191 -0
  436. package/src/display/DetailList.tsx +74 -0
  437. package/src/display/DeviceCard.tsx +49 -0
  438. package/src/display/Identity.tsx +56 -0
  439. package/src/display/ImageCard.tsx +102 -0
  440. package/src/display/ImagePicker.tsx +149 -0
  441. package/src/display/InfoBox.tsx +48 -0
  442. package/src/display/InsetPanel.tsx +37 -0
  443. package/src/display/ItemAction.tsx +53 -0
  444. package/src/display/Kbd.tsx +6 -0
  445. package/src/display/KindIcon.tsx +15 -0
  446. package/src/display/NoticeCard.tsx +77 -0
  447. package/src/display/PairingList.tsx +55 -0
  448. package/src/display/PathList.tsx +16 -0
  449. package/src/display/PeoplePreview.tsx +66 -0
  450. package/src/display/PropertySheet.tsx +180 -0
  451. package/src/display/QrCode.tsx +47 -0
  452. package/src/display/RadioChoice.tsx +34 -0
  453. package/src/display/RatingLink.tsx +76 -0
  454. package/src/display/ResourceCard.tsx +201 -0
  455. package/src/display/RowList.tsx +110 -0
  456. package/src/display/StackedMeter.tsx +72 -0
  457. package/src/display/StatTile.tsx +39 -0
  458. package/src/display/StepList.tsx +10 -0
  459. package/src/display/TextPreview.tsx +66 -0
  460. package/src/display/TimeSeriesChart.tsx +191 -0
  461. package/src/display/ToneTile.ts +10 -0
  462. package/src/display/index.ts +37 -0
  463. package/src/feedback/Alert.tsx +35 -0
  464. package/src/feedback/AsyncState.tsx +56 -0
  465. package/src/feedback/ErrorNotification.ts +24 -0
  466. package/src/feedback/Notifications.tsx +5 -0
  467. package/src/feedback/ProgressStatusRow.tsx +104 -0
  468. package/src/feedback/SkeletonLoader.tsx +88 -0
  469. package/src/feedback/StatusIndicator.tsx +28 -0
  470. package/src/feedback/StatusPopoverContent.tsx +54 -0
  471. package/src/feedback/StatusRow.tsx +70 -0
  472. package/src/feedback/index.ts +15 -0
  473. package/src/forms/Checkbox.tsx +61 -0
  474. package/src/forms/Field.tsx +17 -0
  475. package/src/forms/FormControlStyles.ts +9 -0
  476. package/src/forms/FormSection.tsx +175 -0
  477. package/src/forms/InlineFields.tsx +22 -0
  478. package/src/forms/Input.tsx +22 -0
  479. package/src/forms/OptionSelect.tsx +49 -0
  480. package/src/forms/RadioGroup.tsx +48 -0
  481. package/src/forms/Select.tsx +46 -0
  482. package/src/forms/Switch.tsx +10 -0
  483. package/src/forms/TagInput.tsx +76 -0
  484. package/src/forms/Textarea.tsx +14 -0
  485. package/src/forms/index.ts +11 -0
  486. package/src/foundations/DesignSystemProvider.tsx +79 -0
  487. package/src/foundations/KeyboardFocus.ts +6 -0
  488. package/src/foundations/KeyboardShortcut.ts +12 -0
  489. package/src/foundations/Theme.ts +75 -0
  490. package/src/foundations/index.ts +10 -0
  491. package/src/foundations/theme.css +425 -0
  492. package/src/icons/BrandIcons.tsx +8 -0
  493. package/src/icons/index.ts +4 -0
  494. package/src/icons.ts +1 -0
  495. package/src/index.ts +13 -0
  496. package/src/layout/AppShell.tsx +63 -0
  497. package/src/layout/AuthLayout.tsx +40 -0
  498. package/src/layout/ContentContainer.tsx +16 -0
  499. package/src/layout/Flow.tsx +56 -0
  500. package/src/layout/PageLayout.tsx +35 -0
  501. package/src/layout/PageSection.tsx +103 -0
  502. package/src/layout/ScrollArea.tsx +7 -0
  503. package/src/layout/Section.tsx +36 -0
  504. package/src/layout/Site.tsx +205 -0
  505. package/src/layout/TitleBar.tsx +97 -0
  506. package/src/layout/WorkspaceActionsHeader.tsx +17 -0
  507. package/src/layout/index.ts +18 -0
  508. package/src/layout/sidebar/SidebarNavigationItem.tsx +45 -0
  509. package/src/layout/sidebar/SidebarPane.tsx +37 -0
  510. package/src/layout/toolbar/CommandPaletteTrigger.tsx +53 -0
  511. package/src/layout/toolbar/ToolbarStatusGroup.tsx +9 -0
  512. package/src/layout/toolbar/ToolbarStatusItem.tsx +18 -0
  513. package/src/navigation/ArtworkTabs.tsx +107 -0
  514. package/src/navigation/Breadcrumbs.tsx +31 -0
  515. package/src/navigation/CollectionBrowseSelector.tsx +90 -0
  516. package/src/navigation/CollectionViewToggle.tsx +52 -0
  517. package/src/navigation/DrilldownBrowseSelector.tsx +229 -0
  518. package/src/navigation/FolderSelector.tsx +172 -0
  519. package/src/navigation/TabKeys.ts +21 -0
  520. package/src/navigation/ViewTabs.tsx +85 -0
  521. package/src/navigation/index.ts +15 -0
  522. package/src/overlays/ActionModal.tsx +81 -0
  523. package/src/overlays/CommandPalette.tsx +199 -0
  524. package/src/overlays/Drawer.tsx +107 -0
  525. package/src/overlays/DropdownMenu.tsx +122 -0
  526. package/src/overlays/ImageViewer.tsx +96 -0
  527. package/src/overlays/Modal.tsx +234 -0
  528. package/src/overlays/Popover.tsx +40 -0
  529. package/src/overlays/Tooltip.tsx +56 -0
  530. package/src/overlays/index.ts +8 -0
  531. package/src/overlays/useModalAutoFocus.ts +119 -0
  532. package/src/overlays/useScrollFade.ts +49 -0
  533. package/src/showcase/CallToAction.tsx +46 -0
  534. package/src/showcase/Cards.tsx +133 -0
  535. package/src/showcase/Devices.tsx +259 -0
  536. package/src/showcase/FeatureRow.tsx +107 -0
  537. package/src/showcase/Hero.tsx +70 -0
  538. package/src/showcase/PhotoSearchConcept.tsx +50 -0
  539. package/src/showcase/Platforms.tsx +49 -0
  540. package/src/showcase/ProductBand.tsx +148 -0
  541. package/src/showcase/Roadmap.tsx +115 -0
  542. package/src/showcase/RouteDiagram.tsx +56 -0
  543. package/src/showcase/ServerUnit.tsx +191 -0
  544. package/src/showcase/Stage.tsx +160 -0
  545. package/src/showcase/Status.tsx +107 -0
  546. package/src/showcase/StepFlow.tsx +48 -0
  547. package/src/showcase/devices.css +441 -0
  548. package/src/showcase/index.ts +34 -0
  549. package/src/showcase/server-unit.css +258 -0
  550. package/src/showcase/stage.css +175 -0
  551. package/src/styles.css +5 -0
  552. package/src/testing.ts +34 -0
  553. package/src/typography/Link.tsx +105 -0
  554. package/src/typography/Typography.tsx +113 -0
  555. package/src/typography/index.ts +3 -0
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import { tabbable } from '../foundations/KeyboardFocus';
4
+ import { Stack } from '../layout/Flow';
5
+
6
+ interface InsetPanelProps {
7
+ children: ReactNode;
8
+ onClick?: () => void;
9
+ presentation?: 'default' | 'settings';
10
+ }
11
+
12
+ /**
13
+ * A neutral surface that groups related content without adding message or status meaning.
14
+ * Use Alert for current status, InfoBox for optional guidance, and NoticeCard for a decision item.
15
+ */
16
+ export function InsetPanel({ children, onClick, presentation = 'default' }: InsetPanelProps) {
17
+ if (presentation === 'settings') {
18
+ return (
19
+ <div className="divide-base-300 border-base-300 bg-base-100 divide-y overflow-hidden rounded-lg border shadow-xs/5">
20
+ {children}
21
+ </div>
22
+ );
23
+ }
24
+
25
+ return (
26
+ <Stack
27
+ as={onClick ? 'button' : 'div'}
28
+ type={onClick ? 'button' : undefined}
29
+ tabIndex={onClick ? tabbable.tabIndex : undefined}
30
+ onClick={onClick}
31
+ space="related"
32
+ className={`border-base-300 bg-base-100 rounded-lg border p-5 ${onClick ? 'focus-visible:outline-primary w-full cursor-pointer text-left focus-visible:outline-2 focus-visible:outline-offset-2' : ''}`}
33
+ >
34
+ {children}
35
+ </Stack>
36
+ );
37
+ }
@@ -0,0 +1,53 @@
1
+ import { Loading } from '@ninna-ui/feedback';
2
+ import { PencilIcon } from 'lucide-react';
3
+
4
+ export interface ItemActionProps {
5
+ label: string;
6
+ onClick?: () => void;
7
+ }
8
+
9
+ export function ItemAction({
10
+ action,
11
+ loading = false,
12
+ loadingLabel,
13
+ }: {
14
+ action?: ItemActionProps;
15
+ loading?: boolean;
16
+ loadingLabel?: string;
17
+ }) {
18
+ const disabled = loading || !action?.onClick;
19
+
20
+ if (!loading && !action) return null;
21
+
22
+ return (
23
+ <button
24
+ type="button"
25
+ aria-label={loading ? loadingLabel : action?.label}
26
+ aria-hidden={loading && !loadingLabel ? true : undefined}
27
+ aria-disabled={disabled}
28
+ tabIndex={disabled ? -1 : 0}
29
+ title={loading ? loadingLabel : action?.label}
30
+ className={`bg-base-50/90 text-base-content focus-visible:outline-primary pointer-events-auto flex size-6 items-center justify-center rounded-full shadow-sm backdrop-blur-sm transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 motion-reduce:transition-none ${loading ? '' : 'opacity-0 group-hover/media-item:opacity-100 group-has-focus-visible/media-item:opacity-100 [@media(hover:none)]:opacity-100'} ${disabled ? 'cursor-default' : 'hover:bg-base-50 hover:text-primary cursor-pointer'}`}
31
+ onClick={(event) => {
32
+ event.stopPropagation();
33
+
34
+ if (!disabled) action?.onClick?.();
35
+ }}
36
+ >
37
+ {loading ? (
38
+ <Loading
39
+ aria-hidden={!loadingLabel}
40
+ className="motion-reduce:animate-none"
41
+ color="primary"
42
+ label={loadingLabel ?? ''}
43
+ size="sm"
44
+ variant="spin"
45
+ />
46
+ ) : (
47
+ <span className={`size-3.5 [&>svg]:size-full ${disabled ? 'opacity-40' : ''}`}>
48
+ <PencilIcon />
49
+ </span>
50
+ )}
51
+ </button>
52
+ );
53
+ }
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ /** A keyboard key or shortcut, as quiet small text, such as ⌘K beside the search field. */
4
+ export function Kbd({ children }: { children?: ReactNode }) {
5
+ return <kbd className="text-base-500 font-sans text-[11px] font-medium">{children}</kbd>;
6
+ }
@@ -0,0 +1,15 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+
3
+ /** Colours the icon inside it in a muted version of a lar-brand app hue, such as a catalog's kind; neutral without one. Its
4
+ * container sizes the icon. */
5
+ export function KindIcon({ hue, children }: { hue?: number; children: ReactNode }) {
6
+ return (
7
+ <span
8
+ aria-hidden="true"
9
+ className={`contents ${hue === undefined ? 'text-base-500 dark:text-base-600' : 'kind-icon'}`}
10
+ style={hue === undefined ? undefined : ({ '--lar-kind-hue': hue } as CSSProperties)}
11
+ >
12
+ {children}
13
+ </span>
14
+ );
15
+ }
@@ -0,0 +1,77 @@
1
+ import { type ReactNode, useId } from 'react';
2
+
3
+ import type { StatusTone } from '../feedback/StatusIndicator';
4
+ import { Heading, Text } from '../typography/Typography';
5
+ import { toneTileClasses } from './ToneTile';
6
+
7
+ const accentClasses: Record<StatusTone, string> = {
8
+ neutral: 'border-l-base-300',
9
+ success: 'border-l-success',
10
+ warning: 'border-l-warning',
11
+ danger: 'border-l-danger',
12
+ info: 'border-l-info',
13
+ };
14
+
15
+ interface NoticeCardProps {
16
+ /** Buttons for what can be done, primary first. */
17
+ actions?: ReactNode;
18
+ /** A short status such as a severity, beside the title. */
19
+ badge?: ReactNode;
20
+ children?: ReactNode;
21
+ description: ReactNode;
22
+ /** Quiet content under the actions, such as a disclosure of technical details. */
23
+ footer?: ReactNode;
24
+ icon: ReactNode;
25
+ /** The title's heading level; one below the section the card sits in. */
26
+ level?: 'h2' | 'h3' | 'h4';
27
+ title: string;
28
+ tone: StatusTone;
29
+ }
30
+
31
+ /**
32
+ * A persistent, substantial item that needs examination or a decision, with optional details and
33
+ * actions. Use Alert for current status, InfoBox for optional guidance, and InsetPanel for grouping.
34
+ */
35
+ export function NoticeCard({
36
+ actions,
37
+ badge,
38
+ children,
39
+ description,
40
+ footer,
41
+ icon,
42
+ level = 'h2',
43
+ title,
44
+ tone,
45
+ }: NoticeCardProps) {
46
+ const id = useId();
47
+
48
+ return (
49
+ <article
50
+ aria-labelledby={id}
51
+ className={`border-base-300 bg-base-100 rounded-lg border border-l-4 p-4 sm:p-5 ${accentClasses[tone]}`}
52
+ >
53
+ <div className="flex min-w-0 gap-3 sm:gap-4">
54
+ <span
55
+ aria-hidden="true"
56
+ className={`flex size-9 shrink-0 items-center justify-center rounded-lg [&>svg]:size-5 ${toneTileClasses[tone]}`}
57
+ >
58
+ {icon}
59
+ </span>
60
+ <div className="flex min-w-0 flex-1 flex-col gap-3">
61
+ <div className="flex min-w-0 flex-col gap-1">
62
+ <div className="flex min-w-0 flex-wrap items-center justify-between gap-2">
63
+ <Heading id={id} as={level} variant="title">
64
+ {title}
65
+ </Heading>
66
+ {badge}
67
+ </div>
68
+ <Text tone="muted">{description}</Text>
69
+ </div>
70
+ {children}
71
+ {actions ? <div className="flex flex-wrap items-center gap-2">{actions}</div> : null}
72
+ {footer}
73
+ </div>
74
+ </div>
75
+ </article>
76
+ );
77
+ }
@@ -0,0 +1,55 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import { Text } from '../typography/Typography';
4
+
5
+ export interface PairingListItem {
6
+ key: string;
7
+ /** Short ordinal such as `1` or `2-05`. */
8
+ position: string;
9
+ title: string;
10
+ /** A secondary fact aligned in its own column, such as a duration. */
11
+ detail?: string;
12
+ /** One line under the title; `warning` draws attention to a doubt. */
13
+ note?: string;
14
+ noteTone?: 'muted' | 'warning';
15
+ control: ReactNode;
16
+ }
17
+
18
+ /** Rows that pair a numbered item with a chosen counterpart, such as release tracks and files. */
19
+ export function PairingList({ items, label }: { items: readonly PairingListItem[]; label: string }) {
20
+ return (
21
+ <ul aria-label={label} className="divide-base-300 border-base-300 bg-base-100 divide-y rounded-lg border">
22
+ {items.map((item) => (
23
+ <li
24
+ key={item.key}
25
+ className="grid min-w-0 grid-cols-[2.5rem_minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2 px-3 py-2.5 sm:grid-cols-[2.5rem_minmax(0,1fr)_3.5rem_minmax(0,20rem)] sm:px-4"
26
+ >
27
+ <Text as="span" tone="muted" className="tabular-nums">
28
+ {item.position}
29
+ </Text>
30
+ <span className="min-w-0">
31
+ <Text as="span" className="block" truncate title={item.title} variant="label">
32
+ {item.title}
33
+ </Text>
34
+ {item.note ? (
35
+ <Text
36
+ as="span"
37
+ className="block"
38
+ truncate
39
+ title={item.note}
40
+ variant="caption"
41
+ tone={item.noteTone === 'warning' ? 'warning' : 'muted'}
42
+ >
43
+ {item.note}
44
+ </Text>
45
+ ) : null}
46
+ </span>
47
+ <Text as="span" tone="muted" className="text-right tabular-nums">
48
+ {item.detail ?? ''}
49
+ </Text>
50
+ <span className="col-span-3 min-w-0 sm:col-span-1">{item.control}</span>
51
+ </li>
52
+ ))}
53
+ </ul>
54
+ );
55
+ }
@@ -0,0 +1,16 @@
1
+ import { Code } from '@ninna-ui/primitives';
2
+
3
+ /** File paths as truncated code, one per line. */
4
+ export function PathList({ label, paths }: { label: string; paths: readonly { key: string; path: string }[] }) {
5
+ return (
6
+ <ul aria-label={label} className="space-y-1">
7
+ {paths.map(({ key, path }) => (
8
+ <li key={key} className="min-w-0">
9
+ <Code title={path} className="block max-w-full truncate text-xs">
10
+ {path}
11
+ </Code>
12
+ </li>
13
+ ))}
14
+ </ul>
15
+ );
16
+ }
@@ -0,0 +1,66 @@
1
+ import { type ReactNode, useLayoutEffect, useRef, useState } from 'react';
2
+
3
+ import { ImageCard } from './ImageCard';
4
+
5
+ interface PeoplePreviewItem {
6
+ id: string;
7
+ name: string;
8
+ role: string;
9
+ artwork: ReactNode;
10
+ href?: string;
11
+ }
12
+
13
+ /** Render only the cards that fit in one row, including keyboard navigation. */
14
+ export function PeoplePreview({
15
+ label,
16
+ items,
17
+ onNavigate,
18
+ }: {
19
+ label: string;
20
+ items: readonly PeoplePreviewItem[];
21
+ onNavigate?: (href: string) => void;
22
+ }) {
23
+ const rowRef = useRef<HTMLUListElement>(null);
24
+ const [visibleCount, setVisibleCount] = useState<number>();
25
+
26
+ useLayoutEffect(() => {
27
+ const row = rowRef.current;
28
+
29
+ if (!row) return;
30
+
31
+ const measure = () => {
32
+ const columns = getComputedStyle(row).gridTemplateColumns;
33
+
34
+ if (columns && !columns.includes('repeat(') && columns !== 'none')
35
+ setVisibleCount(columns.trim().split(/\s+/).length);
36
+ };
37
+ const observer = new ResizeObserver(measure);
38
+
39
+ measure();
40
+ observer.observe(row);
41
+
42
+ return () => observer.disconnect();
43
+ }, []);
44
+
45
+ return (
46
+ <ul
47
+ ref={rowRef}
48
+ aria-label={label}
49
+ className="grid min-w-0 grid-cols-[repeat(auto-fill,minmax(min(5.5rem,100%),1fr))] gap-x-3 gap-y-5"
50
+ >
51
+ {items.slice(0, visibleCount).map((person) => (
52
+ <li key={person.id} className="min-w-0">
53
+ <ImageCard
54
+ presentation="person"
55
+ title={person.name}
56
+ label={person.name}
57
+ subtitle={person.role}
58
+ artwork={person.artwork}
59
+ href={person.href}
60
+ onNavigate={onNavigate}
61
+ />
62
+ </li>
63
+ ))}
64
+ </ul>
65
+ );
66
+ }
@@ -0,0 +1,180 @@
1
+ import { ChevronDownIcon } from 'lucide-react';
2
+ /* oxlint-disable react/only-export-components -- Compound members are exported through PropertySheet. */
3
+ import { type ReactNode, useId } from 'react';
4
+
5
+ import { SkeletonLoader } from '../feedback/SkeletonLoader';
6
+ import { Heading, Text } from '../typography/Typography';
7
+ import { BadgeList, type BadgeListItem } from './BadgeList';
8
+ import { InsetPanel } from './InsetPanel';
9
+
10
+ type PropertySheetProps = { title: string } & (
11
+ | { children: ReactNode; loading?: false; loadingLabel?: never }
12
+ | { children?: never; loading: true; loadingLabel?: string }
13
+ );
14
+
15
+ /** A titled sheet of facts about one thing; the body is label/value rows, a row of tags, or a short note. */
16
+ function PropertySheetRoot({ children, loading = false, loadingLabel, title }: PropertySheetProps) {
17
+ const id = useId();
18
+ const content = (
19
+ <section
20
+ aria-labelledby={loading ? undefined : id}
21
+ aria-hidden={(loading && !loadingLabel) || undefined}
22
+ className="min-w-0"
23
+ >
24
+ <Heading
25
+ id={id}
26
+ as="h3"
27
+ variant="label"
28
+ tone="muted"
29
+ className="px-1"
30
+ loading={loading}
31
+ aria-hidden={loading || undefined}
32
+ >
33
+ {title}
34
+ </Heading>
35
+ <div className="mt-3">
36
+ <InsetPanel presentation="settings">{loading ? <PropertySheetRows loading /> : children}</InsetPanel>
37
+ </div>
38
+ </section>
39
+ );
40
+
41
+ return loading && loadingLabel ? <SkeletonLoader label={loadingLabel}>{content}</SkeletonLoader> : content;
42
+ }
43
+
44
+ interface PropertySheetRow {
45
+ label: string;
46
+ value: ReactNode;
47
+ }
48
+
49
+ type RowsProps = { loading: true; items?: never } | { loading?: false; items: readonly PropertySheetRow[] };
50
+
51
+ function PropertySheetRows({ items, loading = false }: RowsProps) {
52
+ const rows = items ?? Array.from({ length: 3 }, () => ({ label: '', value: '' }));
53
+
54
+ return (
55
+ <dl className="divide-base-300 divide-y">
56
+ {rows.map(({ label, value }, index) => (
57
+ <div
58
+ key={loading ? index : label}
59
+ className="grid grid-cols-[minmax(0,1fr)_minmax(0,1.5fr)] items-baseline gap-x-6 px-4 py-2.5 sm:px-5"
60
+ >
61
+ <dt>
62
+ <Text as="span" tone="muted" loading={loading}>
63
+ {label}
64
+ </Text>
65
+ </dt>
66
+ <dd className="min-w-0 text-right">
67
+ <Text as="span" className="wrap-break-word tabular-nums" variant="label" loading={loading}>
68
+ {value}
69
+ </Text>
70
+ </dd>
71
+ </div>
72
+ ))}
73
+ </dl>
74
+ );
75
+ }
76
+
77
+ type PropertySheetTag = Omit<BadgeListItem, 'struck'>;
78
+
79
+ function PropertySheetTags({ items }: { items: readonly PropertySheetTag[] }) {
80
+ return (
81
+ <div className="px-4 py-3 sm:px-5">
82
+ <BadgeList items={items} />
83
+ </div>
84
+ );
85
+ }
86
+
87
+ function PropertySheetNote({ children }: { children: ReactNode }) {
88
+ return (
89
+ <Text className="px-4 py-3 sm:px-5" tone="muted">
90
+ {children}
91
+ </Text>
92
+ );
93
+ }
94
+
95
+ function PropertySheetCollapsible({
96
+ children,
97
+ title,
98
+ summary,
99
+ }: {
100
+ children: ReactNode;
101
+ title: string;
102
+ summary?: string;
103
+ }) {
104
+ const id = useId();
105
+
106
+ return (
107
+ <section aria-labelledby={id} className="min-w-0">
108
+ <InsetPanel presentation="settings">
109
+ <details className="group/sheet">
110
+ <summary className="hover:bg-base-100 focus-visible:outline-primary flex cursor-pointer list-none items-center gap-4 px-4 py-4 focus-visible:outline-2 focus-visible:-outline-offset-2 sm:px-5 [&::-webkit-details-marker]:hidden">
111
+ <span className="min-w-0 flex-1 wrap-anywhere">
112
+ <Text as="span" id={id} variant="label" className="block">
113
+ {title}
114
+ </Text>
115
+ {summary ? (
116
+ <Text as="span" tone="muted" variant="caption" className="mt-1 block">
117
+ {summary}
118
+ </Text>
119
+ ) : null}
120
+ </span>
121
+ <span
122
+ aria-hidden="true"
123
+ className="shrink-0 transition-transform group-open/sheet:rotate-180 [&>svg]:size-4"
124
+ >
125
+ <ChevronDownIcon />
126
+ </span>
127
+ </summary>
128
+ <div className="border-base-300 border-t p-4 sm:p-5">{children}</div>
129
+ </details>
130
+ </InsetPanel>
131
+ </section>
132
+ );
133
+ }
134
+
135
+ function PropertySheetTable({
136
+ label,
137
+ columns,
138
+ rows,
139
+ }: {
140
+ label: string;
141
+ columns: readonly string[];
142
+ rows: readonly { key: string; cells: readonly ReactNode[] }[];
143
+ }) {
144
+ return (
145
+ <div className="overflow-x-auto" tabIndex={0}>
146
+ <table aria-label={label} className="w-full min-w-[30rem] table-fixed border-collapse text-left text-sm">
147
+ <thead className="border-base-300 text-base-700 border-b text-xs">
148
+ <tr>
149
+ {columns.map((column) => (
150
+ <th key={column} scope="col" className="px-4 py-3 font-medium sm:px-5">
151
+ {column}
152
+ </th>
153
+ ))}
154
+ </tr>
155
+ </thead>
156
+ <tbody className="divide-base-300 divide-y">
157
+ {rows.map((row) => (
158
+ <tr key={row.key}>
159
+ {row.cells.map((cell, index) => (
160
+ <td key={index} className="px-4 py-3 align-top wrap-anywhere sm:px-5">
161
+ {cell}
162
+ </td>
163
+ ))}
164
+ </tr>
165
+ ))}
166
+ </tbody>
167
+ </table>
168
+ </div>
169
+ );
170
+ }
171
+
172
+ export const PropertySheet = Object.assign(PropertySheetRoot, {
173
+ Collapsible: PropertySheetCollapsible,
174
+ Note: PropertySheetNote,
175
+ Rows: PropertySheetRows,
176
+ Table: PropertySheetTable,
177
+ Tags: PropertySheetTags,
178
+ });
179
+
180
+ export type { PropertySheetRow, PropertySheetTag };
@@ -0,0 +1,47 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import { SkeletonLoader } from '../feedback/SkeletonLoader';
4
+
5
+ /** Encodes locally; the value is never sent to a QR service. */
6
+ export function QrCode({ label, value }: { label: string; value: string }) {
7
+ const [encoded, setEncoded] = useState<{ source: string | null; value: string }>();
8
+
9
+ useEffect(() => {
10
+ let active = true;
11
+
12
+ void import('qrcode-generator')
13
+ .then(({ default: createQrCode }) => {
14
+ try {
15
+ const code = createQrCode(0, 'M');
16
+
17
+ code.addData(value, 'Byte');
18
+ code.make();
19
+
20
+ if (active) setEncoded({ source: code.createDataURL(4), value });
21
+ } catch {
22
+ // The copyable value remains available if it exceeds QR capacity.
23
+ if (active) setEncoded({ source: null, value });
24
+ }
25
+ })
26
+ .catch(() => {
27
+ // The copyable value remains usable if this optional chunk fails to load.
28
+ if (active) setEncoded({ source: null, value });
29
+ });
30
+
31
+ return () => {
32
+ active = false;
33
+ };
34
+ }, [value]);
35
+
36
+ if (encoded?.value !== value) {
37
+ return (
38
+ <SkeletonLoader label={label}>
39
+ <SkeletonLoader.Shape presentation="artwork" />
40
+ </SkeletonLoader>
41
+ );
42
+ }
43
+
44
+ return encoded.source ? (
45
+ <img alt={label} src={encoded.source} className="block w-full max-w-sm rounded-lg bg-white" />
46
+ ) : null;
47
+ }
@@ -0,0 +1,34 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import { tabbable } from '../foundations/KeyboardFocus';
4
+
5
+ export function RadioChoice({
6
+ name,
7
+ checked,
8
+ onChange,
9
+ children,
10
+ trailing,
11
+ }: {
12
+ name: string;
13
+ checked: boolean;
14
+ onChange: () => void;
15
+ children: ReactNode;
16
+ trailing?: ReactNode;
17
+ }) {
18
+ return (
19
+ <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">
20
+ <label className="flex min-w-0 flex-1 cursor-pointer items-center gap-3 px-4 py-3 has-disabled:cursor-default">
21
+ <input
22
+ {...tabbable}
23
+ type="radio"
24
+ name={name}
25
+ checked={checked}
26
+ onChange={onChange}
27
+ className="accent-primary size-4 shrink-0"
28
+ />
29
+ <span className="min-w-0 flex-1">{children}</span>
30
+ </label>
31
+ {trailing ? <div className="flex shrink-0 items-center gap-3 pr-4">{trailing}</div> : null}
32
+ </div>
33
+ );
34
+ }
@@ -0,0 +1,76 @@
1
+ import { CheckIcon } from 'lucide-react';
2
+
3
+ import { Link } from '../typography/Link';
4
+ import { Text } from '../typography/Typography';
5
+
6
+ /** The sources' own marks and colors, as the Apple apps draw them. Anything else reads by its name. */
7
+ function ratingMark(source: string) {
8
+ switch (source.trim().toLowerCase()) {
9
+ case 'trakt':
10
+ return {
11
+ name: 'Trakt',
12
+ label: 'Trakt',
13
+ mark: (
14
+ <span className="inline-flex size-5 items-center justify-center rounded-full bg-[#ed1c24] text-white [&>svg]:size-3 [&>svg]:stroke-[3]">
15
+ <CheckIcon />
16
+ </span>
17
+ ),
18
+ };
19
+ case 'imdb':
20
+ return {
21
+ name: 'IMDb',
22
+ mark: (
23
+ <span className="inline-flex h-5 items-center rounded-sm bg-[#f5c518] px-1 text-xs font-black text-black">
24
+ IMDb
25
+ </span>
26
+ ),
27
+ };
28
+ case 'rotten tomatoes critics':
29
+ return { name: 'Tomatometer', mark: <span>🍅</span> };
30
+ case 'rotten tomatoes audience':
31
+ return { name: 'Popcornmeter', mark: <span>🍿</span> };
32
+ default:
33
+ return { name: source, label: source, mark: null };
34
+ }
35
+ }
36
+
37
+ /** A provider's mark and its score, linked to the original rating. */
38
+ export function RatingLink({
39
+ source,
40
+ value,
41
+ scale,
42
+ href,
43
+ }: {
44
+ source: string;
45
+ /** The score as it reads, such as "6.5" or "57%". */
46
+ value: string;
47
+ /** The scale shown after the score, such as "/ 10"; none for percentages. */
48
+ scale?: string;
49
+ href: string;
50
+ }) {
51
+ const { name, label, mark } = ratingMark(source);
52
+
53
+ return (
54
+ <Link
55
+ href={href}
56
+ external
57
+ aria-label={[name, value, scale].filter(Boolean).join(' ')}
58
+ className="max-w-full gap-1.5"
59
+ >
60
+ {mark ? <span aria-hidden="true">{mark}</span> : null}
61
+ {label ? (
62
+ <Text as="span" variant="caption" aria-hidden="true">
63
+ {label}
64
+ </Text>
65
+ ) : null}
66
+ <Text as="span" variant="label" className="tabular-nums">
67
+ {value}
68
+ </Text>
69
+ {scale ? (
70
+ <Text as="span" variant="caption" tone="muted" className="tabular-nums">
71
+ {scale}
72
+ </Text>
73
+ ) : null}
74
+ </Link>
75
+ );
76
+ }